@@ -73,35 +73,15 @@ func (v *Value) UnmarshalCBOR(data []byte) error {
7373 case CborTagMap :
7474 return v .processMap (tmpTag .Content )
7575 default :
76- // Parse the tag value via our custom Value object to handle problem types
77- tmpValue := Value {}
78- if _ , err := Decode (tmpTag .Content , & tmpValue ); err != nil {
79- return err
80- }
81- // These tag numbers correspond to the Enumerated Alternative Data Items notable CBOR tags. These
82- // are often used in Plutus script datums
83- // https://www.ietf.org/archive/id/draft-bormann-cbor-notable-tags-07.html#name-enumerated-alternative-data
84- if tmpTag .Number >= 121 && tmpTag .Number <= 127 {
85- // Alternatives 0-6
86- v .value = Constructor {
87- constructor : uint (tmpTag .Number - 121 ),
88- value : & tmpValue ,
89- }
90- } else if tmpTag .Number >= 1280 && tmpTag .Number <= 1400 {
91- // Alternatives 7-127
92- v .value = Constructor {
93- constructor : uint (tmpTag .Number - 1280 + 7 ),
94- value : & tmpValue ,
95- }
96- } else if tmpTag .Number == 101 {
97- // Alternatives 128+
98- newValue := Value {
99- value : tmpValue .Value ().([]interface {})[1 ],
100- }
101- v .value = Constructor {
102- constructor : tmpValue .Value ().([]interface {})[0 ].(uint ),
103- value : & newValue ,
76+ if (tmpTag .Number >= CborTagAlternative1Min && tmpTag .Number <= CborTagAlternative1Max ) ||
77+ (tmpTag .Number >= CborTagAlternative2Min && tmpTag .Number <= CborTagAlternative2Max ) ||
78+ tmpTag .Number == CborTagAlternative3 {
79+ // Constructors/alternatives
80+ var tmpConstr Constructor
81+ if _ , err := Decode (data , & tmpConstr ); err != nil {
82+ return err
10483 }
84+ v .value = tmpConstr
10585 } else {
10686 // Fall back to standard CBOR tag parsing for our supported types
10787 var tmpTagDecode interface {}
@@ -263,6 +243,18 @@ type Constructor struct {
263243 value * Value
264244}
265245
246+ func NewConstructor (constructor uint , value any ) Constructor {
247+ c := Constructor {
248+ constructor : constructor ,
249+ }
250+ if value != nil {
251+ c .value = & Value {
252+ value : value ,
253+ }
254+ }
255+ return c
256+ }
257+
266258func (v Constructor ) Constructor () uint {
267259 return v .constructor
268260}
@@ -271,6 +263,63 @@ func (v Constructor) Fields() []any {
271263 return v .value .Value ().([]any )
272264}
273265
266+ func (c Constructor ) FieldsCbor () []byte {
267+ return c .value .Cbor ()
268+ }
269+
270+ func (c * Constructor ) UnmarshalCBOR (data []byte ) error {
271+ // Parse as a raw tag to get number and nested CBOR data
272+ tmpTag := RawTag {}
273+ if _ , err := Decode (data , & tmpTag ); err != nil {
274+ return err
275+ }
276+ // Parse the tag value via our custom Value object to handle problem types
277+ tmpValue := Value {}
278+ if _ , err := Decode (tmpTag .Content , & tmpValue ); err != nil {
279+ return err
280+ }
281+ if tmpTag .Number >= CborTagAlternative1Min && tmpTag .Number <= CborTagAlternative1Max {
282+ // Alternatives 0-6
283+ c .constructor = uint (tmpTag .Number - CborTagAlternative1Min )
284+ c .value = & tmpValue
285+ } else if tmpTag .Number >= CborTagAlternative2Min && tmpTag .Number <= CborTagAlternative2Max {
286+ // Alternatives 7-127
287+ c .constructor = uint (tmpTag .Number - CborTagAlternative2Min + 7 )
288+ c .value = & tmpValue
289+ } else if tmpTag .Number == CborTagAlternative3 {
290+ // Alternatives 128+
291+ tmpValues := tmpValue .Value ().([]any )
292+ c .constructor = uint (tmpValues [0 ].(uint64 ))
293+ newValue := Value {
294+ value : tmpValues [1 ],
295+ }
296+ c .value = & newValue
297+ } else {
298+ return fmt .Errorf ("unsupported tag: %d" , tmpTag .Number )
299+ }
300+ return nil
301+ }
302+
303+ func (c Constructor ) MarshalCBOR () ([]byte , error ) {
304+ var tmpTag Tag
305+ if c .constructor <= 6 {
306+ // Alternatives 0-6
307+ tmpTag .Number = uint64 (c .constructor + CborTagAlternative1Min )
308+ tmpTag .Content = c .value .Value ()
309+ } else if c .constructor >= 7 && c .constructor <= 127 {
310+ // Alternatives 7-127
311+ tmpTag .Number = uint64 (c .constructor + CborTagAlternative2Min - 7 )
312+ tmpTag .Content = c .value .Value ()
313+ } else if c .constructor >= 128 {
314+ tmpTag .Number = CborTagAlternative3
315+ tmpTag .Content = []any {
316+ c .constructor ,
317+ c .value .Value (),
318+ }
319+ }
320+ return Encode (& tmpTag )
321+ }
322+
274323func (v Constructor ) MarshalJSON () ([]byte , error ) {
275324 tmpJson := fmt .Sprintf (`{"constructor":%d,"fields":[` , v .constructor )
276325 tmpList := [][]byte {}
0 commit comments