← All source files

V10 / 66cebf3528e0

ScenarioBindings.cs

Lilith/Core/Scenarios/ScenarioBindings.cs

Unchanged from the preceding version
CS
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;
    }
}