@@ -92,9 +92,11 @@ private void generateGroupFieldRepresentations(
9292 for (final GroupTreeNode node : groupTree )
9393 {
9494 appendStructHeader (appendable , node .contextualName + "Member" , true );
95- appendStructFields (appendable , node .fields );
95+ appendStructFields (appendable , node .simpleNamedFields );
9696 appendable .append ("}\n " );
9797
98+ generateConstantAccessorImpl (appendable , node .contextualName + "Member" , node .rawFields );
99+
98100 generateGroupFieldRepresentations (appendable , node .groups );
99101 }
100102
@@ -128,7 +130,8 @@ private static Optional<FieldsRepresentationSummary> generateFieldsRepresentatio
128130 appendStructHeader (writer , representationStruct , true );
129131 appendStructFields (writer , namedFieldTokens );
130132 writer .append ("}\n " );
131- // TODO - also implement constants
133+
134+ generateConstantAccessorImpl (writer , representationStruct , components .fields );
132135 }
133136 final int numBytes = components .fields .stream ()
134137 .filter (t -> !t .isConstantEncoding ())
@@ -161,8 +164,38 @@ private static void generateSingleBitSet(final List<Token> tokens, final OutputM
161164 writer .append ("#[repr(C,packed)]\n " );
162165 final String rustPrimitiveType = rustTypeName (beginToken .encoding ().primitiveType ());
163166 writer .append (format ("pub struct %s(pub %s);%n" , setType , rustPrimitiveType ));
167+ writer .append (format ("impl %s {\n " , setType ));
168+ indent (writer , 1 , "pub fn new() -> Self {\n " );
169+ indent (writer , 2 , "%s(0)\n " , setType );
170+ indent (writer , 1 , "}\n " );
164171
165- // TODO - implementation to extract named choices with methods
172+ indent (writer , 1 , "pub fn clear(&mut self) -> &mut Self {\n " );
173+ indent (writer , 2 , "self.0 = 0;\n " );
174+ indent (writer , 2 , "self\n " );
175+ indent (writer , 1 , "}\n " );
176+ for (final Token token : tokens )
177+ {
178+ if (Signal .CHOICE != token .signal ())
179+ {
180+ continue ;
181+ }
182+ final String choiceName = formatMethodName (token .name ());
183+ final Encoding encoding = token .encoding ();
184+ final String choiceBitIndex = encoding .constValue ().toString ();
185+ indent (writer , 1 , "pub fn get_%s(&self) -> bool {\n " , choiceName );
186+ indent (writer , 2 , "0 != self.0 & (1 << %s)\n " , choiceBitIndex );
187+ indent (writer , 1 , "}\n " , choiceName );
188+
189+ indent (writer , 1 , "pub fn set_%s(&mut self, value: bool) -> &mut Self {\n " , choiceName );
190+ indent (writer , 2 , "self.0 = if value {\n " , choiceBitIndex );
191+ indent (writer , 3 , "self.0 | (1 << %s)\n " , choiceBitIndex );
192+ indent (writer , 2 , "} else {\n " );
193+ indent (writer , 3 , "self.0 & !(1 << %s)\n " , choiceBitIndex );
194+ indent (writer , 2 , "};\n " );
195+ indent (writer , 2 , "self\n " );
196+ indent (writer , 1 , "}\n " , choiceName );
197+ }
198+ writer .append ("}\n " );
166199 }
167200
168201 }
@@ -695,7 +728,6 @@ private static List<GroupTreeNode> buildGroupTrees(final String parentTypeName,
695728
696729 final List <Token > fields = new ArrayList <>();
697730 i = collectFields (groupsTokens , i , fields );
698- final List <NamedToken > namedFields = NamedToken .gatherNamedFieldTokens (fields );
699731
700732 final List <Token > childGroups = new ArrayList <>();
701733 i = collectGroups (groupsTokens , i , childGroups );
@@ -711,7 +743,7 @@ private static List<GroupTreeNode> buildGroupTrees(final String parentTypeName,
711743 numInGroupType ,
712744 blockLengthType ,
713745 blockLength ,
714- namedFields ,
746+ fields ,
715747 varDataSummaries
716748 );
717749 groups .add (node );
@@ -746,7 +778,8 @@ static class GroupTreeNode
746778 final PrimitiveType numInGroupType ;
747779 final PrimitiveType blockLengthType ;
748780 final int blockLength ;
749- final List <NamedToken > fields ;
781+ final List <Token > rawFields ;
782+ final List <NamedToken > simpleNamedFields ;
750783 final List <GroupTreeNode > groups = new ArrayList <>();
751784 final List <VarDataSummary > varData ;
752785
@@ -756,7 +789,7 @@ static class GroupTreeNode
756789 final PrimitiveType numInGroupType ,
757790 final PrimitiveType blockLengthType ,
758791 final int blockLength ,
759- final List <NamedToken > fields ,
792+ final List <Token > fields ,
760793 final List <VarDataSummary > varData )
761794 {
762795 this .parent = parent ;
@@ -765,7 +798,8 @@ static class GroupTreeNode
765798 this .numInGroupType = numInGroupType ;
766799 this .blockLengthType = blockLengthType ;
767800 this .blockLength = blockLength ;
768- this .fields = fields ;
801+ this .rawFields = fields ;
802+ this .simpleNamedFields = NamedToken .gatherNamedFieldTokens (fields );
769803 this .varData = varData ;
770804 parent .ifPresent (p -> p .addChild (this ));
771805 }
@@ -1231,10 +1265,7 @@ private static void generateSingleComposite(final List<Token> tokens, final Outp
12311265 appendStructFields (writer , splitTokens .nonConstantEncodingTokens );
12321266 writer .append ("}\n " );
12331267
1234- if (!splitTokens .constantEncodingTokens .isEmpty ())
1235- {
1236- generateCompositeImplForConstants (formattedTypeName , writer , splitTokens .constantEncodingTokens );
1237- }
1268+ generateConstantAccessorImpl (writer , formattedTypeName , getMessageBody (tokens ));
12381269 }
12391270 }
12401271
@@ -1351,20 +1382,42 @@ private static String getRustTypeForPrimitivePossiblyArray(final Token encodingT
13511382 return rustType ;
13521383 }
13531384
1354- private static void generateCompositeImplForConstants (final String formattedTypeName ,
1355- final Writer writer ,
1356- final List <Token > deferredConstantTokens ) throws IOException
1385+ private static void generateConstantAccessorImpl (final Appendable writer , final String formattedTypeName ,
1386+ final List <Token > unfilteredFields ) throws IOException
13571387 {
13581388 writer .append (format ("%nimpl %s {%n" , formattedTypeName ));
1359- for (final Token constantToken : deferredConstantTokens )
1389+ for (int i = 0 ; i < unfilteredFields . size (); )
13601390 {
1391+ final Token fieldToken = unfilteredFields .get (i );
1392+ final String name = fieldToken .name ();
1393+ final int componentTokenCount = fieldToken .componentTokenCount ();
1394+ final Token signalToken ;
1395+ if (fieldToken .signal () == BEGIN_FIELD )
1396+ {
1397+ if (i > unfilteredFields .size () - 1 )
1398+ {
1399+ throw new ArrayIndexOutOfBoundsException ("BEGIN_FIELD token should be followed by content tokens" );
1400+ }
1401+ signalToken = unfilteredFields .get (i + 1 );
1402+ } else
1403+ {
1404+ signalToken = fieldToken ;
1405+ }
1406+
1407+ // Either the field must be marked directly as constant
1408+ // or it must wrap something that is fully constant
1409+ if (!(fieldToken .isConstantEncoding () || signalToken .isConstantEncoding ()))
1410+ {
1411+ i += componentTokenCount ;
1412+ continue ;
1413+ }
13611414 final String constantRustTypeName ;
13621415 final String constantRustExpression ;
1363- switch (constantToken .signal ())
1416+ switch (signalToken .signal ())
13641417 {
13651418 case ENCODING :
1366- final String rawValue = constantToken .encoding ().constValue ().toString ();
1367- if (constantToken .encoding ().primitiveType () == PrimitiveType .CHAR )
1419+ final String rawValue = signalToken .encoding ().constValue ().toString ();
1420+ if (signalToken .encoding ().primitiveType () == PrimitiveType .CHAR )
13681421 {
13691422 // Special case string handling
13701423 constantRustTypeName = "&'static str" ;
@@ -1373,32 +1426,54 @@ private static void generateCompositeImplForConstants(final String formattedType
13731426
13741427 } else
13751428 {
1376- final String constantRustPrimitiveType = RustUtil .rustTypeName (constantToken .encoding ()
1377- .primitiveType ());
1378- constantRustTypeName = getRustTypeForPrimitivePossiblyArray (constantToken ,
1379- constantRustPrimitiveType );
1380- constantRustExpression = generateRustLiteral (constantToken .encoding ().primitiveType (),
1381- rawValue );
1429+ final String constantRustPrimitiveType = RustUtil .rustTypeName (signalToken .encoding ()
1430+ .primitiveType ());
1431+ constantRustTypeName = getRustTypeForPrimitivePossiblyArray (signalToken ,
1432+ constantRustPrimitiveType );
1433+ constantRustExpression = generateRustLiteral (signalToken .encoding ().primitiveType (),
1434+ rawValue );
13821435 }
13831436 break ;
13841437 case BEGIN_ENUM :
1385- // TODO - implement constant enums
1386- throw new IllegalStateException (format ("Unsupported constant presence enum or bitset property " +
1387- "%s" , constantToken .toString ()));
1438+ final String enumType = formatTypeName (signalToken .applicableTypeName ());
1439+ String enumValue = null ;
1440+ for (int j = i ; j < unfilteredFields .size (); j ++)
1441+ {
1442+ final Token searchAhead = unfilteredFields .get (j );
1443+ if (searchAhead .signal () == VALID_VALUE )
1444+ {
1445+ enumValue = searchAhead .name ();
1446+ break ;
1447+ }
1448+ }
1449+ if (enumValue == null )
1450+ {
1451+ throw new IllegalStateException ("Found a constant enum field with incomplete token content" );
1452+ }
1453+ constantRustTypeName = enumType ;
1454+ constantRustExpression = enumType + "::" + enumValue ;
1455+ break ;
13881456 case BEGIN_SET :
13891457 case BEGIN_COMPOSITE :
13901458 default :
13911459 throw new IllegalStateException (format ("Unsupported constant presence property " +
1392- "%s" , constantToken .toString ()));
1460+ "%s" , fieldToken .toString ()));
13931461 }
1394- writer .append ("\n " ).append (INDENT ).append ("#[inline]\n " ).append (INDENT );
1395- writer .append (format ("pub fn %s() -> %s {%n" , formatMethodName (constantToken .name ()),
1396- constantRustTypeName ));
1397- indent (writer , 2 ).append (constantRustExpression ).append ("\n " );
1398- indent (writer ).append ("}\n " );
1462+ appendConstAccessor (writer , name , constantRustTypeName , constantRustExpression );
1463+ i += componentTokenCount ;
13991464 }
14001465
14011466 writer .append ("}\n " );
14021467 }
14031468
1469+ private static void appendConstAccessor (final Appendable writer , final String name ,
1470+ final String rustTypeName , final String rustExpression ) throws IOException
1471+ {
1472+ writer .append ("\n " ).append (INDENT ).append ("#[inline]\n " ).append (INDENT );
1473+ writer .append (format ("pub fn %s() -> %s {%n" , formatMethodName (name ),
1474+ rustTypeName ));
1475+ indent (writer , 2 ).append (rustExpression ).append ("\n " );
1476+ indent (writer ).append ("}\n " );
1477+ }
1478+
14041479}
0 commit comments