@@ -422,16 +422,23 @@ private void generateDecodePrimitive(
422422 private void generateRangeCheckPrimitive (
423423 final StringBuilder sb ,
424424 final String varName ,
425- final Token token )
425+ final Token token ,
426+ final Boolean isOptional )
426427 {
428+ // Note that constant encoding is a property of the type
429+ // and so works on signal/encoding tokens but optionality is
430+ // a property of the field and so is not set on the encoding token.
431+ // For this reason we can use the token to check for constancy
432+ // but pass in optionality as a parameter
433+
427434 // Constant values don't need checking
428435 if (token .isConstantEncoding ())
429436 {
430437 return ;
431438 }
432439
433440 // If this field is unknown then we have nothing to check
434- // Otherwise do a The Min,MaxValue checks (possibly for arrays)
441+ // Otherwise do the Min,MaxValue checks (possibly for arrays)
435442 this .imports .add ("fmt" );
436443 if (token .arrayLength () > 1 )
437444 {
@@ -449,9 +456,22 @@ private void generateRangeCheckPrimitive(
449456 }
450457 else
451458 {
459+ // Optional fields can be NullValue which may be outside the
460+ // range of Min->Max so we need a special case.
461+ // Structured this way for go fmt sanity on both cases.
462+ final String check ;
463+ if (isOptional )
464+ {
465+ check = "\t \t if %1$s != %1$sNullValue() && (%1$s < %1$sMinValue() || %1$s > %1$sMaxValue()) {\n " ;
466+ }
467+ else
468+ {
469+ check = "\t \t if %1$s < %1$sMinValue() || %1$s > %1$sMaxValue() {\n " ;
470+ }
471+
452472 sb .append (String .format (
453473 "\t if %1$sInActingVersion(actingVersion) {\n " +
454- " \t \t if %1$s < %1$sMinValue() || %1$s > %1$sMaxValue() { \n " +
474+ check +
455475 "\t \t \t return fmt.Errorf(\" Range check failed on %1$s " +
456476 "(%%d < %%d > %%d)\" , %1$sMinValue(), %1$s, %1$sMaxValue())\n " +
457477 "\t \t }\n " +
@@ -468,40 +488,56 @@ private void generateRangeCheckPrimitive(
468488 }
469489 }
470490
471- private void generateInitPrimitive (
491+ private void generateOptionalInitPrimitive (
472492 final StringBuilder sb ,
473493 final String varName ,
474494 final Token token )
475495 {
496+ final Encoding encoding = token .encoding ();
497+
498+ // Optional items get initialized to their NullValue
499+ sb .append (String .format (
500+ "\t %1$s = %2$s\n " ,
501+ varName ,
502+ generateNullValueLiteral (encoding .primitiveType (), encoding )));
503+ }
504+
505+ private void generateConstantInitPrimitive (
506+ final StringBuilder sb ,
507+ final String varName ,
508+ final Token token )
509+ {
510+ final Encoding encoding = token .encoding ();
511+
476512 // Decode of a constant is simply assignment
477513 if (token .isConstantEncoding ())
478514 {
479515 // if primitiveType="char" this is a character array
480- if (token . encoding () .primitiveType () == CHAR )
516+ if (encoding .primitiveType () == CHAR )
481517 {
482- if (token . encoding () .constValue ().size () > 1 )
518+ if (encoding .constValue ().size () > 1 )
483519 {
484520 // constValue is a string
485521 sb .append (String .format (
486522 "\t copy(%1$s[:], \" %2$s\" )\n " ,
487523 varName ,
488- token . encoding () .constValue ()));
524+ encoding .constValue ()));
489525 }
490526 else
491527 {
492528 // constValue is a char
493529 sb .append (String .format (
494530 "\t %1$s[0] = %2$s\n " ,
495531 varName ,
496- token . encoding () .constValue ()));
532+ encoding .constValue ()));
497533 }
498534 }
499535 else
500536 {
501537 sb .append (String .format (
502538 "\t %1$s = %2$s\n " ,
503539 varName ,
504- generateLiteral (token . encoding () .primitiveType (), token . encoding () .constValue ().toString ())));
540+ generateLiteral (encoding .primitiveType (), encoding .constValue ().toString ())));
505541 }
506542 }
507543 }
@@ -652,17 +688,28 @@ private int generateEncodeDecode(
652688 encode .append (generateEncodeOffset (gap , "" ));
653689 decode .append (generateDecodeOffset (gap , "" ));
654690 currentOffset += signalToken .encodedLength () + gap ;
691+ final String primitive = Character .toString (varName ) + "." + propertyName ;
655692
656- // Encode of a constant is a nullop
657- if (!signalToken .isConstantEncoding ())
693+ // Encode of a constant is a nullop and we want to
694+ // initialize constant values.
695+ if (signalToken .isConstantEncoding ())
696+ {
697+ generateConstantInitPrimitive (init , primitive , signalToken );
698+ }
699+ else
658700 {
659701 generateEncodePrimitive (encode , varName , formatPropertyName (signalToken .name ()), signalToken );
702+ }
660703
704+ // Optional tokens also get initialized
705+ if (signalToken .isOptionalEncoding ())
706+ {
707+ generateOptionalInitPrimitive (init , primitive , signalToken );
661708 }
662- final String primitive = Character . toString ( varName ) + "." + propertyName ;
709+
663710 generateDecodePrimitive (decode , primitive , signalToken );
664- generateRangeCheckPrimitive (rangeCheck , primitive , signalToken );
665- generateInitPrimitive ( init , primitive , signalToken );
711+ generateRangeCheckPrimitive (rangeCheck , primitive , signalToken , signalToken . isOptionalEncoding () );
712+
666713 break ;
667714
668715 case BEGIN_GROUP :
@@ -1004,16 +1051,29 @@ private int generateFieldEncodeDecode(
10041051 gap = encodingToken .offset () - currentOffset ;
10051052 encode .append (generateEncodeOffset (gap , "" ));
10061053 decode .append (generateDecodeOffset (gap , "" ));
1054+ final String primitive = Character .toString (varName ) + "." + propertyName ;
10071055
1008- // Encode of a constant is a nullop
1009- if (!encodingToken .isConstantEncoding ())
1056+ // Encode of a constant is a nullop and we want to
1057+ // initialize constant values.
1058+ // (note: constancy is determined by the type's token)
1059+ if (encodingToken .isConstantEncoding ())
1060+ {
1061+ generateConstantInitPrimitive (init , primitive , encodingToken );
1062+ }
1063+ else
10101064 {
10111065 generateEncodePrimitive (encode , varName , formatPropertyName (signalToken .name ()), encodingToken );
10121066 }
1013- final String primitive = Character .toString (varName ) + "." + propertyName ;
1067+
1068+ // Optional tokens get initialized to NullValue
1069+ // (note: optionality is determined by the field's token)
1070+ if (signalToken .isOptionalEncoding ())
1071+ {
1072+ generateOptionalInitPrimitive (init , primitive , encodingToken );
1073+ }
1074+
10141075 generateDecodePrimitive (decode , primitive , encodingToken );
1015- generateRangeCheckPrimitive (rc , primitive , encodingToken );
1016- generateInitPrimitive (init , primitive , encodingToken );
1076+ generateRangeCheckPrimitive (rc , primitive , encodingToken , signalToken .isOptionalEncoding ());
10171077 break ;
10181078 }
10191079
0 commit comments