V12 / ea1357ad1734
ScenarioBindings.cs
Lilith/Core/Scenarios/ScenarioBindings.cs
Unchanged from the preceding versionCS
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace Lilith.Core.Scenarios;
internal static class ScenarioBindings
{
internal static bool ValidReference(string value) => Regex.IsMatch(value, @"^[A-Za-z][A-Za-z0-9_-]{0,63}(\.[A-Za-z][A-Za-z0-9_-]{0,63})*$");
internal static string? ResultName(XElement element)
{
string? name = (string?)element.Attribute("result");
if (name is not null && !ScenarioXmlParser.ValidName(name)) throw new InvalidDataException("Invalid result name.");
return name;
}
internal static Dictionary<string, string> ReadFields(XElement element, string child)
{
var fields = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (var field in element.Elements())
{
ScenarioXmlParser.Shape(field, child, ["name", "value"], []);
string name = (string?)field.Attribute("name") ?? "", value = (string?)field.Attribute("value") ?? throw new InvalidDataException("Missing field value.");
if (!ScenarioXmlParser.ValidName(name) || value.Length > 20000 || !fields.TryAdd(name, value)) throw new InvalidDataException("Invalid or duplicate field.");
}
if (fields.Count > 32) throw new InvalidDataException("Too many fields.");
return fields;
}
internal static string Resolve(string reference, IReadOnlyDictionary<string, string> values)
{
string[] path = reference.Split('.');
if (!ValidReference(reference) || !values.TryGetValue(path[0], out string? value)) throw new InvalidDataException("Unknown scenario value: " + reference);
if (path.Length == 1) return value;
using var doc = JsonDocument.Parse(value);
var node = doc.RootElement;
foreach (string part in path.Skip(1))
if (node.ValueKind != JsonValueKind.Object || !node.TryGetProperty(part, out node)) throw new InvalidDataException("Unknown result field: " + reference);
return node.ValueKind == JsonValueKind.String ? node.GetString()! : node.GetRawText();
}
internal static void Store(Dictionary<string, string> values, string name, string value)
{
if (value.Length > 60000) throw new InvalidDataException("Scenario result exceeds 60000 characters.");
values[name] = value;
}
}