From 997762069f39ad71d537111df07e776efc463c35 Mon Sep 17 00:00:00 2001 From: codex Date: Wed, 5 Aug 2026 16:41:46 +0300 Subject: [PATCH] feat: parse exact legacy compatibility overlays --- .../LegacyCompatibilityOverlayParser.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Launcher.Next.Application/LegacyCompatibilityOverlayParser.cs diff --git a/Launcher.Next.Application/LegacyCompatibilityOverlayParser.cs b/Launcher.Next.Application/LegacyCompatibilityOverlayParser.cs new file mode 100644 index 0000000..5b217f6 --- /dev/null +++ b/Launcher.Next.Application/LegacyCompatibilityOverlayParser.cs @@ -0,0 +1,29 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Launcher.Next.Application; + +public static class LegacyCompatibilityOverlayParser +{ + private sealed record Package(string Id,string Product,int ProductYear,string Architecture,string Channel,string Version); + private sealed record Entry(string MappingId,string Pattern,string LegacyPluginId,string? LegacyCatalog,string? LegacyInstall,Package Package); + private sealed record Document(int SchemaVersion,IReadOnlyList Mappings); + private static readonly JsonSerializerOptions Options=new(){PropertyNameCaseInsensitive=true,UnmappedMemberHandling=JsonUnmappedMemberHandling.Disallow}; + public static LegacyCompatibilityOverlay Parse(string json) + { + try + { + var document=JsonSerializer.Deserialize(json,Options)??throw new InvalidOperationException("LEGACY_OVERLAY_MALFORMED"); + if(document.SchemaVersion!=1) throw new InvalidOperationException("LEGACY_MAPPING_SCHEMA_UNSUPPORTED"); + if(document.Mappings.Count==0||document.Mappings.GroupBy(x=>x.MappingId,StringComparer.OrdinalIgnoreCase).Any(x=>x.Count()>1)) throw new InvalidOperationException("LEGACY_MAPPING_DUPLICATE"); + var entries=document.Mappings.Select(x=>{ + if(string.IsNullOrWhiteSpace(x.MappingId)||string.IsNullOrWhiteSpace(x.LegacyPluginId)||string.IsNullOrWhiteSpace(x.Package.Id)||x.Package.Version is "latest"||x.Package.Version.Contains('*')||x.Package.Version.Contains('>')||x.Package.Version.Contains('<')||!System.Text.RegularExpressions.Regex.IsMatch(x.Package.Version,@"^\d+\.\d+\.\d+(\.\d+)?$")) throw new InvalidOperationException("LEGACY_OVERLAY_MALFORMED"); + if(!string.Equals(x.Package.Product,"Plant3D",StringComparison.Ordinal)||x.Package.ProductYear!=2026||!string.Equals(x.Package.Architecture,"x64",StringComparison.OrdinalIgnoreCase)||!new[]{"pilot","stable","development"}.Contains(x.Package.Channel,StringComparer.OrdinalIgnoreCase)) throw new InvalidOperationException("LEGACY_MAPPING_INCOMPATIBLE"); + return new LegacyCompatibilityMapping(x.LegacyPluginId,x.Package.Id,x.Package.Version,x.Package.Channel); + }).ToArray(); + var first=document.Mappings[0].Package; + return new("legacy-overlay-v1",first.Product,first.ProductYear,first.Architecture,false,entries); + } + catch(JsonException){throw new InvalidOperationException("LEGACY_OVERLAY_MALFORMED");} + } +}