@@ -358,12 +358,11 @@ func msgpackUnmarshalUnknown(dec *msgpack.Decoder, typ Type, path *AttributePath
358358 // If the extension is zero or one-length, this is a wholly unknown value with no
359359 // refinements.
360360
361- // TODO: Previous implementations always skipped the body, should we preserve that?
362361 if extLen > 0 {
363362 // Skip the body
364363 err = dec .Skip ()
365364 if err != nil {
366- return Value {}, path .NewErrorf ("error skipping extension byte : %w" , err )
365+ return Value {}, path .NewErrorf ("error skipping extension body : %w" , err )
367366 }
368367 }
369368
@@ -372,33 +371,29 @@ func msgpackUnmarshalUnknown(dec *msgpack.Decoder, typ Type, path *AttributePath
372371
373372 // Check if the extension is the designated cty unknown refinement code
374373 if typeCode != unknownWithRefinementsExt {
375- // TODO: cleanup error
376374 return Value {}, path .NewErrorf ("unsupported extension type" )
377375 }
378376
379377 if extLen > 1024 {
380- // A refinement description greater than 1 kiB is unreasonable and
381- // might be an abusive attempt to allocate large amounts of memory
382- // in a system consuming this input.
383- return Value {}, path .NewErrorf ("unsupported extension type" )
378+ // cty refinements cannot be greater than 1 kiB
379+ return Value {}, path .NewErrorf ("unknown value refinement too large" )
384380 }
385381
382+ // Unknown value refinements are always a msgpack-encoded map
386383 body := make ([]byte , extLen )
387384 _ , err = io .ReadAtLeast (dec .Buffered (), body , len (body ))
388385 if err != nil {
389- return Value {}, path .NewErrorf ("failed to read msgpack extension body: %s" , err )
386+ return Value {}, path .NewErrorf ("error reading msgpack extension body: %s" , err )
390387 }
391388
392389 rfnDec := msgpack .NewDecoder (bytes .NewReader (body ))
393390 entryCount , err := rfnDec .DecodeMapLen ()
394391 if err != nil {
395- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: not a map" )
392+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: not a map" )
396393 }
397394
398- // Ignore all refinements for DynamicPseudoType for now, since go-cty also ignores this.
399- //
400- // We know that's invalid today but we might find a way to support it in the future and
401- // if so will want to introduce that in a backward-compatible way.
395+ // cty ignores all refinements for DynamicPseudoType at the moment, this allows them to be introduced
396+ // in the future in a backward compatible way.
402397 if typ .Is (DynamicPseudoType ) {
403398 return NewValue (typ , UnknownValue ), nil
404399 }
@@ -409,69 +404,64 @@ func msgpackUnmarshalUnknown(dec *msgpack.Decoder, typ Type, path *AttributePath
409404 for i := 0 ; i < entryCount ; i ++ {
410405 keyCode , err := rfnDec .DecodeInt64 ()
411406 if err != nil {
412- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: non-integer key in map" )
407+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: non-integer key in map" )
413408 }
414409
415410 switch keyCode := refinement .Key (keyCode ); keyCode {
416411 case refinement .KeyNullness :
417412 isNull , err := rfnDec .DecodeBool ()
418413 if err != nil {
419- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: null refinement is not boolean" )
414+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: null refinement is not boolean" )
420415 }
421- // The presence of this key means we're refining the null-ness one
422- // way or another. If nullness is unknown then this key should not
423- // be present at all.
424- //
425- // isNull should always be false if this refinement is present, but to match Terraform's support
416+
417+ // isNull should always be false if this refinement is present, but to match cty's support
426418 // of this encoding, we will pass along the value. If isNull is true, then the value should not be
427419 // unknown with refinements, it should be a known null value.
428420 newRefinements [keyCode ] = refinement .NewNullness (isNull )
429421 case refinement .KeyStringPrefix :
430422 if ! typ .Is (String ) {
431- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: string prefix refinement for non-string type" )
423+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: string prefix refinement for non-string type" )
432424 }
433425 prefix , err := rfnDec .DecodeString ()
434426 if err != nil {
435- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: string prefix refinement is not string" )
427+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: string prefix refinement is not string" )
436428 }
437429 if ! utf8 .ValidString (prefix ) {
438- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: string prefix refinement is not valid UTF-8" )
430+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: string prefix refinement is not valid UTF-8" )
439431 }
440432
441- // TODO: If terraform doesn't support an empty string prefix, then neither should we, potentially return an error here.
442-
443433 newRefinements [keyCode ] = refinement .NewStringPrefix (prefix )
444434 case refinement .KeyNumberLowerBound , refinement .KeyNumberUpperBound :
445435 if ! typ .Is (Number ) {
446- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement for non-number type" )
436+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement for non-number type" )
447437 }
448438
449- // We know these refinements are a tuple of [number, bool] so we can re-use the msgpack decoding logic on this refinement
439+ // Numeric bound refinements are always a tuple of [number, bool] so we re-use the msgpack decoding logic on this refinement.
450440 tfValBound , err := msgpackUnmarshal (rfnDec , Tuple {ElementTypes : []Type {Number , Bool }}, path )
451441 if err != nil || tfValBound .IsNull () || ! tfValBound .IsKnown () {
452- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement must be [number, bool] tuple" )
442+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement must be [number, bool] tuple" )
453443 }
454444
455- tupleVal := []Value {}
445+ tupleVal := make ( []Value , 2 )
456446 err = tfValBound .As (& tupleVal )
457447 if err != nil {
458- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement tuple value conversion failed: %w" , err )
448+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement tuple value conversion failed: %w" , err )
459449 }
460450
461451 if len (tupleVal ) != 2 {
462- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement tuple value conversion failed: expected 2 elements, got %d elements" , len (tupleVal ))
452+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement tuple value conversion failed: expected 2 elements, got %d elements" , len (tupleVal ))
463453 }
464454
465455 var boundVal * big.Float
466456 err = tupleVal [0 ].As (& boundVal )
467457 if err != nil {
468- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement bound value conversion failed: %w" , err )
458+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement bound value conversion failed: %w" , err )
469459 }
470460
471461 var inclusiveVal bool
472462 err = tupleVal [1 ].As (& inclusiveVal )
473463 if err != nil {
474- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: numeric bound refinement inclusive value conversion failed: %w" , err )
464+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: numeric bound refinement inclusive value conversion failed: %w" , err )
475465 }
476466
477467 if keyCode == refinement .KeyNumberLowerBound {
@@ -481,12 +471,12 @@ func msgpackUnmarshalUnknown(dec *msgpack.Decoder, typ Type, path *AttributePath
481471 }
482472 case refinement .KeyCollectionLengthLowerBound , refinement .KeyCollectionLengthUpperBound :
483473 if ! typ .Is (List {}) && ! typ .Is (Map {}) && ! typ .Is (Set {}) {
484- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: length bound refinement for non-collection type" )
474+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: length bound refinement for non-collection type" )
485475 }
486476
487477 boundVal , err := rfnDec .DecodeInt ()
488478 if err != nil {
489- return Value {}, path .NewErrorf ("failed to decode msgpack extension body: length bound refinement must be integer" )
479+ return Value {}, path .NewErrorf ("error decoding msgpack extension body: length bound refinement must be integer" )
490480 }
491481
492482 if keyCode == refinement .KeyCollectionLengthLowerBound {
@@ -499,7 +489,7 @@ func msgpackUnmarshalUnknown(dec *msgpack.Decoder, typ Type, path *AttributePath
499489 if err != nil {
500490 return Value {}, path .NewErrorf ("error skipping unknown extension body, keycode = %d: %w" , keyCode , err )
501491 }
502- // We don't want to error here, as go- cty could introduce new refinements that we'd
492+ // We don't want to error here, as cty could introduce new refinements that we'd
503493 // want to just ignore until this logic is updated
504494 continue
505495 }
@@ -576,7 +566,7 @@ func marshalUnknownValue(val Value, typ Type, p *AttributePath, enc *msgpack.Enc
576566 return p .NewErrorf ("error encoding Nullness value refinement key: %w" , err )
577567 }
578568
579- // It shouldn't be possible for an unknown value to be definitely null (i.e. nullness .value = true),
569+ // It shouldn't be possible for an unknown value to be definitely null (i.e. Nullness .value = true),
580570 // as that should be represented by a known null value instead. This encoding is in place to be compliant
581571 // with Terraform's encoding which uses a definitely null refinement to collapse into a known null value.
582572 err = refnEnc .EncodeBool (data .Nullness ())
@@ -595,14 +585,13 @@ func marshalUnknownValue(val Value, typ Type, p *AttributePath, enc *msgpack.Enc
595585 return p .NewErrorf ("error encoding StringPrefix value refinement: unexpected refinement data of type %T" , refnVal )
596586 }
597587
598- if rawPrefix := data .PrefixValue (); rawPrefix != "" {
599- // Matching go- cty for the max prefix length allowed here
588+ if prefix := data .PrefixValue (); prefix != "" {
589+ // Matching cty for the max prefix length allowed here.
600590 //
601591 // This ensures the total size of the refinements blob does not exceed the limit
602592 // set by the decoder (1024).
603593 maxPrefixLength := 256
604- prefix := rawPrefix
605- if len (rawPrefix ) > maxPrefixLength {
594+ if len (prefix ) > maxPrefixLength {
606595 prefix = prefix [:maxPrefixLength - 1 ]
607596 }
608597
@@ -629,10 +618,8 @@ func marshalUnknownValue(val Value, typ Type, p *AttributePath, enc *msgpack.Enc
629618 return p .NewErrorf ("error encoding NumberLowerBound value refinement: unexpected refinement data of type %T" , refnVal )
630619 }
631620
632- // TODO: should check this isn't negative infinity? To match go-cty
621+ // Numeric bound refinements are always a tuple of [number, bool] so we re-use the msgpack encoding logic on this refinement.
633622 boundTfType := Tuple {ElementTypes : []Type {Number , Bool }}
634-
635- // TODO: Do we need to do this? Kind of nasty
636623 boundTfVal := NewValue (
637624 boundTfType ,
638625 []Value {
@@ -660,10 +647,8 @@ func marshalUnknownValue(val Value, typ Type, p *AttributePath, enc *msgpack.Enc
660647 return p .NewErrorf ("error encoding NumberUpperBound value refinement: unexpected refinement data of type %T" , refnVal )
661648 }
662649
663- // TODO: should check this isn't positive infinity? To match go-cty
650+ // Numeric bound refinements are always a tuple of [number, bool] so we re-use the msgpack encoding logic on this refinement.
664651 boundTfType := Tuple {ElementTypes : []Type {Number , Bool }}
665-
666- // TODO: Do we need to do this? Kind of nasty
667652 boundTfVal := NewValue (
668653 boundTfType ,
669654 []Value {
@@ -735,25 +720,26 @@ func marshalUnknownValue(val Value, typ Type, p *AttributePath, enc *msgpack.Enc
735720 return nil
736721 }
737722
738- // If we have at least one refinement to encode then we'll use the new
739- // representation of unknown values where refinement information is in the
740- // extension payload.
723+ // Encode all of the unknown value refinements
741724 var lenBuf bytes.Buffer
742725 lenEnc := msgpack .NewEncoder (& lenBuf )
743726 lenEnc .EncodeMapLen (mapLen ) //nolint
744727
745728 err := enc .EncodeExtHeader (unknownWithRefinementsExt , lenBuf .Len ()+ refnBuf .Len ())
746729 if err != nil {
747- return p .NewErrorf ("failed to write unknown value : %s" , err )
730+ return p .NewErrorf ("error encoding UnknownValue with refinements : %s" , err )
748731 }
732+
749733 _ , err = enc .Writer ().Write (lenBuf .Bytes ())
750734 if err != nil {
751- return p .NewErrorf ("failed to write unknown value : %s" , err )
735+ return p .NewErrorf ("error encoding UnknownValue with refinements : %s" , err )
752736 }
737+
753738 _ , err = enc .Writer ().Write (refnBuf .Bytes ())
754739 if err != nil {
755- return p .NewErrorf ("failed to write unknown value : %s" , err )
740+ return p .NewErrorf ("error encoding UnknownValue with refinements : %s" , err )
756741 }
742+
757743 return nil
758744}
759745
0 commit comments