Browse Source

encoding/cbor: deterministically store bit sets as big endian

Laytan Laats 1 năm trước cách đây
mục cha
commit
317931a3c5

+ 0 - 18
core/encoding/cbor/cbor.odin

@@ -675,21 +675,3 @@ _i128_to_uint :: proc(v: i128) -> (u: u64, m: Major, err: Encode_Data_Error) {
 	u, err = _u128_to_u64(u128(v))
 	return
 }
-
-@(private)
-is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool {
-	if ti == nil {
-		return false
-	}
-	t := runtime.type_info_base(ti)
-	#partial switch info in t.variant {
-	case runtime.Type_Info_Integer:
-		switch info.endianness {
-		case .Platform: return false
-		case .Little:   return ODIN_ENDIAN != .Little
-		case .Big:      return ODIN_ENDIAN != .Big
-		}
-	}
-	return false
-}
-

+ 2 - 1
core/encoding/cbor/marshal.odin

@@ -541,7 +541,8 @@ marshal_into_encoder :: proc(e: Encoder, v: any) -> (err: Marshal_Error) {
 		return marshal_into(e, any{v.data, info.base.id})
 
 	case runtime.Type_Info_Bit_Set:
-		do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying)
+		// Store bit_set as big endian just like the protocol.
+		do_byte_swap := !reflect.bit_set_is_big_endian(v)
 		switch ti.size * 8 {
 		case  0:
 			return _encode_u8(e.writer, 0)

+ 6 - 7
core/encoding/cbor/unmarshal.odin

@@ -856,12 +856,11 @@ _assign_int :: proc(val: any, i: $T) -> bool {
 	case uintptr: dst = uintptr(i)
 	case:
 		ti := type_info_of(v.id)
-		do_byte_swap := is_bit_set_different_endian_to_platform(ti)
-		#partial switch info in ti.variant {
-		case runtime.Type_Info_Bit_Set:
+		if _, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok {
+			do_byte_swap := !reflect.bit_set_is_big_endian(v)
 			switch ti.size * 8 {
-			case  0:
-			case  8:
+			case 0: // no-op.
+			case 8:
 				x := (^u8)(v.data)
 				x^ = u8(i)
 			case 16:
@@ -876,9 +875,9 @@ _assign_int :: proc(val: any, i: $T) -> bool {
 			case:
 				panic("unknown bit_size size")
 			}
-		case:
-			return false
+			return true
 		}
+		return false
 	}
 	return true
 }

+ 21 - 0
core/reflect/reflect.odin

@@ -934,6 +934,27 @@ set_union_value :: proc(dst: any, value: any) -> bool {
 	panic("expected a union to reflect.set_union_variant_typeid")
 }
 
+@(require_results)
+bit_set_is_big_endian :: proc(value: any, loc := #caller_location) -> bool {
+	if value == nil { return ODIN_ENDIAN == .Big }
+	
+	ti := runtime.type_info_base(type_info_of(value.id))
+	if info, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok {
+		if info.underlying == nil { return ODIN_ENDIAN == .Big }
+
+		underlying_ti := runtime.type_info_base(info.underlying)
+		if underlying_info, uok := underlying_ti.variant.(runtime.Type_Info_Integer); uok {
+			switch underlying_info.endianness {
+			case .Platform: return ODIN_ENDIAN == .Big
+			case .Little:   return false
+			case .Big:      return true
+			}
+		}
+
+		return ODIN_ENDIAN == .Big
+	}
+	panic("expected a bit_set to reflect.bit_set_is_big_endian", loc)
+}
 
 
 @(require_results)

+ 1 - 1
tests/core/encoding/cbor/test_core_cbor.odin

@@ -251,7 +251,7 @@ test_marshalling :: proc(t: ^testing.T) {
 	],
 	"cstr": "Hellnope",
 	"ennie": 0,
-	"ennieb": 2,
+	"ennieb": 512,
 	"iamint": -256,
 	"important": "!",
 	"my_bytes": h'',