public override async Task <int?> ExpectedLength(ObjectGeneration objGen, TypeGeneration typeGen)
        {
            GenderedType gender = typeGen as GenderedType;

            if (!this.Module.TryGetTypeGeneration(gender.SubTypeGeneration.GetType(), out var subTransl))
            {
                throw new ArgumentException("Unsupported type generator: " + gender.SubTypeGeneration);
            }

            var expected = await subTransl.ExpectedLength(objGen, gender.SubTypeGeneration);

            if (expected == null)
            {
                return(null);
            }
            return(expected.Value * 2);
        }
        public override async Task GenerateCopyIn(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor readerAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationAccessor)
        {
            GenderedType gender = typeGen as GenderedType;
            var          data   = typeGen.GetFieldData();

            if (!this.Module.TryGetTypeGeneration(gender.SubTypeGeneration.GetType(), out var subTransl))
            {
                throw new ArgumentException("Unsupported type generator: " + gender.SubTypeGeneration);
            }

            if (data.RecordType.HasValue)
            {
                fg.AppendLine($"{readerAccessor}.Position += {readerAccessor}.{nameof(MutagenBinaryReadStream.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(RecordHeaderConstants.HeaderLength)};");
            }
            else if (data.MarkerType.HasValue && !gender.MarkerPerGender)
            {
                fg.AppendLine($"{readerAccessor}.Position += {readerAccessor}.{nameof(MutagenBinaryReadStream.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(RecordHeaderConstants.HeaderLength)} + contentLength; // Skip marker");
            }

            bool notNull = gender.ItemNullable && !gender.SubTypeGeneration.IsNullable;

            using (var args = new ArgsWrapper(fg,
                                              $"{itemAccessor} = {this.NamespacePrefix}GenderedItemBinaryTranslation.Parse{(gender.MarkerPerGender ? "MarkerPerItem" : null)}<{gender.SubTypeGeneration.TypeName(getter: false, needsCovariance: true)}>"))
            {
                args.AddPassArg($"frame");
                if (gender.MaleMarker.HasValue)
                {
                    args.Add($"maleMarker: {objGen.RecordTypeHeaderName(gender.MaleMarker.Value)}");
                    args.Add($"femaleMarker: {objGen.RecordTypeHeaderName(gender.FemaleMarker.Value)}");
                }
                if (data.MarkerType.HasValue && gender.MarkerPerGender)
                {
                    args.Add($"marker: {objGen.RecordTypeHeaderName(data.MarkerType.Value)}");
                }
                var subData = gender.SubTypeGeneration.GetFieldData();
                if (subData.RecordType.HasValue &&
                    !(gender.SubTypeGeneration is LoquiType))
                {
                    args.Add($"contentMarker: {objGen.RecordTypeHeaderName(subData.RecordType.Value)}");
                }
                LoquiType loqui = gender.SubTypeGeneration as LoquiType;
                if (loqui != null)
                {
                    if (subData?.RecordTypeConverter != null &&
                        subData.RecordTypeConverter.FromConversions.Count > 0)
                    {
                        args.Add($"parseParams: {objGen.RegistrationName}.{typeGen.Name}Converter");
                    }
                }
                if (gender.FemaleConversions != null)
                {
                    args.Add($"femaleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}FemaleConverter");
                }
                if (gender.MaleConversions != null)
                {
                    args.Add($"maleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}MaleConverter");
                }

                bool needsRecordConv = gender.SubTypeGeneration.NeedsRecordConverter();
                if (subTransl.AllowDirectParse(objGen, gender.SubTypeGeneration, false))
                {
                    if (loqui != null)
                    {
                        args.Add($"transl: {loqui.ObjectTypeName}{loqui.GenericTypes(getter: false)}.TryCreateFromBinary");
                    }
                    else
                    {
                        args.Add($"transl: {subTransl.GetTranslatorInstance(gender.SubTypeGeneration, getter: false)}.Parse");
                        if (gender.ItemNullable)
                        {
                            args.Add($"skipMarker: false");
                        }
                    }
                }
                else
                {
                    args.Add(gen =>
                    {
                        gen.AppendLine($"transl: (MutagenFrame r, out {gender.SubTypeGeneration.TypeName(getter: false, needsCovariance: true)} genSubItem{(needsRecordConv ? $", {nameof(RecordTypeConverter)}? conv" : null)}) =>");
                        using (new BraceWrapper(gen))
                        {
                            subTransl.GenerateCopyInRet(
                                fg: gen,
                                objGen: objGen,
                                targetGen: gender.SubTypeGeneration,
                                typeGen: gender.SubTypeGeneration,
                                readerAccessor: "r",
                                translationAccessor: null,
                                retAccessor: "return ",
                                outItemAccessor: new Accessor("genSubItem"),
                                asyncMode: AsyncMode.Off,
                                errorMaskAccessor: "listErrMask",
                                converterAccessor: "conv",
                                inline: false);
                        }
                        if (gender.ItemNullable)
                        {
                            args.Add($"skipMarker: false");
                        }
                    });
                }
                if (notNull)
                {
                    args.Add($"fallback: {gender.SubTypeGeneration.GetDefault(getter: false)}");
                }
            }
        }
        public override async Task GenerateWrite(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor writerAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationAccessor,
            Accessor converterAccessor)
        {
            GenderedType gendered = typeGen as GenderedType;
            var          gen      = this.Module.GetTypeGeneration(gendered.SubTypeGeneration.GetType());
            var          data     = typeGen.GetFieldData();

            if (!this.Module.TryGetTypeGeneration(gendered.SubTypeGeneration.GetType(), out var subTransl))
            {
                throw new ArgumentException("Unsupported type generator: " + gendered.SubTypeGeneration);
            }
            var  allowDirectWrite = subTransl.AllowDirectWrite(objGen, gendered.SubTypeGeneration);
            var  loqui            = gendered.SubTypeGeneration as LoquiType;
            bool needsMasters     = gendered.SubTypeGeneration is FormLinkType || (loqui != null && loqui.GetFieldData().HasTrigger);
            var  typeName         = gendered.SubTypeGeneration.TypeName(getter: true, needsCovariance: true);

            if (loqui != null)
            {
                typeName = loqui.TypeNameInternal(getter: true, internalInterface: true);
            }
            using (var args = new ArgsWrapper(fg,
                                              $"GenderedItemBinaryTranslation.Write{(gendered.MarkerPerGender ? "MarkerPerItem" : null)}"))
            {
                args.Add($"writer: {writerAccessor}");
                args.Add($"item: {itemAccessor}");
                if (data.RecordType.HasValue)
                {
                    args.Add($"recordType: {objGen.RecordTypeHeaderName(data.RecordType.Value)}");
                }
                else if (data.MarkerType.HasValue)
                {
                    args.Add($"markerType: {objGen.RecordTypeHeaderName(data.MarkerType.Value)}");
                }
                if (gendered.MaleMarker.HasValue)
                {
                    args.Add($"maleMarker: {objGen.RecordTypeHeaderName(gendered.MaleMarker.Value)}");
                }
                if (gendered.FemaleMarker.HasValue)
                {
                    args.Add($"femaleMarker: {objGen.RecordTypeHeaderName(gendered.FemaleMarker.Value)}");
                }
                if (gendered.MaleMarker.HasValue &&
                    loqui != null)
                {
                    args.Add("markerWrap: false");
                }
                if (gendered.FemaleConversions != null)
                {
                    args.Add($"femaleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}FemaleConverter");
                }
                if (gendered.MaleConversions != null)
                {
                    args.Add($"maleRecordConverter: {objGen.RegistrationName}.{typeGen.Name}MaleConverter");
                }
                if (allowDirectWrite)
                {
                    args.Add($"transl: {subTransl.GetTranslatorInstance(gendered.SubTypeGeneration, getter: true)}.Write{(gendered.SubTypeGeneration.Nullable ? "Nullable" : string.Empty)}");
                }
                else
                {
                    args.Add((gen) =>
                    {
                        var listTranslMask = this.MaskModule.GetMaskModule(gendered.SubTypeGeneration.GetType()).GetTranslationMaskTypeStr(gendered.SubTypeGeneration);
                        gen.AppendLine($"transl: (MutagenWriter subWriter, {typeName}{gendered.SubTypeGeneration.NullChar} subItem{(needsMasters ? $", {nameof(TypedWriteParams)}? conv" : null)}) =>");
                        using (new BraceWrapper(gen))
                        {
                            subTransl.GenerateWrite(
                                fg: gen,
                                objGen: objGen,
                                typeGen: gendered.SubTypeGeneration,
                                writerAccessor: "subWriter",
                                translationAccessor: "subTranslMask",
                                itemAccessor: new Accessor($"subItem"),
                                errorMaskAccessor: null,
                                converterAccessor: needsMasters ? "conv" : null);
                        }
                    });
                }
            }
        }