예제 #1
0
 public override async Task GenerateWrapperFields(
     FileGeneration fg,
     ObjectGeneration objGen,
     TypeGeneration typeGen,
     Accessor dataAccessor,
     int?passedLength,
     string passedLengthAccessor,
     DataType data = null)
 {
     using (var args = new ArgsWrapper(fg,
                                       $"partial void {(typeGen.Name == null ? typeGen.GetFieldData().RecordType?.ToString() : typeGen.Name)}CustomParse"))
     {
         args.Add($"{nameof(OverlayStream)} stream");
         args.Add($"int offset");
     }
 }
예제 #2
0
        public override async Task GenerateCopyIn(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor frameAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationMaskAccessor)
        {
            var fieldData = typeGen.GetFieldData();

            if (fieldData.HasTrigger)
            {
                fg.AppendLine($"{frameAccessor}.Position += {frameAccessor}.{nameof(MutagenBinaryReadStream.MetaData)}.{nameof(ParsingBundle.Constants)}.{nameof(GameConstants.SubConstants)}.{nameof(RecordHeaderConstants.HeaderLength)};");
            }

            bool          hasCustom = false;
            List <string> extraArgs = new List <string>();

            extraArgs.Add($"frame: {frameAccessor}{(fieldData.HasTrigger ? ".SpawnWithLength(contentLength)" : "")}");
            foreach (var writeParam in this.AdditionalCopyInParams)
            {
                var get = writeParam(
                    objGen: objGen,
                    typeGen: typeGen);
                if (get.Failed)
                {
                    continue;
                }
                extraArgs.Add(get.Value);
                hasCustom = true;
            }

            if (CustomRead != null)
            {
                if (CustomRead(fg, objGen, typeGen, frameAccessor, itemAccessor))
                {
                    return;
                }
            }
            if (PreferDirectTranslation && !hasCustom)
            {
                fg.AppendLine($"{itemAccessor} = {frameAccessor}.Read{typeName}();");
            }
            else
            {
                TranslationGeneration.WrapParseCall(
                    new TranslationWrapParseArgs()
                {
                    FG                      = fg,
                    TypeGen                 = typeGen,
                    TranslatorLine          = $"{this.Namespace}{this.Typename(typeGen)}BinaryTranslation.Instance",
                    MaskAccessor            = errorMaskAccessor,
                    ItemAccessor            = itemAccessor,
                    TranslationMaskAccessor = null,
                    AsyncMode               = AsyncMode.Off,
                    IndexAccessor           = typeGen.HasIndex ? typeGen.IndexEnumInt : null,
                    ExtraArgs               = extraArgs.ToArray(),
                    SkipErrorMask           = !this.DoErrorMasks
                });
            }
        }
        public override async Task GenerateWrapperFields(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor dataAccessor,
            int?currentPosition,
            string passedLengthAccessor,
            DataType dataType)
        {
            LoquiType loqui = typeGen as LoquiType;
            var       data  = typeGen.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields(
                    fg,
                    objGen,
                    typeGen,
                    dataAccessor,
                    currentPosition,
                    passedLengthAccessor,
                    dataType);

                return;

            default:
                throw new NotImplementedException();
            }

            string DataAccessor(Accessor accessor, string positionStr, string lenStr)
            {
                if (objGen.GetObjectType() == ObjectType.Mod)
                {
                    return($"{nameof(PluginBinaryOverlay)}.{nameof(PluginBinaryOverlay.LockExtractMemory)}({accessor}, {positionStr}, {lenStr})");
                }
                else
                {
                    return($"{accessor}.Slice({positionStr})");
                }
            }

            string recConverter = $"default({nameof(TypedParseParams)})";

            if (loqui.GetFieldData()?.RecordTypeConverter != null &&
                loqui.GetFieldData().RecordTypeConverter.FromConversions.Count > 0)
            {
                recConverter = $"{objGen.RegistrationName}.{loqui.Name}Converter";
            }

            var isRequiredRecord = !loqui.Nullable && data.HasTrigger;

            if (dataType == null)
            {
                if (loqui.GetFieldData()?.HasTrigger ?? false)
                {
                    if (loqui is GroupType)
                    {
                        fg.AppendLine($"private List<{GetLocationObjectString(objGen)}>? _{typeGen.Name}Locations;");
                        using (new LineWrapper(fg))
                        {
                            if (loqui.IsNullable)
                            {
                                fg.Append($"public ");
                            }
                            else
                            {
                                fg.Append($"private ");
                            }

                            fg.Append(
                                $"{loqui.Interface(getter: true, internalInterface: true)}{(typeGen.CanBeNullable(getter: true) ? "?" : null)} ");
                            if (!loqui.IsNullable ||
                                isRequiredRecord)
                            {
                                fg.Append("_");
                            }

                            fg.Append($"{typeGen.Name}");
                            fg.Append($" => _{typeGen.Name}Locations != null ? ");
                            fg.Append(
                                $"{this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(_data, _{typeGen.Name}Locations, _package");
                            if (!recConverter.StartsWith("default("))
                            {
                                fg.Append($", {recConverter}");
                            }

                            fg.Append($") ");
                            fg.Append($": default;");
                        }
                    }
                    else if (loqui.TargetObjectGeneration.IsTypelessStruct())
                    {
                        if (loqui.Singleton ||
                            isRequiredRecord)
                        {
                            fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name};");
                        }
                        else if (loqui.Nullable)
                        {
                            fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)}? {typeGen.Name} {{ get; private set; }}");
                        }
                    }
                    else
                    {
                        var severalSubTypes = data.GenerationTypes
                                              .Select(i => i.Value)
                                              .WhereCastable <TypeGeneration, LoquiType>()
                                              .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true)
                                              .CountGreaterThan(1);
                        if (severalSubTypes)
                        {
                            fg.AppendLine($"private {nameof(RecordType)} _{typeGen.Name}Type;");
                        }

                        if (data.OverflowRecordType.HasValue)
                        {
                            fg.AppendLine($"private int? _{typeGen.Name}LengthOverride;");
                        }
                        fg.AppendLine($"private {GetLocationObjectString(objGen)}? _{typeGen.Name}Location;");
                        using (new LineWrapper(fg))
                        {
                            if (loqui.IsNullable)
                            {
                                fg.Append($"public ");
                            }
                            else
                            {
                                fg.Append($"private ");
                            }
                            fg.Append($"{loqui.Interface(getter: true, internalInterface: true)}{(typeGen.CanBeNullable(getter: true) ? "?" : null)} ");
                            if (!loqui.IsNullable ||
                                isRequiredRecord)
                            {
                                fg.Append("_");
                            }
                            fg.Append($"{typeGen.Name}");
                            if (!severalSubTypes)
                            {
                                fg.Append($" => _{typeGen.Name}Location.HasValue ? ");
                                fg.Append($"{this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location!.Value.Min", $"_{typeGen.Name}Location!.Value.Max")}, _package), _package{(data.OverflowRecordType.HasValue ? $", new {nameof(TypedParseParams)}(_{typeGen.Name}LengthOverride, null)" : null)}");
                                if (!recConverter.StartsWith("default("))
                                {
                                    fg.Append($", {recConverter}");
                                }
                                fg.Append($") ");
                                fg.Append($": default;");
                            }
                        }
                        if (severalSubTypes)
                        {
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("get");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine($"if (!_{typeGen.Name}Location.HasValue) return default;");
                                    fg.AppendLine($"switch (_{typeGen.Name}Type.TypeInt)");
                                    using (new BraceWrapper(fg))
                                    {
                                        foreach (var gen in data.GenerationTypes)
                                        {
                                            if (!(gen.Value is LoquiType subLoq))
                                            {
                                                continue;
                                            }
                                            if (subLoq?.TargetObjectGeneration?.Abstract ?? false)
                                            {
                                                continue;
                                            }
                                            foreach (var trigger in gen.Key)
                                            {
                                                fg.AppendLine($"case 0x{trigger.TypeInt.ToString("X")}: // {trigger.Type}");
                                            }
                                            using (new DepthWrapper(fg))
                                                using (new LineWrapper(fg))
                                                {
                                                    fg.Append($"return {this.Module.BinaryOverlayClassName(subLoq)}.{subLoq.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{subLoq.Name}Location!.Value.Min", $"_{subLoq.Name}Location!.Value.Max")}, _package), _package");
                                                    if (!loqui.Singleton)
                                                    {
                                                        fg.Append($", {recConverter}");
                                                    }
                                                    fg.Append($");");
                                                }
                                        }
                                        fg.AppendLine("default:");
                                        using (new DepthWrapper(fg))
                                        {
                                            fg.AppendLine("throw new ArgumentException();");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!loqui.Singleton)
                    {
                        fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({dataAccessor}.Slice({passedLengthAccessor ?? "0x0"}), _package), _package, {recConverter});");
                    }
                    else
                    {
                        fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)} _{typeGen.Name} {{ get; private set; }}");
                    }
                }
            }
            else
            {
                isRequiredRecord = true;
                DataBinaryTranslationGeneration.GenerateWrapperExtraMembers(fg, dataType, objGen, typeGen, passedLengthAccessor);
                fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name} => _{typeGen.Name}_IsSet ? {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location", null)}, _package), _package) : default;");
            }

            if (loqui.Singleton ||
                isRequiredRecord)
            {
                fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => _{typeGen.Name} ?? new {loqui.DirectTypeName}({(loqui.ThisConstruction ? "this" : null)});");
            }
        }
        public override async Task <int?> ExpectedLength(ObjectGeneration objGen, TypeGeneration typeGen)
        {
            var data = typeGen.GetFieldData();

            if (data.Length.HasValue)
            {
                return(data.Length);
            }

            LoquiType loqui = typeGen as LoquiType;

            if (loqui.TargetObjectGeneration == null)
            {
                return(null);
            }

            var sum = 0;

            foreach (var item in loqui.TargetObjectGeneration.IterateFields(includeBaseClass: true))
            {
                if (item.Nullable)
                {
                    return(null);
                }
                if (!this.Module.TryGetTypeGeneration(item.GetType(), out var gen))
                {
                    continue;
                }
                var len = await gen.ExpectedLength(loqui.TargetObjectGeneration, item);

                if (len == null)
                {
                    return(null);
                }
                sum += len.Value;
            }

            if (loqui.TargetObjectGeneration.Abstract)
            {
                int?absSum = null;
                foreach (var inheritingObj in await loqui.TargetObjectGeneration.InheritingObjects())
                {
                    int objectSum = 0;
                    foreach (var item in inheritingObj.IterateFields(includeBaseClass: true))
                    {
                        if (item.Nullable)
                        {
                            return(null);
                        }
                        if (!this.Module.TryGetTypeGeneration(item.GetType(), out var gen))
                        {
                            continue;
                        }
                        var len = await gen.ExpectedLength(inheritingObj, item);

                        if (len == null)
                        {
                            return(null);
                        }
                        objectSum += len.Value;
                    }
                    if (absSum == null)
                    {
                        absSum = objectSum;
                    }
                    else if (absSum.Value != objectSum)
                    {
                        // Inheriting objects don't agree on their length, so we can't expect a certain length
                        return(null);
                    }
                }
                if (absSum == null)
                {
                    return(null);
                }
                sum += absSum.Value;
            }

            return(sum);
        }
