public override Task PostFieldLoad(ObjectGeneration obj, TypeGeneration field, XElement node) { var data = field.CustomData.TryCreateValue(Constants.DataKey, () => new MutagenFieldData(field)) as MutagenFieldData; if (node.TryGetAttribute("recordType", out string recordAttr)) { data.RecordType = new RecordType(recordAttr); } else if (node.TryGetAttribute("recordTypeHex", out string recordAttrInt)) { data.RecordType = new RecordType(Convert.ToInt32(recordAttrInt, 16)); } if (node.TryGetAttribute("overflowRecordType", out var overflow)) { data.OverflowRecordType = new RecordType(overflow.Value); } var markerAttr = node.GetAttribute("markerType"); if (markerAttr != null) { data.MarkerType = new RecordType(markerAttr); } if (obj.IsTopLevelGroup() && (field.Name?.Equals("Items") ?? false)) { DictType dict = field as DictType; LoquiType loqui = dict.ValueTypeGen as LoquiType; data.TriggeringRecordAccessors.Add($"Group<T>.T_RecordType"); } return(base.PostFieldLoad(obj, field, node)); }
public override void GenerateCopyInRet( FileGeneration fg, ObjectGeneration objGen, TypeGeneration targetGen, TypeGeneration typeGen, Accessor readerAccessor, AsyncMode asyncMode, Accessor retAccessor, Accessor outItemAccessor, Accessor errorMaskAccessor, Accessor translationAccessor, Accessor converterAccessor, bool inline) { LoquiType loqui = typeGen as LoquiType; if (inline) { if (loqui.GenericDef != null) { fg.AppendLine($"{retAccessor}{Loqui.Generation.Utility.Await(asyncMode)}LoquiBinary{(asyncMode == AsyncMode.Off ? null : "Async")}Translation<{loqui.ObjectTypeName}{loqui.GenericTypes(getter: false)}>.Instance.Parse"); } else { fg.AppendLine($"{retAccessor}{loqui.ObjectTypeName}{loqui.GenericTypes(getter: false)}.TryCreateFromBinary"); } } else { fg.AppendLine($"var ret = {loqui.ObjectTypeName}{loqui.GenericTypes(getter: false)}.TryCreateFromBinary({readerAccessor}, out var tmp{outItemAccessor}, {converterAccessor});"); fg.AppendLine($"{outItemAccessor} = tmp{outItemAccessor};"); fg.AppendLine("return ret;"); } }
public void AddMaskException(StructuredStringBuilder sb, string errorMaskAccessor, string exception, bool key) { LoquiType valueLoquiType = ValueTypeGen as LoquiType; var valStr = valueLoquiType == null ? "Exception" : $"Tuple<Exception, {valueLoquiType.TargetObjectGeneration.GetMaskString("Exception")}>"; sb.AppendLine($"{errorMaskAccessor}?.{Name}.Value.Add({(key ? "null" : exception)});"); }
public static async Task <Case> HasMajorRecords(LoquiType loqui, bool includeBaseClass, GenericSpecification specifications = null, bool includeSelf = true) { if (loqui.TargetObjectGeneration != null) { if (includeSelf && await loqui.TargetObjectGeneration.IsMajorRecord()) { return(Case.Yes); } return(await MajorRecordModule.HasMajorRecordsInTree(loqui.TargetObjectGeneration, includeBaseClass, loqui.GenericSpecification)); } else if (specifications != null) { foreach (var target in specifications.Specifications.Values) { if (!ObjectNamedKey.TryFactory(target, out var key)) { continue; } var specObj = loqui.ObjectGen.ProtoGen.Gen.ObjectGenerationsByObjectNameKey[key]; if (await specObj.IsMajorRecord()) { return(Case.Yes); } return(await MajorRecordModule.HasMajorRecordsInTree(specObj, includeBaseClass)); } } else if (loqui.RefType == LoquiType.LoquiRefType.Interface) { // ToDo // Quick hack. Real solution should use reflection to investigate the interface return(includeSelf ? Case.Yes : Case.No); } return(Case.Maybe); }
public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg) { var objData = obj.GetObjectData(); GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base"); foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true)) { LoquiType loquiType = field as LoquiType; if (loquiType == null) { switch (field) { case WrapperType wrapper: loquiType = wrapper.SubTypeGeneration as LoquiType; if (loquiType != null) { break; } continue; default: continue; } } var fieldData = loquiType.GetFieldData(); GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name); } return(base.GenerateInRegistration(obj, fg)); }
public void AddMaskException(StructuredStringBuilder sb, string errorMaskMemberAccessor, string exception, bool key) { LoquiType keyLoquiType = KeyTypeGen as LoquiType; LoquiType valueLoquiType = ValueTypeGen as LoquiType; var item2 = $"KeyValuePair<{(keyLoquiType == null ? "Exception" : keyLoquiType.TargetObjectGeneration.GetMaskString("Exception"))}, {(valueLoquiType == null ? "Exception" : valueLoquiType.TargetObjectGeneration.GetMaskString("Exception"))}>"; sb.AppendLine($"{errorMaskMemberAccessor}?.{Name}.Value.Add(new {item2}({(key ? exception : "null")}, {(key ? "null" : exception)}));"); }
public override string GenerateForTypicalWrapper( ObjectGeneration objGen, TypeGeneration typeGen, Accessor dataAccessor, Accessor packageAccessor) { LoquiType loqui = typeGen as LoquiType; return($"{this.Module.BinaryOverlayClass(loqui.TargetObjectGeneration)}.{loqui.TargetObjectGeneration.Name}Factory({dataAccessor}, {packageAccessor})"); }
public override void GenerateForCopy(FileGeneration fg, Accessor accessor, Accessor rhs, Accessor copyMaskAccessor, bool protectedMembers, bool deepCopy) { if (!deepCopy) { throw new NotImplementedException(); } if (this.Nullable) { fg.AppendLine($"if (!{rhs}.TryGet(out var rhs{this.Name}item))"); using (new BraceWrapper(fg)) { fg.AppendLine($"{accessor} = null;"); } fg.AppendLine("else"); rhs = $"rhs{this.Name}item"; } using (new BraceWrapper(fg, doIt: this.Nullable)) { using (var args = new ArgsWrapper(fg, $"{accessor} = new GenderedItem<{this.SubTypeGeneration.TypeName(getter: false, needsCovariance: true)}{this.SubTypeGeneration.NullChar}>")) { if (this.isLoquiSingle) { LoquiType loqui = this.SubTypeGeneration as LoquiType; args.Add(subFg => { loqui.GenerateTypicalMakeCopy( subFg, retAccessor: $"male: ", rhsAccessor: $"{rhs}.Male{this.SubTypeGeneration.NullChar}", copyMaskAccessor: $"{copyMaskAccessor}.Male", deepCopy: deepCopy, doTranslationMask: false); }); args.Add(subFg => { loqui.GenerateTypicalMakeCopy( subFg, retAccessor: $"female: ", rhsAccessor: $"{rhs}.Female{this.SubTypeGeneration.NullChar}", copyMaskAccessor: $"{copyMaskAccessor}.Female", deepCopy: deepCopy, doTranslationMask: false); }); } else { args.Add($"male: {this.SubTypeGeneration.GetDuplicate($"{rhs}.Male")}"); args.Add($"female: {this.SubTypeGeneration.GetDuplicate($"{rhs}.Female")}"); } } } }
public bool NeedsHeaderProcessing(LoquiType loquiGen) { if (!loquiGen.Singleton && loquiGen.TargetObjectGeneration != null && loquiGen.GetFieldData().HasTrigger && !loquiGen.TargetObjectGeneration.Abstract && loquiGen.TargetObjectGeneration.GetObjectData().TriggeringSource == null) { return(true); } return(false); }
public override void GenerateForErrorMaskCombine(StructuredStringBuilder sb, TypeGeneration field, string accessor, string retAccessor, string rhsAccessor) { LoquiType loqui = field as LoquiType; if (!IsUnknownGeneric(loqui)) { sb.AppendLine($"{retAccessor} = {accessor}.Combine({rhsAccessor}, (l, r) => l.Combine(r));"); } else { sb.AppendLine($"{retAccessor} = new MaskItem<Exception?, {loqui.Mask(MaskType.Error)}?>(ExceptionExt.Combine({accessor}.Overall, {rhsAccessor}.Overall), Loqui.Internal.LoquiHelper.Combine({accessor}.Specific, {rhsAccessor}.Specific));"); } }
public override void GenerateForTranslationMask(StructuredStringBuilder sb, TypeGeneration field) { LoquiType loqui = field as LoquiType; if (loqui.RefType == LoquiRefType.Direct) { sb.AppendLine($"public {loqui.Mask(MaskType.Translation)}? {field.Name};"); } else { sb.AppendLine($"public bool {field.Name};"); } }
public override void GenerateForTranslate(StructuredStringBuilder sb, TypeGeneration field, string retAccessor, string rhsAccessor, bool indexed) { LoquiType loqui = field as LoquiType; if (IsUnknownGeneric(loqui)) { sb.AppendLine($"{retAccessor};"); sb.AppendLine($"throw new {nameof(NotImplementedException)}();"); } else { sb.AppendLine($"{retAccessor} = {rhsAccessor} == null ? null : new MaskItem{(indexed ? "Indexed" : null)}<R, {loqui.GenerateMaskString("R")}?>({(indexed ? $"{rhsAccessor}.Index, " : null)}eval({rhsAccessor}.Overall), {rhsAccessor}.Specific?.Translate(eval));"); } }
public static async Task <bool> IsMajorRecord(this LoquiType loqui) { if (loqui.TargetObjectGeneration != null) { return(await IsMajorRecord(loqui.TargetObjectGeneration)); } else if (loqui.RefType == LoquiType.LoquiRefType.Interface) { // ToDo // Quick hack. Real solution should use reflection to investigate the interface return(true); } return(false); }
public static async IAsyncEnumerable <ObjectGeneration> IterateMajorRecords(LoquiType loqui, bool includeBaseClass, GenericSpecification specifications = null) { if (specifications?.Specifications.Count > 0) { foreach (var target in specifications.Specifications.Values) { if (!ObjectNamedKey.TryFactory(target, out var key)) { continue; } var specObj = loqui.ObjectGen.ProtoGen.Gen.ObjectGenerationsByObjectNameKey[key]; if (await specObj.IsMajorRecord()) { yield return(specObj); } await foreach (var item in IterateMajorRecords(specObj, includeBaseClass, includeSelf: true, loqui.GenericSpecification)) { yield return(item); } } } else if (loqui.TargetObjectGeneration != null) { if (await loqui.TargetObjectGeneration.IsMajorRecord()) { yield return(loqui.TargetObjectGeneration); } await foreach (var item in IterateMajorRecords(loqui.TargetObjectGeneration, includeBaseClass, includeSelf: true, loqui.GenericSpecification)) { yield return(item); } } else if (loqui.RefType == LoquiType.LoquiRefType.Interface) { // Must be a link interface if (!LinkInterfaceModule.ObjectMappings[loqui.ObjectGen.ProtoGen.Protocol].TryGetValue(loqui.SetterInterface, out var mappings)) { throw new ArgumentException(); } foreach (var obj in mappings) { yield return(obj); } } else { throw new ArgumentException(); } }
public override XElement GenerateForXSD( ObjectGeneration objGen, XElement rootElement, XElement choiceElement, TypeGeneration typeGen, string nameOverride = null) { LoquiType loqui = typeGen as LoquiType; var targetObject = loqui.TargetObjectGeneration; var targetNamespace = XmlMod.ObjectNamespace(targetObject); var diffNamespace = !targetNamespace.Equals(XmlMod.ObjectNamespace(objGen)); if (diffNamespace) { rootElement.Add( new XAttribute(XNamespace.Xmlns + $"{targetObject.Name.ToLower()}", XmlMod.ObjectNamespace(targetObject))); } FilePath xsdPath = XmlMod.ObjectXSDLocation(targetObject); var relativePath = xsdPath.GetRelativePathTo(objGen.TargetDir); var importElem = new XElement( XmlTranslationModule.XSDNamespace + "include", new XAttribute("schemaLocation", relativePath)); if (diffNamespace && !rootElement.Elements().Any((e) => e.ContentEqual(importElem))) { importElem.Add(new XAttribute("namespace", XmlMod.ObjectNamespace(targetObject))); } if (!rootElement.Elements().Any((e) => e.ContentEqual(importElem))) { rootElement.AddFirst(importElem); } var elem = new XElement( XmlTranslationModule.XSDNamespace + "element", new XAttribute("name", nameOverride ?? loqui.Name)); if (diffNamespace) { elem.Add( new XAttribute("type", $"{targetObject.Name.ToLower()}:{loqui.TargetObjectGeneration.Name}Type")); } else { elem.Add( new XAttribute("type", $"{loqui.TargetObjectGeneration.Name}Type")); } choiceElement.Add(elem); return(elem); }
private async Task LoquiTypeHandler( FileGeneration fg, Accessor loquiAccessor, LoquiType loquiType, string generic, bool checkType, ObjectGeneration targetObj = null) { // ToDo // Quick hack. Real solution should use reflection to investigate the interface if (loquiType.RefType == LoquiType.LoquiRefType.Interface) { if (checkType) { fg.AppendLine($"if (type.IsAssignableFrom({loquiAccessor}.GetType()))"); } using (new BraceWrapper(fg, doIt: checkType)) { fg.AppendLine($"yield return {loquiAccessor};"); } return; } if (loquiType.TargetObjectGeneration != null && await loquiType.TargetObjectGeneration.IsMajorRecord() && (targetObj == null || targetObj == loquiType.TargetObjectGeneration)) { if (checkType) { fg.AppendLine($"if (type.IsAssignableFrom({loquiAccessor}.GetType()))"); } using (new BraceWrapper(fg, doIt: checkType)) { fg.AppendLine($"yield return {loquiAccessor};"); } } if (await MajorRecordModule.HasMajorRecords(loquiType, includeBaseClass: true) == Case.No) { return; } fg.AppendLine($"foreach (var item in {loquiAccessor}.EnumerateMajorRecords({(generic == null ? null : "type, throwIfUnknown: false")}))"); using (new BraceWrapper(fg)) { fg.AppendLine($"yield return item;"); } }
public static string GetSubMaskString(IDictType dictType, string typeStr, bool getter) { LoquiType keyLoquiType = dictType.KeyTypeGen as LoquiType; LoquiType valueLoquiType = dictType.ValueTypeGen as LoquiType; switch (dictType.Mode) { case DictMode.KeyValue: if (valueLoquiType != null) { return($"{(valueLoquiType == null ? $"({dictType.KeyTypeGen.TypeName(getter)} Key, {typeStr} Value)" : $"MaskItemIndexed<{dictType.KeyTypeGen.TypeName(getter)}, {typeStr}, {valueLoquiType.GetMaskString(typeStr)}?>")}"); } else { string keyStr = $"{(keyLoquiType == null ? dictType.KeyTypeGen.TypeName(getter: true) : $"MaskItem<{typeStr}, {keyLoquiType.GetMaskString(typeStr)}?>")}"; string valueStr = $"{(valueLoquiType == null ? typeStr : $"MaskItem<{typeStr}, {valueLoquiType.GetMaskString(typeStr)}?>")}"; return($"KeyValuePair<{keyStr}, {valueStr}>"); }
public static async Task <bool> NeedsRecordTypeConverter(LoquiType loqui) { foreach (var field in loqui.TargetObjectGeneration.IterateFields(includeBaseClass: true)) { if (field.GetFieldData().HasTrigger) { return(true); } } foreach (var subObj in await loqui.ObjectGen.InheritingObjects()) { if (subObj.GetObjectData().BaseRecordTypeConverter != null) { return(true); } } return(false); }
public static async Task AddAsSubLoquiType(this LoquiType loqui, IEnumerable <ObjectGeneration> objGens) { var data = loqui.GetFieldData(); foreach (var subObj in objGens) { var subRecs = await subObj.TryGetTriggeringRecordTypes(); if (subRecs.Failed) { continue; } foreach (var subRec in subRecs.Value) { data.SubLoquiTypes.TryCreateValue(subRec).Add(subObj); } } }
public override void GenerateForAny(StructuredStringBuilder sb, TypeGeneration field, Accessor accessor, bool nullCheck, bool indexed) { LoquiType loqui = field as LoquiType; if (nullCheck) { sb.AppendLine($"if ({field.Name} != null)"); } using (sb.CurlyBrace(doIt: nullCheck)) { sb.AppendLine($"if (eval({accessor.Access}.Overall)) return true;"); if (!IsUnknownGeneric(loqui)) { sb.AppendLine($"if ({accessor.Access}.Specific != null && {accessor.Access}.Specific.Any(eval)) return true;"); } else { sb.AppendLine($"if (({accessor.Access}.Specific?.Any(eval) ?? false)) return true;"); } } }
public override async Task Load(XElement node, bool requireName = true) { await base.Load(node, requireName); LoquiType = this.ObjectGen.ProtoGen.Gen.GetTypeGeneration <MutagenLoquiType>(); _rawFormID = this.ObjectGen.ProtoGen.Gen.GetTypeGeneration <FormIDType>(); LoquiType.SetObjectGeneration(this.ObjectGen, setDefaults: true); LoquiType.RequireInterfaceObject = false; await LoquiType.Load(node, requireName : false); LoquiType.Name = this.Name; LoquiType.GetterInterfaceType = LoquiInterfaceType.IGetter; _rawFormID.Name = this.Name; _rawFormID.SetObjectGeneration(this.ObjectGen, false); this.NotifyingProperty.Subscribe(i => LoquiType.NotifyingProperty.OnNext(i)); this.NotifyingProperty.Subscribe(i => _rawFormID.NotifyingProperty.OnNext(i)); this.HasBeenSetProperty.Subscribe(i => LoquiType.HasBeenSetProperty.OnNext(i)); this.HasBeenSetProperty.Subscribe(i => _rawFormID.HasBeenSetProperty.OnNext(i)); this.FormIDType = node.GetAttribute <FormIDTypeEnum>("type", defaultVal: FormIDTypeEnum.Normal); this.Singleton = true; this.SetPermission = PermissionLevel.@private; }
public override bool IsAsync(TypeGeneration gen, bool read) { if (!read) { return(false); } LoquiType loqui = gen as LoquiType; if (loqui.CustomData.TryGetValue(AsyncOverrideKey, out var asyncOverride)) { return((bool)asyncOverride); } if (loqui.TargetObjectGeneration != null) { if (loqui.TargetObjectGeneration.GetObjectData().CustomBinaryEnd == CustomEnd.Async) { return(true); } return(this.Module.HasAsync(loqui.TargetObjectGeneration, self: true)); } return(false); }
public override void GenerateForEqualsMask(FileGeneration fg, Accessor accessor, Accessor rhsAccessor, string retAccessor) { LoquiType loqui = this.SubTypeGeneration as LoquiType; if (this.Nullable || loqui != null) { using (var args = new ArgsWrapper(fg, $"ret.{this.Name} = {nameof(GenderedItem)}.{nameof(GenderedItem.EqualityMaskHelper)}")) { args.Add($"lhs: {accessor}"); args.Add($"rhs: {rhsAccessor}"); if (loqui == null) { args.Add($"maskGetter: (l, r, i) => EqualityComparer<{this.SubTypeGeneration.TypeName(getter: true, needsCovariance: true)}{this.SubTypeGeneration.NullChar}>.Default.Equals(l, r)"); } else { if (this.ItemNullable) { args.Add($"maskGetter: (l, r, i) => EqualsMaskHelper.EqualsHelper(l, r, (loqLhs, loqRhs, incl) => loqLhs.GetEqualsMask(loqRhs, incl), i)"); } else { args.Add("maskGetter: (l, r, i) => l.GetEqualsMask(r, i)"); } } args.AddPassArg("include"); } } else { using (var args = new ArgsWrapper(fg, $"ret.{this.Name} = new GenderedItem<bool>")) { args.Add($"male: {this.SubTypeGeneration.GenerateEqualsSnippet($"{accessor}.Male", $"{rhsAccessor}.Male")}"); args.Add($"female: {this.SubTypeGeneration.GenerateEqualsSnippet($"{accessor}.Female", $"{rhsAccessor}.Female")}"); } } }
public void GenerateForEqualsMaskCheck(StructuredStringBuilder sb, string accessor, string rhsAccessor, string retAccessor) { LoquiType keyLoqui = KeyTypeGen as LoquiType; LoquiType valLoqui = ValueTypeGen as LoquiType; if (keyLoqui != null && valLoqui != null) { throw new NotImplementedException(); } else if (keyLoqui != null) { throw new NotImplementedException(); } else if (valLoqui != null) { using (var args = sb.Call( $"{retAccessor} = EqualsMaskHelper.DictEqualsHelper")) { args.Add($"lhs: {accessor}"); args.Add($"rhs: {rhsAccessor}"); args.Add($"maskGetter: (k, l, r) => l.GetEqualsMask(r, include)"); args.AddPassArg("include"); } } else { using (var args = sb.Call( $"{retAccessor} = EqualsMaskHelper.DictEqualsHelper")) { args.Add($"lhs: {accessor}"); args.Add($"rhs: {rhsAccessor}"); args.AddPassArg("include"); } } }
public static async Task <Case> HasLinks(LoquiType loqui, bool includeBaseClass, GenericSpecification specifications = null) { if (loqui.TargetObjectGeneration != null) { return(await HasLinks(loqui.TargetObjectGeneration, includeBaseClass, loqui.GenericSpecification)); } else if (specifications != null) { foreach (var target in specifications.Specifications.Values) { if (!ObjectNamedKey.TryFactory(target, out var key)) { continue; } var specObj = loqui.ObjectGen.ProtoGen.Gen.ObjectGenerationsByObjectNameKey[key]; return(await HasLinks(specObj, includeBaseClass)); } return(Case.Maybe); } else { return(Case.Maybe); } }
public override void GenerateForCopyMaskCtor(StructuredStringBuilder sb, TypeGeneration field, string basicValueStr, string deepCopyStr) { LoquiType loqui = field as LoquiType; if (loqui.RefType == LoquiRefType.Direct) { if (loqui.Singleton) { if (loqui.SetterInterfaceType == LoquiInterfaceType.IGetter) { return; } sb.AppendLine($"this.{field.Name} = new MaskItem<bool, {loqui.Mask(MaskType.Copy)}>({basicValueStr}, default);"); } else { sb.AppendLine($"this.{field.Name} = new MaskItem<{nameof(CopyOption)}, {loqui.Mask(MaskType.Copy)}>({deepCopyStr}, default);"); } } else { sb.AppendLine($"this.{field.Name} = {deepCopyStr};"); } }
public override void GenerateForCopyMask(StructuredStringBuilder sb, TypeGeneration field) { LoquiType loqui = field as LoquiType; if (loqui.RefType == LoquiRefType.Direct) { if (loqui.Singleton) { if (loqui.SetterInterfaceType == LoquiInterfaceType.IGetter) { return; } sb.AppendLine($"public MaskItem<bool, {loqui.Mask(MaskType.Copy)}> {field.Name};"); } else { sb.AppendLine($"public MaskItem<{nameof(CopyOption)}, {loqui.Mask(MaskType.Copy)}> {field.Name};"); } } else { sb.AppendLine($"public {nameof(CopyOption)} {field.Name};"); } }
private void GenerateWriteParallel(ObjectGeneration obj, FileGeneration fg) { LoquiType groupInstance = null; LoquiType listGroupInstance = null; var objData = obj.GetObjectData(); fg.AppendLine("const int CutCount = 100;"); using (var args = new FunctionWrapper(fg, "public static void WriteParallel")) { args.Add($"{obj.Interface(getter: true, internalInterface: false)} item"); args.Add($"Stream stream"); args.Add($"{nameof(BinaryWriteParameters)} param"); args.Add($"ModKey modKey"); } using (new BraceWrapper(fg)) { string gameConstantsStr; if (objData.GameReleaseOptions == null) { gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}"; } else { fg.AppendLine($"var gameConstants = {nameof(GameConstants)}.Get(item.{ReleaseEnumName(obj)}.ToGameRelease());"); gameConstantsStr = $"gameConstants"; } fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr});"); fg.AppendLine($"var writer = new MutagenWriter(stream, bundle);"); using (var args = new ArgsWrapper(fg, $"{nameof(ModHeaderWriteLogic)}.{nameof(ModHeaderWriteLogic.WriteHeader)}")) { args.AddPassArg("param"); args.AddPassArg("writer"); args.Add("mod: item"); args.Add("modHeader: item.ModHeader.DeepCopy()"); args.AddPassArg("modKey"); } int groupCount = obj.IterateFields() .Select(f => f as LoquiType) .Where(l => l != null) .Where(l => l.TargetObjectGeneration?.GetObjectData().ObjectType == ObjectType.Group) .Count(); fg.AppendLine($"Stream[] outputStreams = new Stream[{groupCount}];"); fg.AppendLine($"List<Action> toDo = new List<Action>();"); int i = 0; foreach (var field in obj.IterateFields()) { if (!(field is LoquiType loqui)) { continue; } if (loqui.TargetObjectGeneration?.GetObjectData().ObjectType != ObjectType.Group) { continue; } if (loqui.TargetObjectGeneration.Name == "ListGroup") { listGroupInstance = loqui; } else { groupInstance = loqui; } if (loqui.GetGroupTarget().GetObjectData().CustomBinaryEnd == CustomEnd.Off && loqui.TargetObjectGeneration.Name != "ListGroup") { fg.AppendLine($"toDo.Add(() => WriteGroupParallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams{(objData.UsesStringFiles ? ", param.StringsWriter" : null)}));"); } else { fg.AppendLine($"toDo.Add(() => Write{field.Name}Parallel(item.{field.Name}, writer.MetaData.MasterReferences!, {i}{(objData.GameReleaseOptions == null ? null : ", gameConstants")}, outputStreams));"); } i++; } fg.AppendLine("Parallel.Invoke(toDo.ToArray());"); using (var args = new ArgsWrapper(fg, $"{nameof(UtilityTranslation)}.{nameof(UtilityTranslation.CompileStreamsInto)}")) { args.Add("outputStreams.NotNull()"); args.Add("stream"); } } fg.AppendLine(); if (groupInstance != null) { using (var args = new FunctionWrapper(fg, $"public static void WriteGroupParallel<T>")) { args.Add("IGroupGetter<T> group"); args.Add($"{nameof(MasterReferenceReader)} masters"); args.Add("int targetIndex"); if (objData.GameReleaseOptions != null) { args.Add($"{nameof(GameConstants)} gameConstants"); } args.Add("Stream[] streamDepositArray"); if (objData.UsesStringFiles) { args.Add($"{nameof(StringsWriter)}? stringsWriter"); } args.Wheres.AddRange(groupInstance.TargetObjectGeneration.GenerateWhereClauses(LoquiInterfaceType.IGetter, groupInstance.TargetObjectGeneration.Generics)); } using (new BraceWrapper(fg)) { string gameConstantsStr; if (objData.GameReleaseOptions == null) { gameConstantsStr = $"{nameof(GameConstants)}.{obj.GetObjectData().GameCategory}"; } else { gameConstantsStr = "gameConstants"; } fg.AppendLine("if (group.RecordCache.Count == 0) return;"); fg.AppendLine($"var cuts = group.Cut(CutCount).ToArray();"); fg.AppendLine($"Stream[] subStreams = new Stream[cuts.Length + 1];"); fg.AppendLine($"byte[] groupBytes = new byte[{gameConstantsStr}.GroupConstants.HeaderLength];"); fg.AppendLine($"BinaryPrimitives.WriteInt32LittleEndian(groupBytes.AsSpan(), RecordTypes.GRUP.TypeInt);"); fg.AppendLine($"var groupByteStream = new MemoryStream(groupBytes);"); fg.AppendLine($"using (var stream = new MutagenWriter(groupByteStream, {gameConstantsStr}, dispose: false))"); using (new BraceWrapper(fg)) { fg.AppendLine($"stream.Position += 8;"); fg.AppendLine($"GroupBinaryWriteTranslation.WriteEmbedded<T>(group, stream);"); } fg.AppendLine($"subStreams[0] = groupByteStream;"); fg.AppendLine($"Parallel.ForEach(cuts, (cutItems, state, counter) =>"); using (new BraceWrapper(fg) { AppendSemicolon = true, AppendParenthesis = true }) { fg.AppendLine($"{nameof(MemoryTributary)} trib = new {nameof(MemoryTributary)}();"); fg.AppendLine($"var bundle = new {nameof(WritingBundle)}({gameConstantsStr})"); using (var prop = new PropertyCtorWrapper(fg)) { prop.Add($"{nameof(WritingBundle.MasterReferences)} = masters"); if (objData.UsesStringFiles) { prop.Add($"{nameof(WritingBundle.StringsWriter)} = stringsWriter"); } } fg.AppendLine($"using (var stream = new MutagenWriter(trib, bundle, dispose: false))"); using (new BraceWrapper(fg)) { fg.AppendLine($"foreach (var item in cutItems)"); using (new BraceWrapper(fg)) { fg.AppendLine($"item.WriteToBinary(stream);"); } } fg.AppendLine($"subStreams[(int)counter + 1] = trib;"); } fg.AppendLine($"UtilityTranslation.CompileSetGroupLength(subStreams, groupBytes);"); fg.AppendLine($"streamDepositArray[targetIndex] = new CompositeReadStream(subStreams, resetPositions: true);"); } fg.AppendLine(); } }
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 bool IsUnknownGeneric(LoquiType type) { return(type.RefType != LoquiRefType.Direct && type.TargetObjectGeneration == null); }