Browse Source

encoding/cbor: add a custom tag to the example

Laytan Laats 1 year ago
parent
commit
6ab559437a
1 changed files with 33 additions and 5 deletions
  1. 33 5
      core/encoding/cbor/doc.odin

+ 33 - 5
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