44package cbor
55
66import (
7+ "bytes"
78 "encoding"
89 "encoding/base64"
910 "encoding/binary"
@@ -906,6 +907,11 @@ type DecOptions struct {
906907 // TextUnmarshaler specifies how to decode into types that implement
907908 // encoding.TextUnmarshaler.
908909 TextUnmarshaler TextUnmarshalerMode
910+
911+ // JSONUnmarshalerTranscoder sets the transcoding scheme used to unmarshal types that
912+ // implement json.Unmarshaler but do not also implement cbor.Unmarshaler. If nil, decoding
913+ // behavior is not influenced by whether or not a type implements json.Unmarshaler.
914+ JSONUnmarshalerTranscoder Transcoder
909915}
910916
911917// DecMode returns DecMode with immutable options and no tags (safe for concurrency).
@@ -1123,33 +1129,34 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore
11231129 }
11241130
11251131 dm := decMode {
1126- dupMapKey : opts .DupMapKey ,
1127- timeTag : opts .TimeTag ,
1128- maxNestedLevels : opts .MaxNestedLevels ,
1129- maxArrayElements : opts .MaxArrayElements ,
1130- maxMapPairs : opts .MaxMapPairs ,
1131- indefLength : opts .IndefLength ,
1132- tagsMd : opts .TagsMd ,
1133- intDec : opts .IntDec ,
1134- mapKeyByteString : opts .MapKeyByteString ,
1135- extraReturnErrors : opts .ExtraReturnErrors ,
1136- defaultMapType : opts .DefaultMapType ,
1137- utf8 : opts .UTF8 ,
1138- fieldNameMatching : opts .FieldNameMatching ,
1139- bigIntDec : opts .BigIntDec ,
1140- defaultByteStringType : opts .DefaultByteStringType ,
1141- byteStringToString : opts .ByteStringToString ,
1142- fieldNameByteString : opts .FieldNameByteString ,
1143- unrecognizedTagToAny : opts .UnrecognizedTagToAny ,
1144- timeTagToAny : opts .TimeTagToAny ,
1145- simpleValues : simpleValues ,
1146- nanDec : opts .NaN ,
1147- infDec : opts .Inf ,
1148- byteStringToTime : opts .ByteStringToTime ,
1149- byteStringExpectedFormat : opts .ByteStringExpectedFormat ,
1150- bignumTag : opts .BignumTag ,
1151- binaryUnmarshaler : opts .BinaryUnmarshaler ,
1152- textUnmarshaler : opts .TextUnmarshaler ,
1132+ dupMapKey : opts .DupMapKey ,
1133+ timeTag : opts .TimeTag ,
1134+ maxNestedLevels : opts .MaxNestedLevels ,
1135+ maxArrayElements : opts .MaxArrayElements ,
1136+ maxMapPairs : opts .MaxMapPairs ,
1137+ indefLength : opts .IndefLength ,
1138+ tagsMd : opts .TagsMd ,
1139+ intDec : opts .IntDec ,
1140+ mapKeyByteString : opts .MapKeyByteString ,
1141+ extraReturnErrors : opts .ExtraReturnErrors ,
1142+ defaultMapType : opts .DefaultMapType ,
1143+ utf8 : opts .UTF8 ,
1144+ fieldNameMatching : opts .FieldNameMatching ,
1145+ bigIntDec : opts .BigIntDec ,
1146+ defaultByteStringType : opts .DefaultByteStringType ,
1147+ byteStringToString : opts .ByteStringToString ,
1148+ fieldNameByteString : opts .FieldNameByteString ,
1149+ unrecognizedTagToAny : opts .UnrecognizedTagToAny ,
1150+ timeTagToAny : opts .TimeTagToAny ,
1151+ simpleValues : simpleValues ,
1152+ nanDec : opts .NaN ,
1153+ infDec : opts .Inf ,
1154+ byteStringToTime : opts .ByteStringToTime ,
1155+ byteStringExpectedFormat : opts .ByteStringExpectedFormat ,
1156+ bignumTag : opts .BignumTag ,
1157+ binaryUnmarshaler : opts .BinaryUnmarshaler ,
1158+ textUnmarshaler : opts .TextUnmarshaler ,
1159+ jsonUnmarshalerTranscoder : opts .JSONUnmarshalerTranscoder ,
11531160 }
11541161
11551162 return & dm , nil
@@ -1202,34 +1209,35 @@ type DecMode interface {
12021209}
12031210
12041211type decMode struct {
1205- tags tagProvider
1206- dupMapKey DupMapKeyMode
1207- timeTag DecTagMode
1208- maxNestedLevels int
1209- maxArrayElements int
1210- maxMapPairs int
1211- indefLength IndefLengthMode
1212- tagsMd TagsMode
1213- intDec IntDecMode
1214- mapKeyByteString MapKeyByteStringMode
1215- extraReturnErrors ExtraDecErrorCond
1216- defaultMapType reflect.Type
1217- utf8 UTF8Mode
1218- fieldNameMatching FieldNameMatchingMode
1219- bigIntDec BigIntDecMode
1220- defaultByteStringType reflect.Type
1221- byteStringToString ByteStringToStringMode
1222- fieldNameByteString FieldNameByteStringMode
1223- unrecognizedTagToAny UnrecognizedTagToAnyMode
1224- timeTagToAny TimeTagToAnyMode
1225- simpleValues * SimpleValueRegistry
1226- nanDec NaNMode
1227- infDec InfMode
1228- byteStringToTime ByteStringToTimeMode
1229- byteStringExpectedFormat ByteStringExpectedFormatMode
1230- bignumTag BignumTagMode
1231- binaryUnmarshaler BinaryUnmarshalerMode
1232- textUnmarshaler TextUnmarshalerMode
1212+ tags tagProvider
1213+ dupMapKey DupMapKeyMode
1214+ timeTag DecTagMode
1215+ maxNestedLevels int
1216+ maxArrayElements int
1217+ maxMapPairs int
1218+ indefLength IndefLengthMode
1219+ tagsMd TagsMode
1220+ intDec IntDecMode
1221+ mapKeyByteString MapKeyByteStringMode
1222+ extraReturnErrors ExtraDecErrorCond
1223+ defaultMapType reflect.Type
1224+ utf8 UTF8Mode
1225+ fieldNameMatching FieldNameMatchingMode
1226+ bigIntDec BigIntDecMode
1227+ defaultByteStringType reflect.Type
1228+ byteStringToString ByteStringToStringMode
1229+ fieldNameByteString FieldNameByteStringMode
1230+ unrecognizedTagToAny UnrecognizedTagToAnyMode
1231+ timeTagToAny TimeTagToAnyMode
1232+ simpleValues * SimpleValueRegistry
1233+ nanDec NaNMode
1234+ infDec InfMode
1235+ byteStringToTime ByteStringToTimeMode
1236+ byteStringExpectedFormat ByteStringExpectedFormatMode
1237+ bignumTag BignumTagMode
1238+ binaryUnmarshaler BinaryUnmarshalerMode
1239+ textUnmarshaler TextUnmarshalerMode
1240+ jsonUnmarshalerTranscoder Transcoder
12331241}
12341242
12351243var defaultDecMode , _ = DecOptions {}.decMode ()
@@ -1244,33 +1252,34 @@ func (dm *decMode) DecOptions() DecOptions {
12441252 }
12451253
12461254 return DecOptions {
1247- DupMapKey : dm .dupMapKey ,
1248- TimeTag : dm .timeTag ,
1249- MaxNestedLevels : dm .maxNestedLevels ,
1250- MaxArrayElements : dm .maxArrayElements ,
1251- MaxMapPairs : dm .maxMapPairs ,
1252- IndefLength : dm .indefLength ,
1253- TagsMd : dm .tagsMd ,
1254- IntDec : dm .intDec ,
1255- MapKeyByteString : dm .mapKeyByteString ,
1256- ExtraReturnErrors : dm .extraReturnErrors ,
1257- DefaultMapType : dm .defaultMapType ,
1258- UTF8 : dm .utf8 ,
1259- FieldNameMatching : dm .fieldNameMatching ,
1260- BigIntDec : dm .bigIntDec ,
1261- DefaultByteStringType : dm .defaultByteStringType ,
1262- ByteStringToString : dm .byteStringToString ,
1263- FieldNameByteString : dm .fieldNameByteString ,
1264- UnrecognizedTagToAny : dm .unrecognizedTagToAny ,
1265- TimeTagToAny : dm .timeTagToAny ,
1266- SimpleValues : simpleValues ,
1267- NaN : dm .nanDec ,
1268- Inf : dm .infDec ,
1269- ByteStringToTime : dm .byteStringToTime ,
1270- ByteStringExpectedFormat : dm .byteStringExpectedFormat ,
1271- BignumTag : dm .bignumTag ,
1272- BinaryUnmarshaler : dm .binaryUnmarshaler ,
1273- TextUnmarshaler : dm .textUnmarshaler ,
1255+ DupMapKey : dm .dupMapKey ,
1256+ TimeTag : dm .timeTag ,
1257+ MaxNestedLevels : dm .maxNestedLevels ,
1258+ MaxArrayElements : dm .maxArrayElements ,
1259+ MaxMapPairs : dm .maxMapPairs ,
1260+ IndefLength : dm .indefLength ,
1261+ TagsMd : dm .tagsMd ,
1262+ IntDec : dm .intDec ,
1263+ MapKeyByteString : dm .mapKeyByteString ,
1264+ ExtraReturnErrors : dm .extraReturnErrors ,
1265+ DefaultMapType : dm .defaultMapType ,
1266+ UTF8 : dm .utf8 ,
1267+ FieldNameMatching : dm .fieldNameMatching ,
1268+ BigIntDec : dm .bigIntDec ,
1269+ DefaultByteStringType : dm .defaultByteStringType ,
1270+ ByteStringToString : dm .byteStringToString ,
1271+ FieldNameByteString : dm .fieldNameByteString ,
1272+ UnrecognizedTagToAny : dm .unrecognizedTagToAny ,
1273+ TimeTagToAny : dm .timeTagToAny ,
1274+ SimpleValues : simpleValues ,
1275+ NaN : dm .nanDec ,
1276+ Inf : dm .infDec ,
1277+ ByteStringToTime : dm .byteStringToTime ,
1278+ ByteStringExpectedFormat : dm .byteStringExpectedFormat ,
1279+ BignumTag : dm .bignumTag ,
1280+ BinaryUnmarshaler : dm .binaryUnmarshaler ,
1281+ TextUnmarshaler : dm .textUnmarshaler ,
1282+ JSONUnmarshalerTranscoder : dm .jsonUnmarshalerTranscoder ,
12741283 }
12751284}
12761285
@@ -1497,6 +1506,14 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin
14971506
14981507 case specialTypeUnexportedUnmarshalerIface :
14991508 return d .parseToUnexportedUnmarshaler (v )
1509+
1510+ case specialTypeJSONUnmarshalerIface :
1511+ // This special type implies that the type does not also implement
1512+ // cbor.Umarshaler.
1513+ if d .dm .jsonUnmarshalerTranscoder == nil {
1514+ break
1515+ }
1516+ return d .parseToJSONUnmarshaler (v )
15001517 }
15011518 }
15021519
@@ -1862,6 +1879,32 @@ func (d *decoder) parseToUnexportedUnmarshaler(v reflect.Value) error {
18621879 return errors .New ("cbor: failed to assert " + v .Type ().String () + " as cbor.unmarshaler" )
18631880}
18641881
1882+ // parseToJSONUnmarshaler parses CBOR data to be transcoded to JSON and passed to the value's
1883+ // implementation of the json.Unmarshaler interface. It assumes data is well-formed, and does not
1884+ // perform bounds checking.
1885+ func (d * decoder ) parseToJSONUnmarshaler (v reflect.Value ) error {
1886+ if d .nextCBORNil () && v .Kind () == reflect .Pointer && v .IsNil () {
1887+ d .skip ()
1888+ return nil
1889+ }
1890+
1891+ if v .Kind () != reflect .Pointer && v .CanAddr () {
1892+ v = v .Addr ()
1893+ }
1894+ if u , ok := v .Interface ().(jsonUnmarshaler ); ok {
1895+ start := d .off
1896+ d .skip ()
1897+ e := getEncodeBuffer ()
1898+ defer putEncodeBuffer (e )
1899+ if err := d .dm .jsonUnmarshalerTranscoder .Transcode (e , bytes .NewReader (d .data [start :d .off ])); err != nil {
1900+ return & TranscodeError {err : err , rtype : v .Type (), sourceFormat : "cbor" , targetFormat : "json" }
1901+ }
1902+ return u .UnmarshalJSON (e .Bytes ())
1903+ }
1904+ d .skip ()
1905+ return errors .New ("cbor: failed to assert " + v .Type ().String () + " as json.Unmarshaler" )
1906+ }
1907+
18651908// parse parses CBOR data and returns value in default Go type.
18661909// It assumes data is well-formed, and does not perform bounds checking.
18671910func (d * decoder ) parse (skipSelfDescribedTag bool ) (any , error ) { //nolint:gocyclo
@@ -3018,6 +3061,8 @@ func (d *decoder) nextCBORNil() bool {
30183061 return d .data [d .off ] == 0xf6 || d .data [d .off ] == 0xf7
30193062}
30203063
3064+ type jsonUnmarshaler interface { UnmarshalJSON ([]byte ) error }
3065+
30213066var (
30223067 typeIntf = reflect .TypeOf ([]any (nil )).Elem ()
30233068 typeTime = reflect .TypeOf (time.Time {})
@@ -3026,6 +3071,7 @@ var (
30263071 typeUnexportedUnmarshaler = reflect .TypeOf ((* unmarshaler )(nil )).Elem ()
30273072 typeBinaryUnmarshaler = reflect .TypeOf ((* encoding .BinaryUnmarshaler )(nil )).Elem ()
30283073 typeTextUnmarshaler = reflect .TypeOf ((* encoding .TextUnmarshaler )(nil )).Elem ()
3074+ typeJSONUnmarshaler = reflect .TypeOf ((* jsonUnmarshaler )(nil )).Elem ()
30293075 typeString = reflect .TypeOf ("" )
30303076 typeByteSlice = reflect .TypeOf ([]byte (nil ))
30313077)
0 commit comments