Merge remote-tracking branch 'offical/master'

This commit is contained in:
2025-10-12 00:52:35 -04:00
272 changed files with 4127 additions and 2670 deletions
+15 -14
View File
@@ -1,19 +1,20 @@
// Base32 encoding/decoding implementation as specified in RFC 4648.
// [[ More; https://www.rfc-editor.org/rfc/rfc4648.html ]]
/*
`Base32` encoding and decoding, as specified in [[ RFC 4648; https://www.rfc-editor.org/rfc/rfc4648.html ]].
A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`.
If none is supplied it just uses the standard Base32 alphabet.
In case your specific version does not use padding, you may
truncate it from the encoded output.
Error represents errors that can occur during base32 decoding operations.
As per RFC 4648:
- Section 3.3: Invalid character handling
- Section 3.2: Padding requirements
- Section 6: Base32 encoding specifics (including block size requirements)
*/
package encoding_base32
// @note(zh): Encoding utility for Base32
// A secondary param can be used to supply a custom alphabet to
// @link(encode) and a matching decoding table to @link(decode).
// If none is supplied it just uses the standard Base32 alphabet.
// In case your specific version does not use padding, you may
// truncate it from the encoded output.
// Error represents errors that can occur during base32 decoding operations.
// As per RFC 4648:
// - Section 3.3: Invalid character handling
// - Section 3.2: Padding requirements
// - Section 6: Base32 encoding specifics (including block size requirements)
Error :: enum {
None,
Invalid_Character, // Input contains characters outside the specified alphabet
-228
View File
@@ -1,228 +0,0 @@
#+test
package encoding_base32
import "core:testing"
import "core:bytes"
@(test)
test_base32_decode_valid :: proc(t: ^testing.T) {
// RFC 4648 Section 10 - Test vectors
cases := [?]struct {
input, expected: string,
}{
{"", ""},
{"MY======", "f"},
{"MZXQ====", "fo"},
{"MZXW6===", "foo"},
{"MZXW6YQ=", "foob"},
{"MZXW6YTB", "fooba"},
{"MZXW6YTBOI======", "foobar"},
}
for c in cases {
output, err := decode(c.input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.None)
expected := transmute([]u8)c.expected
if output != nil {
testing.expect(t, bytes.equal(output, expected))
} else {
testing.expect(t, len(c.expected) == 0)
}
}
}
@(test)
test_base32_encode :: proc(t: ^testing.T) {
// RFC 4648 Section 10 - Test vectors
cases := [?]struct {
input, expected: string,
}{
{"", ""},
{"f", "MY======"},
{"fo", "MZXQ===="},
{"foo", "MZXW6==="},
{"foob", "MZXW6YQ="},
{"fooba", "MZXW6YTB"},
{"foobar", "MZXW6YTBOI======"},
}
for c in cases {
output := encode(transmute([]byte)c.input)
defer delete(output)
testing.expect(t, output == c.expected)
}
}
@(test)
test_base32_decode_invalid :: proc(t: ^testing.T) {
// Section 3.3 - Non-alphabet characters
{
// Characters outside alphabet
input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7)
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Invalid_Character)
}
{
// Lowercase not allowed
input := "mzxq===="
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Invalid_Character)
}
// Section 3.2 - Padding requirements
{
// Padding must only be at end
input := "MZ=Q===="
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Malformed_Input)
}
{
// Missing padding
input := "MZXQ" // Should be MZXQ====
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Malformed_Input)
}
{
// Incorrect padding length
input := "MZXQ=" // Needs 4 padding chars
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Malformed_Input)
}
{
// Too much padding
input := "MY=========" // Extra padding chars
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Malformed_Input)
}
// Section 6 - Base32 block size requirements
{
// Single character (invalid block)
input := "M"
output, err := decode(input)
if output != nil {
defer delete(output)
}
testing.expect_value(t, err, Error.Invalid_Length)
}
}
@(test)
test_base32_roundtrip :: proc(t: ^testing.T) {
cases := [?]string{
"",
"f",
"fo",
"foo",
"foob",
"fooba",
"foobar",
}
for input in cases {
encoded := encode(transmute([]byte)input)
defer delete(encoded)
decoded, err := decode(encoded)
if decoded != nil {
defer delete(decoded)
}
testing.expect_value(t, err, Error.None)
testing.expect(t, bytes.equal(decoded, transmute([]byte)input))
}
}
@(test)
test_base32_custom_alphabet :: proc(t: ^testing.T) {
custom_enc_table := [32]byte{
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
}
custom_dec_table: [256]u8
for i := 0; i < len(custom_enc_table); i += 1 {
custom_dec_table[custom_enc_table[i]] = u8(i)
}
/*
custom_dec_table := [256]u8{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00-0x0f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10-0x1f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2f
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0x30-0x3f ('0'-'9')
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f ('A'-'O')
25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50-0x5f ('P'-'V')
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x6f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x7f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x8f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x9f
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0-0xaf
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0-0xbf
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0-0xcf
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0-0xdf
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0-0xef
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0-0xff
}
*/
custom_validate :: proc(c: byte) -> bool {
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(PADDING)
}
cases := [?]struct {
input: string,
enc_expected: string,
}{
{"f", "CO======"},
{"fo", "CPNG===="},
{"foo", "CPNMU==="},
}
for c in cases {
// Test encoding
encoded := encode(transmute([]byte)c.input, custom_enc_table)
defer delete(encoded)
testing.expect(t, encoded == c.enc_expected)
// Test decoding
decoded, err := decode(encoded, custom_dec_table, custom_validate)
defer if decoded != nil {
delete(decoded)
}
testing.expect_value(t, err, Error.None)
testing.expect(t, bytes.equal(decoded, transmute([]byte)c.input))
}
// Test invalid character detection
{
input := "WXY=====" // Contains chars not in our alphabet
output, err := decode(input, custom_dec_table, custom_validate)
if output != nil {
delete(output)
}
testing.expect_value(t, err, Error.Invalid_Character)
}
}
+9 -7
View File
@@ -1,16 +1,18 @@
/*
`Base64` encoding and decoding.
A secondary param can be used to supply a custom alphabet to `encode` and a matching decoding table to `decode`.
If none is supplied it just uses the standard Base64 alphabet.
In case your specific version does not use padding, you may
truncate it from the encoded output.
*/
package encoding_base64
import "core:io"
import "core:mem"
import "core:strings"
// @note(zh): Encoding utility for Base64
// A secondary param can be used to supply a custom alphabet to
// @link(encode) and a matching decoding table to @link(decode).
// If none is supplied it just uses the standard Base64 alphabet.
// Incase your specific version does not use padding, you may
// truncate it from the encoded output.
ENC_TABLE := [64]byte {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+3 -3
View File
@@ -1,5 +1,6 @@
/*
Package cbor encodes, decodes, marshals and unmarshals types from/into RCF 8949 compatible CBOR binary.
Encodes and decodes types from/into [[ RCF 8949; https://www.rfc-editor.org/rfc/rfc8949.html ]] compatible `CBOR` binary.
Also provided are conversion to and from JSON and the CBOR diagnostic format.
**Allocations:**
@@ -165,5 +166,4 @@ Output:
"str": "Hello, World!"
}
*/
package encoding_cbor
package encoding_cbor
+1 -2
View File
@@ -1,6 +1,5 @@
/*
package csv reads and writes comma-separated values (CSV) files.
This package supports the format described in [[ RFC 4180; https://tools.ietf.org/html/rfc4180.html ]]
Reader and writer for comma-separated values (`CSV`) files, per [[ RFC 4180 ; https://tools.ietf.org/html/rfc4180.html ]].
Example:
package main
+1 -2
View File
@@ -1,6 +1,5 @@
/*
Package endian implements a simple translation between bytes and numbers with
specific endian encodings.
A simple translation between bytes and numbers with specific endian encodings.
Example:
buf: [100]u8
+9 -9
View File
@@ -1,13 +1,5 @@
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
/*
A unicode entity encoder/decoder.
Encode and decode `rune`s to/from a Unicode `&entity;`.
This code has several procedures to map unicode runes to/from different textual encodings.
- SGML/XML/HTML entity
@@ -21,6 +13,14 @@
*/
package encoding_unicode_entity
/*
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
import "core:unicode/utf8"
import "core:unicode"
import "core:strings"
+1
View File
@@ -1,3 +1,4 @@
// Encoding and decoding of hex-encoded binary, e.g. `0x23` -> `#`.
package encoding_hex
import "core:io"
+2 -1
View File
@@ -1,5 +1,6 @@
/*
Implementation of the HxA 3D asset format
Eskil Steenberg's `HxA` 3D asset interchange format.
HxA is a interchangeable graphics asset format.
Designed by Eskil Steenberg. @quelsolaar / eskil 'at' obsession 'dot' se / www.quelsolaar.com
+1
View File
@@ -1,3 +1,4 @@
// Reader and writer for a variant of the `.ini` file format with `key = value` entries in `[sections]`.
package encoding_ini
import "base:runtime"
+5 -1
View File
@@ -176,7 +176,11 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
return .Unsupported_Type
case runtime.Type_Info_Pointer:
return .Unsupported_Type
if v.id == typeid_of(Null) {
io.write_string(w, "null") or_return
} else {
return .Unsupported_Type
}
case runtime.Type_Info_Multi_Pointer:
return .Unsupported_Type
+12 -9
View File
@@ -1,14 +1,13 @@
package encoding_json
import "core:strings"
/*
JSON
Encoding and decoding JSON in strict `JSON`, [[ JSON5 ; https://json5.org/ ]] and [[ BitSquid ; https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html ]] variants.
Using one of these `Specification`s.
JSON
strict JSON
JSON5
JSON5
pure superset of JSON and valid JavaScript
https://json5.org/
* Object keys may be an ECMAScript 5.1 IdentifierName.
* Objects may have a single trailing comma.
* Arrays may have a single trailing comma.
@@ -21,17 +20,21 @@ import "core:strings"
* Numbers may begin with an explicit plus sign.
* Single and multi-line comments are allowed.
* Additional white space characters are allowed.
MJSON
pure superset of JSON5, may not be valid JavaScript
https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html
* All the same features as JSON5 plus extras.
* Assume an object definition at the root level (no need to surround entire file with { } ).
* Commas are optional, using comma insertion rules with newlines.
* Quotes around object keys are optional if the keys are valid identifiers.
* : can be replaced with =
*/
package encoding_json
import "core:strings"
Specification :: enum {
JSON,
JSON5, // https://json5.org/
+1 -2
View File
@@ -1,6 +1,5 @@
/*
package uuid implements Universally Unique Identifiers according to the
standard originally outlined in RFC 4122 with additions from RFC 9562.
Universally Unique Identifiers (`UUID`) according to [[ RFC 4122 ; https://tools.ietf.org/html/rfc4122.html ]], with additions from [[ RFC 9562 ; https://tools.ietf.org/html/rfc9562.html ]].
The UUIDs are textually represented and read in the following string format:
`00000000-0000-v000-V000-000000000000`
+2 -3
View File
@@ -1,7 +1,6 @@
/*
package uuid/legacy implements versions 3 and 5 of UUID generation, both of
which are using hashing algorithms (MD5 and SHA1, respectively) that are known
these days to no longer be secure.
Versions 3 and 5 of `UUID` generation, both of which use legacy (`MD5` + `SHA1`) hashes.
Those are known these days to no longer be secure.
*/
package uuid_legacy
+2 -4
View File
@@ -1,7 +1,5 @@
/*
Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others.
Author of this Odin package: Jeroen van Rijn
`LEB128` variable integer encoding and decoding, as used by `DWARF` & `DEX` files.
Example:
package main
@@ -24,4 +22,4 @@ Example:
fmt.printf("Decoded as %v, using %v byte%v\n", decoded_val, decode_size, "" if decode_size == 1 else "s")
}
*/
package encoding_varint
package encoding_varint
+2 -2
View File
@@ -1,3 +1,5 @@
package encoding_varint
/*
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
@@ -6,8 +8,6 @@
Jeroen van Rijn: Initial implementation.
*/
package encoding_varint
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
// Instead we'll set limits on the values we'll encode/decode
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`.
+4 -4
View File
@@ -1,7 +1,7 @@
/*
XML 1.0 / 1.1 parser
A parser for a useful subset of the `XML` specification.
A from-scratch XML implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]].
A from-scratch `XML` implementation, loosely modelled on the [[ spec; https://www.w3.org/TR/2006/REC-xml11-20060816 ]].
Features:
- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage.
@@ -11,8 +11,8 @@ Caveats:
- We do NOT support HTML in this package, as that may or may not be valid XML.
If it works, great. If it doesn't, that's not considered a bug.
- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences.
- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options.
- We do NOT support `UTF-16`. If you have a `UTF-16` XML file, please convert it to `UTF-8` first. Also, our condolences.
- `<[!ELEMENT` and `<[!ATTLIST` are not supported, and will be either ignored or return an error depending on the parser options.
MAYBE:
- XML writer?
+3 -3
View File
@@ -1,4 +1,7 @@
package encoding_xml
/*
An XML 1.0 / 1.1 parser
2021-2022 Jeroen van Rijn <nom@duclavier.com>.
available under Odin's BSD-3 license.
@@ -6,9 +9,6 @@
- Jeroen van Rijn: Initial implementation.
*/
package encoding_xml
// An XML 1.0 / 1.1 parser
import "core:bytes"
import "core:encoding/entity"
import "base:intrinsics"