void GenStruct()

in TssCodeGen/src/CGenJava.cs [241:451]


        void GenStruct(TpmStruct s)
        {
            bool hasBase = s.DerivedFrom != null;
            string className = s.Name;
            string classBases = hasBase ? s.DerivedFrom.Name
                              : !s.IsCmdStruct() ? "TpmStructure"
                              : s.Info.IsRequest() ? "ReqStructure" : "RespStructure";

            // If this struct is not derived from another one and is a member of one or more unions,
            // it must implement the corresponding union interfaces
            if (!s.IsCmdStruct() && !hasBase)
            {
                string unionInterfaces = string.Join(", ", s.ContainingUnions.Select(u => u.Name));
                if (unionInterfaces != "")
                    classBases += " implements " + unionInterfaces;
            }

            // Javadoc comment for the data structure
            WriteComment(s);

            // Class header
            Write($"public class {className} extends {classBases}");
            TabIn("{");

            //
            // Fields
            //
            Debug.Assert(s.Fields.Count == 0 || !hasBase);
            foreach (var f in s.NonSizeFields)
            {
                if (f.MarshalType == MarshalType.ConstantValue)
                    continue;

                WriteComment(f);
                if (f.MarshalType == MarshalType.UnionSelector)
                {
                    var unionField = f.RelatedUnion;
                    var u = (TpmUnion)unionField.Type;
                    Write($"public {f.TypeName} {f.Name}() {{ ", false);
                    if (u.NullSelector == null)
                        Write($"return {unionField.Name}.GetUnionSelector(); }}");
                    else
                    {
                        Write($"return {unionField.Name} != null ? {unionField.Name}.GetUnionSelector()" +
                                                              $" : {u.NullSelector.QualifiedName}; }}");
                    }
                }
                else
                    Write($"public {f.TypeName} {f.Name};");
            }

            //
            // Default constructor
            //
            var fieldsToInit = s.NonDefaultInitFields;
            Write("");
            Write($"public {className}()", false);
            if (fieldsToInit.Count() == 0)
            {
                Write(" {}");
            }
            else if (fieldsToInit.Count() == 1)
            {
                var f = fieldsToInit[0];
                Write($" {{ {f.Name} = {f.GetInitVal()}; }}");
            }
            else
            {
                TabIn("{");
                foreach (StructField f in fieldsToInit)
                    Write($"{f.Name} = {f.GetInitVal()};");
                TabOut("}");
            }

            //
            // Member-wise constructor
            //
            var ctorParams = s.FieldHolder.NonTagFields;
            if (!s.Info.IsResponse() && ctorParams.Count() != 0)
            {
                // Javadoc comments (note that we provide a bit more info for union parameters)
                string javaDocComment = "";
                foreach (var p in ctorParams)
                    javaDocComment += GetParamComment(p, "_") + eol;
                WriteComment(javaDocComment);

                string ctorOpen = $"public {className}(";
                string ctorParamList = string.Join(", ", ctorParams.Select(p => p.TypeName + " _" + p.Name));
                Write(ctorOpen + ctorParamList + ")", false);
                if (hasBase)
                {
                    if (ctorParams.Length == 1)
                        Write($" {{ super(_{ctorParams[0].Name}); }}");
                    else
                    {
                        string ctorParamNamesList = string.Join(", ", ctorParams.Select(p => "_" + p.Name));
                        TabIn("{");
                        Write($"super({ctorParamNamesList});");
                        TabOut("}");
                    }
                }
                else if (ctorParams.Length == 1)
                {
                    var p = ctorParams[0];
                    Write($" {{ {p.Name} = _{p.Name}; }}");
                }
                else
                {
                    TabIn("{");
                    foreach (var p in ctorParams)
                    {
                        // We turn shorts into ints in constructor args, to allow external API users
                        // avoid incessant casting. Instead the cast is hidden in the constructor body.
                        // Note that we cannot change the type of the corresponding members, as it is
                        // dictated by the TPM 2.0 spec.
                        Write($"{p.Name} = _{p.Name};");
                    }
                    TabOut("}");
                }
            }

            //
            // Union interface: TpmUnion.GetUnionSelector()
            //
            GenGetUnionSelector(s);

            //
            // Marshaling
            //
            GenMarshalingMethod(true, s);
            GenMarshalingMethod(false, s);

            WriteComment("@deprecated Use {@link #toBytes()} instead\n" +
                         "@return Wire (marshaled) representation of this object");
            Write("public byte[] toTpm () { return toBytes(); }");

            WriteComment("Static marshaling helper\n" +
                         "@param byteBuf Wire representation of the object\n" +
                         "@return New object constructed from its wire representation");
            Write($"public static {className} fromBytes (byte[] byteBuf) ");
            TabIn("{");
            Write($"return new TpmBuffer(byteBuf).createObj({className}.class);");
            TabOut("}");

            WriteComment("@deprecated Use {@link #fromBytes(byte[])} instead\n" +
                         "@param byteBuf Wire representation of the object\n" +
                         "@return New object constructed from its wire representation");
            Write($"public static {className} fromTpm (byte[] byteBuf)  {{ return fromBytes(byteBuf); }}");

            WriteComment("Static marshaling helper\n" +
                         "@param buf Wire representation of the object\n" +
                         "@return New object constructed from its wire representation");
            Write($"public static {className} fromTpm (TpmBuffer buf) ");
            TabIn("{");
            Write($"return buf.createObj({className}.class);");
            TabOut("}");

            Write("@Override");
            Write("public String toString()");
            TabIn("{");
            Write($"TpmStructurePrinter _p = new TpmStructurePrinter(\"{s.Name}\");");
            Write("toStringInternal(_p, 1);");
            Write("_p.endStruct();");
            Write("return _p.toString();");
            TabOut("}", false);

            if (s.Fields.Count() > 0)
            {
                Write("@Override");
                Write("public void toStringInternal(TpmStructurePrinter _p, int d)");
                TabIn("{");
                foreach (StructField f in ctorParams)
                    Write($"_p.add(d, \"{f.TypeName}\", \"{f.Name}\", {f.Name});");
                TabOut("}", false);
            }

            var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null;
            if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0))
            {
                if (info.NumHandles != 0)
                {
                    Write("@Override");
                    Write($"public int numHandles() {{ return {info.NumHandles}; }}");
                    if (info.IsRequest())
                    {
                        string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => ThisMember + f.Name));
                        Write("@Override");
                        Write($"public int numAuthHandles() {{ return {info.NumAuthHandles}; }}");
                        Write("@Override");
                        Write($"public TPM_HANDLE[] getHandles() {{ return new TPM_HANDLE[] {{{handles}}}; }}");
                    }
                    else
                    {
                        Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0);
                        Write("@Override");
                        Write($"public TPM_HANDLE getHandle() {{ return {ThisMember}{s.Fields[0].Name}; }}");
                        Write("@Override");
                        Write($"public void setHandle(TPM_HANDLE h) {{ {ThisMember}{s.Fields[0].Name} = h; }}");
                    }
                }
                if (info.SessEncSizeLen != 0)
                {
                    Debug.Assert(info.SessEncValLen != 0);
                    Write("@Override");
                    Write($"public SessEncInfo sessEncInfo() {{ return new SessEncInfo({info.SessEncSizeLen}, {info.SessEncValLen}); }}");
                }
            }

            InsertSnip(s.Name);
            TabOut("}", false);
        } // GenStruct()