예제 #5
0
 public override async Task GenerateWrite(FileGeneration fg, ObjectGeneration objGen, TypeGeneration typeGen, Accessor writerAccessor, Accessor itemAccessor, Accessor errorMaskAccessor, Accessor translationAccessor, Accessor converterAccessor)
 {
     fg.AppendLine($"using (HeaderExport.Subrecord(writer, RecordTypes.{typeGen.GetFieldData().RecordType.Value})) {{ }}");
 }
예제 #6
0
        public override async Task GenerateWrite(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor writerAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationMask,
            Accessor converterAccessor)
        {
            var dict    = typeGen as DictType;
            var subData = dict.ValueTypeGen.GetFieldData();

            var data = typeGen.GetFieldData();

            if (data.MarkerType.HasValue)
            {
                fg.AppendLine($"using (HeaderExport.ExportHeader(writer, {objGen.RegistrationName}.{data.MarkerType.Value.Type}_HEADER, ObjectType.Subrecord)) {{ }}");
            }
            var binaryType = GetDictType(dict);

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

            if (dict.Mode == DictMode.KeyedValue ||
                binaryType == DictBinaryType.EnumMap)
            {
                var term = binaryType == DictBinaryType.EnumMap ? "Dict" : "List";
                using (var args = new ArgsWrapper(fg,
                                                  $"{this.NamespacePrefix}{term}BinaryTranslation<{dict.ValueTypeGen.TypeName(getter: true)}>.Instance.Write"))
                {
                    args.Add($"writer: {writerAccessor}");
                    args.Add($"items: {itemAccessor}{(binaryType == DictBinaryType.EnumMap ? null : ".Items")}");
                    if (binaryType == DictBinaryType.Trigger)
                    {
                        args.Add($"recordType: {objGen.RecordTypeHeaderName(data.RecordType.Value)}");
                    }
                    if (valTransl.AllowDirectWrite(objGen, typeGen))
                    {
                        args.Add($"transl: {valTransl.GetTranslatorInstance(dict.ValueTypeGen, getter: true)}.Write");
                    }
                    else
                    {
                        args.Add((gen) =>
                        {
                            gen.AppendLine($"transl: (MutagenWriter r, {dict.ValueTypeGen.TypeName(getter: true)} dictSubItem) =>");
                            using (new BraceWrapper(gen))
                            {
                                LoquiType targetLoqui = dict.ValueTypeGen as LoquiType;
                                valTransl.GenerateWrite(
                                    fg: gen,
                                    objGen: objGen,
                                    typeGen: targetLoqui,
                                    itemAccessor: new Accessor("dictSubItem"),
                                    writerAccessor: "r",
                                    translationAccessor: "dictTranslMask",
                                    errorMaskAccessor: null,
                                    converterAccessor: null);
                            }
                        });
                    }
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        public override async Task GenerateWrapperFields(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor dataAccessor,
            int?currentPosition,
            string passedLengthAccessor,
            DataType dataType = null)
        {
            var data = typeGen.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields(
                    fg,
                    objGen,
                    typeGen,
                    dataAccessor,
                    currentPosition,
                    passedLengthAccessor,
                    dataType);

                return;

            default:
                throw new NotImplementedException();
            }

            var gendered = typeGen as GenderedType;

            this.Module.TryGetTypeGeneration(gendered.SubTypeGeneration.GetType(), out var subBin);
            var typeName = $"{gendered.SubTypeGeneration.TypeName(getter: true, needsCovariance: true)}{gendered.SubTypeGeneration.NullChar}";

            if (data.HasTrigger &&
                !gendered.ItemNullable)
            {
                var subLen = (await subBin.ExpectedLength(objGen, gendered.SubTypeGeneration)).Value;
                if (data.HasTrigger)
                {
                    fg.AppendLine($"private int? _{typeGen.Name}Location;");
                }
                fg.AppendLine($"public IGenderedItemGetter<{gendered.SubTypeGeneration.TypeName(getter: true, needsCovariance: true)}>{(typeGen.Nullable ? "?" : null)} {typeGen.Name}");
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine("get");
                    using (new BraceWrapper(fg))
                    {
                        var subTypeDefault = gendered.SubTypeGeneration.GetDefault(getter: true);
                        fg.AppendLine($"if (!_{typeGen.Name}Location.HasValue) return {(typeGen.Nullable ? "default" : $"new GenderedItem<{typeName}>({subTypeDefault}, {subTypeDefault})")};");
                        fg.AppendLine($"var data = HeaderTranslation.ExtractSubrecordMemory(_data, _{typeGen.Name}Location.Value, _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)});");
                        using (var args = new ArgsWrapper(fg,
                                                          $"return new GenderedItem<{gendered.SubTypeGeneration.TypeName(getter: true, needsCovariance: true)}>"))
                        {
                            args.Add($"{subBin.GenerateForTypicalWrapper(objGen, gendered.SubTypeGeneration, "data", "_package")}");
                            args.Add($"{subBin.GenerateForTypicalWrapper(objGen, gendered.SubTypeGeneration, $"data.Slice({subLen})", "_package")}");
                        }
                    }
                }
            }
        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.Namespace}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($"recordTypeConverter: {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);
            bool needsMasters     = gendered.SubTypeGeneration is FormLinkType || gendered.SubTypeGeneration is LoquiType;
            var  typeName         = gendered.SubTypeGeneration.TypeName(getter: true, needsCovariance: true);
            var  loqui            = gendered.SubTypeGeneration as LoquiType;

            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(RecordTypeConverter)}? 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);
                        }
                    });
                }
            }
        }
        public override async Task GenerateWrapperFields(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor dataAccessor,
            int?currentPosition,
            string passedLengthAccessor,
            DataType dataType)
        {
            var data = typeGen.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields(
                    fg,
                    objGen,
                    typeGen,
                    dataAccessor,
                    currentPosition,
                    passedLengthAccessor,
                    dataType);

                return;

            default:
                throw new NotImplementedException();
            }
            if (data.HasTrigger)
            {
                fg.AppendLine($"private int? _{typeGen.Name}Location;");
                if (typeGen.CanBeNullable(getter: true))
                {
                    dataAccessor = $"{nameof(HeaderTranslation)}.{nameof(HeaderTranslation.ExtractSubrecordMemory)}({dataAccessor}, _{typeGen.Name}Location.Value, _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)})";
                    fg.AppendLine($"public {typeGen.TypeName(getter: true)}{(typeGen.Nullable ? "?" : null)} {typeGen.Name} => _{typeGen.Name}Location.HasValue ? {dataAccessor}[0] : default(Byte{(typeGen.Nullable ? "?" : null)});");
                }
                else
                {
                    fg.AppendLine($"public bool {typeGen.Name}_IsSet => _{typeGen.Name}Location.HasValue;");
                    if (dataType != null)
                    {
                        throw new ArgumentException();
                    }
                    dataAccessor = $"{nameof(HeaderTranslation)}.{nameof(HeaderTranslation.ExtractSubrecordMemory)}({dataAccessor}, _{typeGen.Name}Location.Value, _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)})";
                    fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => _{typeGen.Name}Location.HasValue ? {dataAccessor}[0] : default(Byte{(typeGen.Nullable ? "?" : null)});");
                }
            }
            else
            {
                if (dataType == null)
                {
                    fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => {dataAccessor}.Span[{passedLengthAccessor ?? "0x0"}];");
                }
                else
                {
                    DataBinaryTranslationGeneration.GenerateWrapperExtraMembers(fg, dataType, objGen, typeGen, passedLengthAccessor);
                    fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => _{typeGen.Name}_IsSet ? {dataAccessor}.Span[_{typeGen.Name}Location] : default;");
                }
            }
        }
