From 6ab559437a49cfc6ac6c6e56657af8341431bc4f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 8 Jul 2024 01:01:11 +0200 Subject: [PATCH] encoding/cbor: add a custom tag to the example --- core/encoding/cbor/doc.odin | 38 ++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/core/encoding/cbor/doc.odin b/core/encoding/cbor/doc.odin index 937b1b61b..b3fa36130 100644 --- a/core/encoding/cbor/doc.odin +++ b/core/encoding/cbor/doc.odin @@ -77,8 +77,11 @@ You can look at the default tags provided for pointers on how these implementati Example: package main + import "base:intrinsics" + import "core:encoding/cbor" import "core:fmt" + import "core:reflect" import "core:time" Possibilities :: union { @@ -93,9 +96,32 @@ Example: ignore_this: ^Data `cbor:"-"`, // Ignored by implementation. renamed: f32 `cbor:"renamed :)"`, // Renamed when encoded. my_union: Possibilities, // Union support. + + my_raw: [8]u32 `cbor_tag:"raw"`, // Custom tag that just writes the value as bytes. } main :: proc() { + // Example custom tag implementation that instead of breaking down all parts, + // just writes the value as a big byte blob. This is an advanced feature but very powerful. + RAW_TAG_NR :: 200 + cbor.tag_register_number({ + marshal = proc(_: ^cbor.Tag_Implementation, e: cbor.Encoder, v: any) -> cbor.Marshal_Error { + cbor._encode_u8(e.writer, RAW_TAG_NR, .Tag) or_return + return cbor.err_conv(cbor._encode_bytes(e, reflect.as_bytes(v))) + }, + unmarshal = proc(_: ^cbor.Tag_Implementation, d: cbor.Decoder, _: cbor.Tag_Number, v: any) -> (cbor.Unmarshal_Error) { + hdr := cbor._decode_header(d.reader) or_return + maj, add := cbor._header_split(hdr) + if maj != .Bytes { + return .Bad_Tag_Value + } + + bytes := cbor.err_conv(cbor._decode_bytes(d, add, maj)) or_return + intrinsics.mem_copy_non_overlapping(v.data, raw_data(bytes), len(bytes)) + return nil + }, + }, RAW_TAG_NR, "raw") + now := time.Time{_nsec = 1701117968 * 1e9} data := Data{ @@ -105,21 +131,22 @@ Example: ignore_this = &Data{}, renamed = 123123.125, my_union = 3, + my_raw = {1=1, 2=2, 3=3}, } - + // Marshal the struct into binary CBOR. binary, err := cbor.marshal(data, cbor.ENCODE_FULLY_DETERMINISTIC) - assert(err == nil) + fmt.assertf(err == nil, "marshal error: %v", err) defer delete(binary) - + // Decode the binary data into a `cbor.Value`. decoded, derr := cbor.decode(string(binary)) - assert(derr == nil) + fmt.assertf(derr == nil, "decode error: %v", derr) defer cbor.destroy(decoded) // Turn the CBOR into a human readable representation defined as the diagnostic format in [[RFC 8949 Section 8;https://www.rfc-editor.org/rfc/rfc8949.html#name-diagnostic-notation]]. diagnosis, eerr := cbor.to_diagnostic_format(decoded) - assert(eerr == nil) + fmt.assertf(eerr == nil, "to diagnostic error: %v", eerr) defer delete(diagnosis) fmt.println(diagnosis) @@ -127,6 +154,7 @@ Example: Output: { + "my_raw": 200(h'00001000200030000000000000000000'), "my_union": 1010([ "int", 3