@@ -82,6 +82,17 @@ interface ParentDef
8282 SubGroup addSubGroup (String name , int level , Token groupToken );
8383 }
8484
85+ static final class NullifyTargets
86+ {
87+ final List <String > optionalFields = new ArrayList <>();
88+ final List <String > compositeFieldEncoders = new ArrayList <>();
89+
90+ boolean isEmpty ()
91+ {
92+ return optionalFields .isEmpty () && compositeFieldEncoders .isEmpty ();
93+ }
94+ }
95+
8596 private final Ir ir ;
8697 private final RustOutputManager outputManager ;
8798 private final String crateVersion ;
@@ -224,9 +235,9 @@ static String getBufOffset(final Token token)
224235 return "offset" ;
225236 }
226237
227- static List < String > getNullifyOptionalFields (final List <Token > tokens )
238+ static NullifyTargets getNullifyTargets (final List <Token > tokens )
228239 {
229- final List < String > optionalFields = new ArrayList <> ();
240+ final NullifyTargets targets = new NullifyTargets ();
230241 Generators .forEachField (
231242 tokens ,
232243 (fieldToken , typeToken ) ->
@@ -237,16 +248,20 @@ static List<String> getNullifyOptionalFields(final List<Token> tokens)
237248 {
238249 if (isOptionalPrimitiveScalar (typeToken ))
239250 {
240- optionalFields .add (fieldName );
251+ targets . optionalFields .add (fieldName );
241252 }
242253 }
243254 else if (signal == BEGIN_ENUM &&
244255 isOptionalEnum (typeToken , fieldToken ))
245256 {
246- optionalFields .add (fieldName );
257+ targets .optionalFields .add (fieldName );
258+ }
259+ else if (signal == Signal .BEGIN_COMPOSITE )
260+ {
261+ targets .compositeFieldEncoders .add (compositeEncoderAccessorName (fieldToken .name ()));
247262 }
248263 });
249- return optionalFields ;
264+ return targets ;
250265 }
251266
252267 static void generateEncoderFields (
@@ -297,17 +312,53 @@ static void generateEncoderFields(
297312 static void generateNullifyOptionalFieldsMethod (
298313 final Appendable out ,
299314 final int level ,
300- final List < String > optionalFields ) throws IOException
315+ final NullifyTargets targets ) throws IOException
301316 {
302317 indent (out , level , "/// Set all optional fields to their null values.\n " );
303318 indent (out , level , "#[inline]\n " );
304319 indent (out , level , "pub fn nullify_optional_fields(&mut self) -> &mut Self {\n " );
305- for (final String field : optionalFields )
320+ appendNullifyOptionalFieldsBody (out , level + 1 , targets );
321+ indent (out , level + 1 , "self\n " );
322+ indent (out , level , "}\n \n " );
323+ }
324+
325+ private static void appendNullifyOptionalFieldsBody (
326+ final Appendable out ,
327+ final int level ,
328+ final NullifyTargets targets ) throws IOException
329+ {
330+ for (final String field : targets .optionalFields )
306331 {
307- indent (out , level + 1 , "self.%s_opt(None);\n " , field );
332+ indent (out , level , "self.%s_opt(None);\n " , field );
308333 }
334+
335+ for (final String compositeFieldEncoder : targets .compositeFieldEncoders )
336+ {
337+ indent (out , level , "{\n " );
338+ indent (out , level + 1 , "let mut composite_encoder = core::mem::take(self).%s();\n " , compositeFieldEncoder );
339+ indent (out , level + 1 , "composite_encoder.nullify_optional_fields();\n " );
340+ indent (out , level + 1 , "*self = composite_encoder.parent().expect(\" parent missing\" );\n " );
341+ indent (out , level , "}\n " );
342+ }
343+ }
344+
345+ private static void appendTraitNullifyOptionalFieldsMethod (
346+ final Appendable out ,
347+ final int level ,
348+ final NullifyTargets targets ) throws IOException
349+ {
350+ if (targets .isEmpty ())
351+ {
352+ return ;
353+ }
354+
355+ indent (out , 0 , "\n " );
356+ indent (out , level , "/// Set all optional fields to their 'null' values.\n " );
357+ indent (out , level , "#[inline]\n " );
358+ indent (out , level , "fn nullify_optional_fields(&mut self) -> &mut Self {\n " );
359+ appendNullifyOptionalFieldsBody (out , level + 1 , targets );
309360 indent (out , level + 1 , "self\n " );
310- indent (out , level , "}\n \n " );
361+ indent (out , level , "}\n " );
311362 }
312363
313364 private static boolean isOptionalPrimitiveScalar (final Token typeToken )
@@ -327,6 +378,11 @@ private static String rustEnumType(final Token typeToken)
327378 return format ("%s::%s" , toLowerSnakeCase (enumTypeName ), formatStructName (enumTypeName ));
328379 }
329380
381+ private static String compositeEncoderAccessorName (final String name )
382+ {
383+ return toLowerSnakeCase (encoderName (name ));
384+ }
385+
330386 static void generateEncoderGroups (
331387 final StringBuilder sb ,
332388 final List <Token > tokens ,
@@ -734,7 +790,7 @@ private static void generateCompositeEncoder(
734790 final Token typeToken ,
735791 final String name ) throws IOException
736792 {
737- final String encoderName = toLowerSnakeCase ( encoderName ( name ) );
793+ final String encoderName = compositeEncoderAccessorName ( name );
738794 final String encoderTypeName = format ("%s::%s" ,
739795 codecModName (typeToken .referencedName () == null ? typeToken .name () : typeToken .referencedName ()),
740796 encoderName (formatStructName (typeToken .applicableTypeName ())));
@@ -1381,7 +1437,7 @@ private static void generateSingleBitSet(
13811437 static void appendImplEncoderTrait (
13821438 final Appendable out ,
13831439 final String typeName ,
1384- final List < String > optionalFields ) throws IOException
1440+ final NullifyTargets targets ) throws IOException
13851441 {
13861442 indent (out , 1 , "impl<%s> %s for %s {\n " , BUF_LIFETIME , withBufLifetime ("Writer" ), withBufLifetime (typeName ));
13871443 indent (out , 2 , "#[inline]\n " );
@@ -1401,19 +1457,7 @@ static void appendImplEncoderTrait(
14011457 indent (out , 3 , "self.limit = limit;\n " );
14021458 indent (out , 2 , "}\n " );
14031459
1404- if (!optionalFields .isEmpty ())
1405- {
1406- indent (out , 0 , "\n " );
1407- indent (out , 2 , "/// Set all optional fields to their 'null' values.\n " );
1408- indent (out , 2 , "#[inline]\n " );
1409- indent (out , 2 , "fn nullify_optional_fields(&mut self) -> &mut Self {\n " );
1410- for (final String field : optionalFields )
1411- {
1412- indent (out , 3 , "self.%s_opt(None);\n " , field );
1413- }
1414- indent (out , 3 , "self\n " );
1415- indent (out , 2 , "}\n " );
1416- }
1460+ appendTraitNullifyOptionalFieldsMethod (out , 2 , targets );
14171461
14181462 indent (out , 1 , "}\n \n " );
14191463 }
@@ -1686,7 +1730,7 @@ static void appendImplEncoderForComposite(
16861730 final Appendable out ,
16871731 final int level ,
16881732 final String name ,
1689- final List < String > optionalFields ) throws IOException
1733+ final NullifyTargets targets ) throws IOException
16901734 {
16911735 appendImplWriterForComposite (out , level , name );
16921736
@@ -1702,19 +1746,7 @@ static void appendImplEncoderForComposite(
17021746 indent (out , level + 2 , "self.parent.as_mut().expect(\" parent missing\" ).set_limit(limit);\n " );
17031747 indent (out , level + 1 , "}\n " );
17041748
1705- if (!optionalFields .isEmpty ())
1706- {
1707- indent (out , 0 , "\n " );
1708- indent (out , 2 , "/// Set all optional fields to their 'null' values.\n " );
1709- indent (out , 2 , "#[inline]\n " );
1710- indent (out , 2 , "fn nullify_optional_fields(&mut self) -> &mut Self {\n " );
1711- for (final String field : optionalFields )
1712- {
1713- indent (out , 3 , "self.%s_opt(None);\n " , field );
1714- }
1715- indent (out , 3 , "self\n " );
1716- indent (out , 2 , "}\n " );
1717- }
1749+ appendTraitNullifyOptionalFieldsMethod (out , 2 , targets );
17181750
17191751 indent (out , level , "}\n \n " );
17201752 }
@@ -1800,7 +1832,7 @@ private static void generateCompositeEncoder(
18001832 indent (out , 3 , "self.parent.take().ok_or(SbeErr::ParentNotSet)\n " );
18011833 indent (out , 2 , "}\n \n " );
18021834
1803- final List < String > optionalFields = new ArrayList <> ();
1835+ final NullifyTargets nullifyTargets = new NullifyTargets ();
18041836 for (int i = 1 , end = tokens .size () - 1 ; i < end ; )
18051837 {
18061838 final Token encodingToken = tokens .get (i );
@@ -1814,22 +1846,23 @@ private static void generateCompositeEncoder(
18141846 {
18151847 generateOptionalPrimitiveEncoder (sb , 2 , encodingToken , encodingToken .name (),
18161848 encodingToken .encoding ());
1817- optionalFields .add (formatFunctionName (encodingToken .name ()));
1849+ nullifyTargets . optionalFields .add (formatFunctionName (encodingToken .name ()));
18181850 }
18191851 break ;
18201852 case BEGIN_ENUM :
18211853 generateEnumEncoder (sb , 2 , encodingToken , encodingToken , encodingToken .name ());
18221854 if (isOptionalEnum (encodingToken , encodingToken ))
18231855 {
18241856 generateOptionalEnumEncoder (sb , 2 , encodingToken , encodingToken .name ());
1825- optionalFields .add (formatFunctionName (encodingToken .name ()));
1857+ nullifyTargets . optionalFields .add (formatFunctionName (encodingToken .name ()));
18261858 }
18271859 break ;
18281860 case BEGIN_SET :
18291861 generateBitSetEncoder (sb , 2 , encodingToken , encodingToken .name ());
18301862 break ;
18311863 case BEGIN_COMPOSITE :
18321864 generateCompositeEncoder (sb , 2 , encodingToken , encodingToken .name ());
1865+ nullifyTargets .compositeFieldEncoders .add (compositeEncoderAccessorName (encodingToken .name ()));
18331866 break ;
18341867 default :
18351868 break ;
@@ -1839,7 +1872,7 @@ private static void generateCompositeEncoder(
18391872 i += encodingToken .componentTokenCount ();
18401873 }
18411874
1842- generateNullifyOptionalFieldsMethod (out , 2 , optionalFields );
1875+ generateNullifyOptionalFieldsMethod (out , 2 , nullifyTargets );
18431876 indent (out , 1 , "}\n " ); // end impl
18441877 indent (out , 0 , "} // end encoder mod \n " );
18451878 }
0 commit comments