mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-24 14:45:00 -07:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
@@ -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,3 +1,4 @@
|
||||
// Encoding and decoding of hex-encoded binary, e.g. `0x23` -> `#`.
|
||||
package encoding_hex
|
||||
|
||||
import "core:io"
|
||||
|
||||
@@ -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,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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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`
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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`.
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user