Factories for templates and objects, Sztl parsing
This commit is contained in:
@@ -1,6 +1,152 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Tomlyn;
|
||||
using Tomlyn.Model;
|
||||
|
||||
namespace SessionZero.Data.Sztl;
|
||||
|
||||
public static class SztlParser
|
||||
{
|
||||
public static SzTemplate ParseTemplate(string tomlText)
|
||||
{
|
||||
var doc = Toml.ToModel(tomlText);
|
||||
|
||||
|
||||
if (!doc.ContainsKey("metadata") || doc["metadata"] is not TomlTable metadata)
|
||||
{
|
||||
throw new Exception("Template missing the [metadata] section");
|
||||
}
|
||||
|
||||
// Determine template type and fill metadata
|
||||
string templateType = metadata.TryGetValue("template_type", out var tempTypeVal)
|
||||
? tempTypeVal?.ToString() ?? throw new Exception("Template missing template_type metadata")
|
||||
: throw new Exception("Template missing template_type metadata");
|
||||
|
||||
SzTemplate template = templateType switch
|
||||
{
|
||||
"data" => new SzDataObjectTemplate(),
|
||||
_ => throw new NotImplementedException($"Unknown template_type '{templateType}'")
|
||||
};
|
||||
|
||||
if (metadata.TryGetValue("id", out var idVal)) template.Id = idVal?.ToString()!;
|
||||
else throw new Exception("Template missing id metadata");
|
||||
|
||||
if (metadata.TryGetValue("uuid", out var uuidVal)) template.Uuid = uuidVal?.ToString()!;
|
||||
else throw new Exception("Template missing uuid metadata");
|
||||
|
||||
if (metadata.TryGetValue("version", out var versionVal)) template.Version = versionVal?.ToString()!;
|
||||
else throw new Exception("Template missing version metadata");
|
||||
|
||||
if (metadata.TryGetValue("compatible_systems", out var compSysVal) && compSysVal is string[] arr)
|
||||
template.CompatibleSystems = arr.ToList();
|
||||
|
||||
if (metadata.TryGetValue("description", out var descVal))
|
||||
template.Description = descVal?.ToString()!;
|
||||
else throw new Exception("Template missing description metadata");
|
||||
|
||||
template.ParseAdditionalMetaData(doc);
|
||||
|
||||
// Process all other tables as fields or groups
|
||||
ProcessTable(template, doc);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void InsertFieldIntoGroup(SzTemplate template, string[] pathParts, TomlTable table)
|
||||
{
|
||||
var groupDict = template.SubGroups;
|
||||
SztlFieldGroup currentGroup = null!;
|
||||
|
||||
for (int i = 0; i < pathParts.Length - 1; i++)
|
||||
{
|
||||
var part = pathParts[i];
|
||||
|
||||
if (!groupDict.TryGetValue(part, out var grp))
|
||||
{
|
||||
grp = new SztlFieldGroup { Id = part };
|
||||
groupDict[part] = grp;
|
||||
}
|
||||
currentGroup = grp;
|
||||
groupDict = grp.SubGroups;
|
||||
}
|
||||
|
||||
var fieldId = pathParts[^1];
|
||||
var leafTable = table;
|
||||
|
||||
if (table.TryGetValue(fieldId, out var possibleLeaf) && possibleLeaf is TomlTable t)
|
||||
{
|
||||
leafTable = t;
|
||||
}
|
||||
|
||||
var field = ParseFieldFromTable(fieldId, leafTable);
|
||||
currentGroup.Fields[fieldId] = field;
|
||||
}
|
||||
|
||||
|
||||
private static SztlField ParseFieldFromTable(string id, TomlTable table)
|
||||
{
|
||||
var field = new SztlField
|
||||
{
|
||||
Id = id
|
||||
};
|
||||
|
||||
if (!table.TryGetValue("type", out var tVal))
|
||||
{
|
||||
throw new Exception($"Field '{id}' missing type");
|
||||
}
|
||||
|
||||
var typeStr = tVal?.ToString() ?? throw new Exception($"Field '{id}' has null type");
|
||||
if (!Enum.TryParse<SzFieldType>(typeStr, ignoreCase: true, out var ftype))
|
||||
{
|
||||
throw new Exception($"Field '{id}' has unknown type '{typeStr}'");
|
||||
}
|
||||
field.Type = ftype;
|
||||
|
||||
if (table.TryGetValue("default_value", out var dVal))
|
||||
{
|
||||
field.DefaultValue = dVal;
|
||||
}
|
||||
|
||||
if (ftype == SzFieldType.Textblock)
|
||||
{
|
||||
field.IsTextBlock = true;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private static void ProcessTable(SzTemplate template, TomlTable table, string parentPath = "")
|
||||
{
|
||||
foreach (var (key, value) in table)
|
||||
{
|
||||
if (key == "metadata") continue;
|
||||
|
||||
var path = string.IsNullOrEmpty(parentPath) ? key : $"{parentPath}.{key}";
|
||||
|
||||
if (value is TomlTable t)
|
||||
{
|
||||
if (t.ContainsKey("type"))
|
||||
{
|
||||
var field = ParseFieldFromTable(key, t);
|
||||
|
||||
if (string.IsNullOrEmpty(parentPath))
|
||||
{
|
||||
template.Fields[key] = field;
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertFieldIntoGroup(template, path.Split('.'), t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessTable(template, t, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user