44package cbor
55
66import (
7+ "bytes"
78 "encoding"
89 "encoding/base64"
910 "encoding/binary"
@@ -883,6 +884,11 @@ type DecOptions struct {
883884 // BinaryUnmarshaler specifies how to decode into types that implement
884885 // encoding.BinaryUnmarshaler.
885886 BinaryUnmarshaler BinaryUnmarshalerMode
887+
888+ // JSONUnmarshalerTranscoder sets the transcoding scheme used to unmarshal types that
889+ // implement json.Unmarshaler but do not also implement cbor.Unmarshaler. If nil, decoding
890+ // behavior is not influenced by whether or not a type implements json.Unmarshaler.
891+ JSONUnmarshalerTranscoder Transcoder
886892}
887893
888894// DecMode returns DecMode with immutable options and no tags (safe for concurrency).
@@ -1096,32 +1102,33 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore
10961102 }
10971103
10981104 dm := decMode {
1099- dupMapKey : opts .DupMapKey ,
1100- timeTag : opts .TimeTag ,
1101- maxNestedLevels : opts .MaxNestedLevels ,
1102- maxArrayElements : opts .MaxArrayElements ,
1103- maxMapPairs : opts .MaxMapPairs ,
1104- indefLength : opts .IndefLength ,
1105- tagsMd : opts .TagsMd ,
1106- intDec : opts .IntDec ,
1107- mapKeyByteString : opts .MapKeyByteString ,
1108- extraReturnErrors : opts .ExtraReturnErrors ,
1109- defaultMapType : opts .DefaultMapType ,
1110- utf8 : opts .UTF8 ,
1111- fieldNameMatching : opts .FieldNameMatching ,
1112- bigIntDec : opts .BigIntDec ,
1113- defaultByteStringType : opts .DefaultByteStringType ,
1114- byteStringToString : opts .ByteStringToString ,
1115- fieldNameByteString : opts .FieldNameByteString ,
1116- unrecognizedTagToAny : opts .UnrecognizedTagToAny ,
1117- timeTagToAny : opts .TimeTagToAny ,
1118- simpleValues : simpleValues ,
1119- nanDec : opts .NaN ,
1120- infDec : opts .Inf ,
1121- byteStringToTime : opts .ByteStringToTime ,
1122- byteStringExpectedFormat : opts .ByteStringExpectedFormat ,
1123- bignumTag : opts .BignumTag ,
1124- binaryUnmarshaler : opts .BinaryUnmarshaler ,
1105+ dupMapKey : opts .DupMapKey ,
1106+ timeTag : opts .TimeTag ,
1107+ maxNestedLevels : opts .MaxNestedLevels ,
1108+ maxArrayElements : opts .MaxArrayElements ,
1109+ maxMapPairs : opts .MaxMapPairs ,
1110+ indefLength : opts .IndefLength ,
1111+ tagsMd : opts .TagsMd ,
1112+ intDec : opts .IntDec ,
1113+ mapKeyByteString : opts .MapKeyByteString ,
1114+ extraReturnErrors : opts .ExtraReturnErrors ,
1115+ defaultMapType : opts .DefaultMapType ,
1116+ utf8 : opts .UTF8 ,
1117+ fieldNameMatching : opts .FieldNameMatching ,
1118+ bigIntDec : opts .BigIntDec ,
1119+ defaultByteStringType : opts .DefaultByteStringType ,
1120+ byteStringToString : opts .ByteStringToString ,
1121+ fieldNameByteString : opts .FieldNameByteString ,
1122+ unrecognizedTagToAny : opts .UnrecognizedTagToAny ,
1123+ timeTagToAny : opts .TimeTagToAny ,
1124+ simpleValues : simpleValues ,
1125+ nanDec : opts .NaN ,
1126+ infDec : opts .Inf ,
1127+ byteStringToTime : opts .ByteStringToTime ,
1128+ byteStringExpectedFormat : opts .ByteStringExpectedFormat ,
1129+ bignumTag : opts .BignumTag ,
1130+ binaryUnmarshaler : opts .BinaryUnmarshaler ,
1131+ jsonUnmarshalerTranscoder : opts .JSONUnmarshalerTranscoder ,
11251132 }
11261133
11271134 return & dm , nil
@@ -1174,33 +1181,34 @@ type DecMode interface {
11741181}
11751182
11761183type decMode struct {
1177- tags tagProvider
1178- dupMapKey DupMapKeyMode
1179- timeTag DecTagMode
1180- maxNestedLevels int
1181- maxArrayElements int
1182- maxMapPairs int
1183- indefLength IndefLengthMode
1184- tagsMd TagsMode
1185- intDec IntDecMode
1186- mapKeyByteString MapKeyByteStringMode
1187- extraReturnErrors ExtraDecErrorCond
1188- defaultMapType reflect.Type
1189- utf8 UTF8Mode
1190- fieldNameMatching FieldNameMatchingMode
1191- bigIntDec BigIntDecMode
1192- defaultByteStringType reflect.Type
1193- byteStringToString ByteStringToStringMode
1194- fieldNameByteString FieldNameByteStringMode
1195- unrecognizedTagToAny UnrecognizedTagToAnyMode
1196- timeTagToAny TimeTagToAnyMode
1197- simpleValues * SimpleValueRegistry
1198- nanDec NaNMode
1199- infDec InfMode
1200- byteStringToTime ByteStringToTimeMode
1201- byteStringExpectedFormat ByteStringExpectedFormatMode
1202- bignumTag BignumTagMode
1203- binaryUnmarshaler BinaryUnmarshalerMode
1184+ tags tagProvider
1185+ dupMapKey DupMapKeyMode
1186+ timeTag DecTagMode
1187+ maxNestedLevels int
1188+ maxArrayElements int
1189+ maxMapPairs int
1190+ indefLength IndefLengthMode
1191+ tagsMd TagsMode
1192+ intDec IntDecMode
1193+ mapKeyByteString MapKeyByteStringMode
1194+ extraReturnErrors ExtraDecErrorCond
1195+ defaultMapType reflect.Type
1196+ utf8 UTF8Mode
1197+ fieldNameMatching FieldNameMatchingMode
1198+ bigIntDec BigIntDecMode
1199+ defaultByteStringType reflect.Type
1200+ byteStringToString ByteStringToStringMode
1201+ fieldNameByteString FieldNameByteStringMode
1202+ unrecognizedTagToAny UnrecognizedTagToAnyMode
1203+ timeTagToAny TimeTagToAnyMode
1204+ simpleValues * SimpleValueRegistry
1205+ nanDec NaNMode
1206+ infDec InfMode
1207+ byteStringToTime ByteStringToTimeMode
1208+ byteStringExpectedFormat ByteStringExpectedFormatMode
1209+ bignumTag BignumTagMode
1210+ binaryUnmarshaler BinaryUnmarshalerMode
1211+ jsonUnmarshalerTranscoder Transcoder
12041212}
12051213
12061214var defaultDecMode , _ = DecOptions {}.decMode ()
@@ -1215,32 +1223,33 @@ func (dm *decMode) DecOptions() DecOptions {
12151223 }
12161224
12171225 return DecOptions {
1218- DupMapKey : dm .dupMapKey ,
1219- TimeTag : dm .timeTag ,
1220- MaxNestedLevels : dm .maxNestedLevels ,
1221- MaxArrayElements : dm .maxArrayElements ,
1222- MaxMapPairs : dm .maxMapPairs ,
1223- IndefLength : dm .indefLength ,
1224- TagsMd : dm .tagsMd ,
1225- IntDec : dm .intDec ,
1226- MapKeyByteString : dm .mapKeyByteString ,
1227- ExtraReturnErrors : dm .extraReturnErrors ,
1228- DefaultMapType : dm .defaultMapType ,
1229- UTF8 : dm .utf8 ,
1230- FieldNameMatching : dm .fieldNameMatching ,
1231- BigIntDec : dm .bigIntDec ,
1232- DefaultByteStringType : dm .defaultByteStringType ,
1233- ByteStringToString : dm .byteStringToString ,
1234- FieldNameByteString : dm .fieldNameByteString ,
1235- UnrecognizedTagToAny : dm .unrecognizedTagToAny ,
1236- TimeTagToAny : dm .timeTagToAny ,
1237- SimpleValues : simpleValues ,
1238- NaN : dm .nanDec ,
1239- Inf : dm .infDec ,
1240- ByteStringToTime : dm .byteStringToTime ,
1241- ByteStringExpectedFormat : dm .byteStringExpectedFormat ,
1242- BignumTag : dm .bignumTag ,
1243- BinaryUnmarshaler : dm .binaryUnmarshaler ,
1226+ DupMapKey : dm .dupMapKey ,
1227+ TimeTag : dm .timeTag ,
1228+ MaxNestedLevels : dm .maxNestedLevels ,
1229+ MaxArrayElements : dm .maxArrayElements ,
1230+ MaxMapPairs : dm .maxMapPairs ,
1231+ IndefLength : dm .indefLength ,
1232+ TagsMd : dm .tagsMd ,
1233+ IntDec : dm .intDec ,
1234+ MapKeyByteString : dm .mapKeyByteString ,
1235+ ExtraReturnErrors : dm .extraReturnErrors ,
1236+ DefaultMapType : dm .defaultMapType ,
1237+ UTF8 : dm .utf8 ,
1238+ FieldNameMatching : dm .fieldNameMatching ,
1239+ BigIntDec : dm .bigIntDec ,
1240+ DefaultByteStringType : dm .defaultByteStringType ,
1241+ ByteStringToString : dm .byteStringToString ,
1242+ FieldNameByteString : dm .fieldNameByteString ,
1243+ UnrecognizedTagToAny : dm .unrecognizedTagToAny ,
1244+ TimeTagToAny : dm .timeTagToAny ,
1245+ SimpleValues : simpleValues ,
1246+ NaN : dm .nanDec ,
1247+ Inf : dm .infDec ,
1248+ ByteStringToTime : dm .byteStringToTime ,
1249+ ByteStringExpectedFormat : dm .byteStringExpectedFormat ,
1250+ BignumTag : dm .bignumTag ,
1251+ BinaryUnmarshaler : dm .binaryUnmarshaler ,
1252+ JSONUnmarshalerTranscoder : dm .jsonUnmarshalerTranscoder ,
12441253 }
12451254}
12461255
@@ -1467,6 +1476,14 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin
14671476
14681477 case specialTypeUnexportedUnmarshalerIface :
14691478 return d .parseToUnexportedUnmarshaler (v )
1479+
1480+ case specialTypeJSONUnmarshalerIface :
1481+ // This special type implies that the type does not also implement
1482+ // cbor.Umarshaler.
1483+ if d .dm .jsonUnmarshalerTranscoder == nil {
1484+ break
1485+ }
1486+ return d .parseToJSONUnmarshaler (v )
14701487 }
14711488 }
14721489
@@ -1832,6 +1849,31 @@ func (d *decoder) parseToUnexportedUnmarshaler(v reflect.Value) error {
18321849 return errors .New ("cbor: failed to assert " + v .Type ().String () + " as cbor.unmarshaler" )
18331850}
18341851
1852+ // parseToJSONUnmarshaler parses CBOR data to be transcoded to JSON and passed to the value's
1853+ // implementation of the json.Unmarshaler interface. It assumes data is well-formed, and does not
1854+ // perform bounds checking.
1855+ func (d * decoder ) parseToJSONUnmarshaler (v reflect.Value ) error {
1856+ if d .nextCBORNil () && v .Kind () == reflect .Pointer && v .IsNil () {
1857+ d .skip ()
1858+ return nil
1859+ }
1860+
1861+ if v .Kind () != reflect .Pointer && v .CanAddr () {
1862+ v = v .Addr ()
1863+ }
1864+ if u , ok := v .Interface ().(jsonUnmarshaler ); ok {
1865+ start := d .off
1866+ d .skip ()
1867+ var jbuffer bytes.Buffer
1868+ if err := d .dm .jsonUnmarshalerTranscoder .Transcode (& jbuffer , bytes .NewReader (d .data [start :d .off ])); err != nil {
1869+ return & TranscodeError {err : err , rtype : v .Type (), source : "cbor" , target : "json" }
1870+ }
1871+ return u .UnmarshalJSON (jbuffer .Bytes ())
1872+ }
1873+ d .skip ()
1874+ return errors .New ("cbor: failed to assert " + v .Type ().String () + " as json.Unmarshaler" )
1875+ }
1876+
18351877// parse parses CBOR data and returns value in default Go type.
18361878// It assumes data is well-formed, and does not perform bounds checking.
18371879func (d * decoder ) parse (skipSelfDescribedTag bool ) (any , error ) { //nolint:gocyclo
@@ -2988,13 +3030,16 @@ func (d *decoder) nextCBORNil() bool {
29883030 return d .data [d .off ] == 0xf6 || d .data [d .off ] == 0xf7
29893031}
29903032
3033+ type jsonUnmarshaler interface { UnmarshalJSON ([]byte ) error }
3034+
29913035var (
29923036 typeIntf = reflect .TypeOf ([]any (nil )).Elem ()
29933037 typeTime = reflect .TypeOf (time.Time {})
29943038 typeBigInt = reflect .TypeOf (big.Int {})
29953039 typeUnmarshaler = reflect .TypeOf ((* Unmarshaler )(nil )).Elem ()
29963040 typeUnexportedUnmarshaler = reflect .TypeOf ((* unmarshaler )(nil )).Elem ()
29973041 typeBinaryUnmarshaler = reflect .TypeOf ((* encoding .BinaryUnmarshaler )(nil )).Elem ()
3042+ typeJSONUnmarshaler = reflect .TypeOf ((* jsonUnmarshaler )(nil )).Elem ()
29983043 typeString = reflect .TypeOf ("" )
29993044 typeByteSlice = reflect .TypeOf ([]byte (nil ))
30003045)
0 commit comments