예제 #11
0
        public override async Task GenerateWrite(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor writerAccessor,
            Accessor itemAccessor,
            Accessor errorMaskAccessor,
            Accessor translationMaskAccessor,
            Accessor converterAccessor)
        {
            var data = typeGen.CustomData[Constants.DataKey] as MutagenFieldData;

            if (CustomWrite != null)
            {
                if (CustomWrite(fg, objGen, typeGen, writerAccessor, itemAccessor))
                {
                    return;
                }
            }
            if (data.HasTrigger || !PreferDirectTranslation)
            {
                using (var args = new ArgsWrapper(fg,
                                                  $"{this.NamespacePrefix}{this.GetTranslatorInstance(typeGen, getter: true)}.Write{(typeGen.Nullable ? "Nullable" : null)}"))
                {
                    args.Add($"writer: {writerAccessor}");
                    args.Add($"item: {ItemWriteAccess(typeGen, itemAccessor)}");
                    if (this.DoErrorMasks)
                    {
                        if (typeGen.HasIndex)
                        {
                            args.Add($"fieldIndex: (int){typeGen.IndexEnumName}");
                        }
                        args.Add($"errorMask: {errorMaskAccessor}");
                    }
                    if (data.RecordType.HasValue &&
                        data.HandleTrigger)
                    {
                        args.Add($"header: translationParams.ConvertToCustom({objGen.RecordTypeHeaderName(data.RecordType.Value)})");
                    }
                    foreach (var writeParam in this.AdditionalWriteParams)
                    {
                        var get = writeParam(
                            objGen: objGen,
                            typeGen: typeGen);
                        if (get.Failed)
                        {
                            continue;
                        }
                        args.Add(get.Value);
                    }
                }
            }
            else if (typeGen.GetFieldData().Length > 1)
            {
                fg.AppendLine($"{writerAccessor}.Write({itemAccessor}, length: {typeGen.GetFieldData().Length});");
            }
            else
            {
                fg.AppendLine($"{writerAccessor}.Write({itemAccessor});");
            }
        }
예제 #12
0
 public override async Task <int?> ExpectedLength(ObjectGeneration objGen, TypeGeneration typeGen)
 {
     return(typeGen.GetFieldData().Length ?? this._ExpectedLength);
 }
예제 #13
0
        public override async Task GenerateWrapperFields(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor dataAccessor,
            int?currentPosition,
            string passedLengthAccessor,
            DataType dataType = null)
        {
            passedLengthAccessor ??= "0x0";
            var data = typeGen.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields(
                    fg,
                    objGen,
                    typeGen,
                    dataAccessor,
                    currentPosition,
                    passedLengthAccessor,
                    dataType);

                return;

            default:
                throw new NotImplementedException();
            }
            if (data.HasTrigger)
            {
                fg.AppendLine($"private int? _{typeGen.Name}Location;");
            }
            if (data.RecordType.HasValue)
            {
                if (dataType != null)
                {
                    throw new ArgumentException();
                }
                dataAccessor = $"{nameof(HeaderTranslation)}.{nameof(HeaderTranslation.ExtractSubrecordMemory)}({dataAccessor}, _{typeGen.Name}Location.Value, _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)})";
                fg.AppendLine($"public {typeGen.TypeName(getter: true)}{(typeGen.Nullable ? "?" : null)} {typeGen.Name} => _{typeGen.Name}Location.HasValue ? {GenerateForTypicalWrapper(objGen, typeGen, dataAccessor, "_package")} : {typeGen.GetDefault(getter: true)};");
            }
            else
            {
                var expectedLen = await this.ExpectedLength(objGen, typeGen);

                if (this.CustomWrapper != null)
                {
                    if (CustomWrapper(fg, objGen, typeGen, dataAccessor, passedLengthAccessor))
                    {
                        return;
                    }
                }
                if (dataType == null)
                {
                    if (typeGen.Nullable)
                    {
                        if (!typeGen.CanBeNullable(getter: true))
                        {
                            throw new NotImplementedException();
                            //fg.AppendLine($"public bool {typeGen.Name}_IsSet => {dataAccessor}.Length >= {(currentPosition + this.ExpectedLength(objGen, typeGen).Value)};");
                            //fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => {GenerateForTypicalWrapper(objGen, typeGen, $"{dataAccessor}.Span.Slice({currentPosition}, {this.ExpectedLength(objGen, typeGen).Value})", "_package")};");
                        }
                        else
                        {
                            string passed = int.TryParse(passedLengthAccessor.TrimStart("0x"), System.Globalization.NumberStyles.HexNumber, null, out var passedInt) ? (passedInt + expectedLen.Value).ToString() : $"({passedLengthAccessor} + {expectedLen.Value})";
                            fg.AppendLine($"public {typeGen.TypeName(getter: true)}? {typeGen.Name} => {dataAccessor}.Length >= {passed} ? {GenerateForTypicalWrapper(objGen, typeGen, $"{dataAccessor}.Slice({passedLengthAccessor}{(expectedLen != null ? $", 0x{expectedLen.Value:X}" : null)})", "_package")} : {typeGen.GetDefault(getter: true)};");
                        }
                    }
                    else if (data.IsAfterBreak)
                    {
                        fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => {dataAccessor}.Length <= {passedLengthAccessor} ? default : {GenerateForTypicalWrapper(objGen, typeGen, $"{dataAccessor}.Slice({passedLengthAccessor}{(expectedLen != null ? $", 0x{expectedLen.Value:X}" : null)})", "_package")};");
                    }
                    else
                    {
                        fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => {GenerateForTypicalWrapper(objGen, typeGen, $"{dataAccessor}.Slice({passedLengthAccessor}{(expectedLen != null ? $", 0x{expectedLen.Value:X}" : null)})", "_package")};");
                    }
                }
                else
                {
                    DataBinaryTranslationGeneration.GenerateWrapperExtraMembers(fg, dataType, objGen, typeGen, passedLengthAccessor);
                    fg.AppendLine($"public {typeGen.TypeName(getter: true)} {typeGen.Name} => _{typeGen.Name}_IsSet ? {GenerateForTypicalWrapper(objGen, typeGen, $"{dataAccessor}.Slice(_{typeGen.Name}Location{(expectedLen.HasValue ? $", {expectedLen.Value}" : null)})", "_package")} : {typeGen.GetDefault(getter: true)};");
                }
            }
        }