diff --git a/TelnetNegotiationCore.Functional/MSDPLibrary.fs b/TelnetNegotiationCore.Functional/MSDPLibrary.fs new file mode 100644 index 0000000..d64636d --- /dev/null +++ b/TelnetNegotiationCore.Functional/MSDPLibrary.fs @@ -0,0 +1,49 @@ +namespace TelnetNegotiationCore.Functional + +open System.Text + +type Trigger = + | NULL = 0uy + | MSDP_VAR = 1uy + | MSDP_VAL = 2uy + | MSDP_TABLE_OPEN = 3uy + | MSDP_TABLE_CLOSE = 4uy + | MSDP_ARRAY_OPEN = 5uy + | MSDP_ARRAY_CLOSE = 6uy + +module MSDPLibrary = + let rec MSDPScan (root: obj, array: seq, type_: Trigger, encoding : Encoding) = + if Seq.length(array) = 0 then root + else + match type_ with + | Trigger.MSDP_VAR -> + (root :?> Map).Add(encoding.GetString(array |> Seq.takeWhile(fun x -> x <> byte Trigger.MSDP_VAL) |> Array.ofSeq), MSDPScan(root, array |> Seq.skipWhile(fun x -> x <> byte Trigger.MSDP_VAL) |> Seq.skip(1), Trigger.MSDP_VAL,encoding)) + | Trigger.MSDP_VAL -> + let nextType = + try + array |> Seq.find(fun x -> + x = byte Trigger.MSDP_ARRAY_OPEN || + x = byte Trigger.MSDP_TABLE_OPEN || + x = byte Trigger.MSDP_ARRAY_CLOSE || + x = byte Trigger.MSDP_TABLE_CLOSE || + x = byte Trigger.MSDP_VAL) + with + | :? System.Collections.Generic.KeyNotFoundException -> 0uy + + match LanguagePrimitives.EnumOfValue nextType : Trigger with + | Trigger.NULL -> + encoding.GetString(array |> Array.ofSeq) + | Trigger.MSDP_VAL -> + MSDPScan((root :?> List) @ [encoding.GetString(array |> Seq.takeWhile(fun x -> x <> nextType) |> Array.ofSeq)], array |> Seq.skipWhile(fun x -> x <> byte Trigger.MSDP_VAL) |> Seq.skip(1), Trigger.MSDP_VAL, encoding) + | Trigger.MSDP_TABLE_CLOSE -> + (root :?> List) @ [encoding.GetString(array |> Seq.takeWhile(fun x -> x <> nextType) |> Array.ofSeq)] + | Trigger.MSDP_ARRAY_OPEN -> + MSDPScan(root, array |> Seq.skipWhile(fun x -> x <> byte Trigger.MSDP_ARRAY_OPEN) |> Seq.skip(1), Trigger.MSDP_ARRAY_OPEN,encoding) + | Trigger.MSDP_TABLE_OPEN -> + MSDPScan(root, array |> Seq.skipWhile(fun x -> x <> byte Trigger.MSDP_TABLE_OPEN) |> Seq.skip(1), Trigger.MSDP_TABLE_OPEN,encoding) + | _ -> root + | Trigger.MSDP_ARRAY_OPEN -> + MSDPScan(List.Empty, array |> Seq.skip(1), Trigger.MSDP_VAL, encoding) + | Trigger.MSDP_TABLE_OPEN -> + MSDPScan(Map [], array |> Seq.skip(1), Trigger.MSDP_VAR, encoding) + | _ -> failwith "Failure in MSDPScan." \ No newline at end of file diff --git a/TelnetNegotiationCore.Functional/TelnetNegotiationCore.Functional.fsproj b/TelnetNegotiationCore.Functional/TelnetNegotiationCore.Functional.fsproj new file mode 100644 index 0000000..78d27df --- /dev/null +++ b/TelnetNegotiationCore.Functional/TelnetNegotiationCore.Functional.fsproj @@ -0,0 +1,12 @@ + + + + net8.0 + true + + + + + + + diff --git a/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs b/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs index fcd9566..30e4e48 100644 --- a/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs +++ b/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs @@ -3,6 +3,7 @@ using Stateless.Graph; using System.Collections.Generic; using System.IO; +using System.Numerics; using System.Text; using System.Threading.Tasks; using TelnetNegotiationCore.Interpreters; diff --git a/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj b/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj index 74e1576..0c50924 100644 --- a/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj +++ b/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj @@ -4,6 +4,8 @@ net8.0 false + + AnyCPU diff --git a/TelnetNegotiationCore.sln b/TelnetNegotiationCore.sln index c7c48a7..d450995 100644 --- a/TelnetNegotiationCore.sln +++ b/TelnetNegotiationCore.sln @@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelnetNegotiationCore.UnitT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelnetNegotiationCore.TestClient", "TelnetNegotiationCore.TestClient\TelnetNegotiationCore.TestClient.csproj", "{E1A76C78-8246-472F-824E-9F7F9B3778B7}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TelnetNegotiationCore.Functional", "TelnetNegotiationCore.Functional\TelnetNegotiationCore.Functional.fsproj", "{0307D0B8-AAA7-40C8-9E3E-34BE64F93BB7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,6 +43,10 @@ Global {E1A76C78-8246-472F-824E-9F7F9B3778B7}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1A76C78-8246-472F-824E-9F7F9B3778B7}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1A76C78-8246-472F-824E-9F7F9B3778B7}.Release|Any CPU.Build.0 = Release|Any CPU + {0307D0B8-AAA7-40C8-9E3E-34BE64F93BB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0307D0B8-AAA7-40C8-9E3E-34BE64F93BB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0307D0B8-AAA7-40C8-9E3E-34BE64F93BB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0307D0B8-AAA7-40C8-9E3E-34BE64F93BB7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TelnetNegotiationCore/Interpreters/TelnetMSDPInterpreter.cs b/TelnetNegotiationCore/Interpreters/TelnetMSDPInterpreter.cs index 41bef4a..b6370b1 100644 --- a/TelnetNegotiationCore/Interpreters/TelnetMSDPInterpreter.cs +++ b/TelnetNegotiationCore/Interpreters/TelnetMSDPInterpreter.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Microsoft.FSharp.Collections; using MoreLinq; using OneOf; using Stateless; @@ -105,76 +106,13 @@ private void CaptureMSDPValue(OneOf b) private async Task ReadMSDPValues() { - dynamic root = new ExpandoObject(); - var array = _currentMSDPInfo.Skip(1).ToImmutableArray(); - - MSDPScan(root, array, Trigger.MSDP_VAR); + Functional.MSDPLibrary.MSDPScan(new FSharpMap(Enumerable.Empty>()), + _currentMSDPInfo.Skip(1), + Functional.Trigger.MSDP_VAL, + CurrentEncoding); await Task.CompletedTask; } - private dynamic MSDPScan(dynamic root, ImmutableArray array, Trigger type) - { - if (array.Length == 0) return root; - - if (type == Trigger.MSDP_VAR) - { - var variableName = array.TakeUntil(x => x is (byte)Trigger.MSDP_VAL).ToArray(); - ((IDictionary)root).Add(CurrentEncoding.GetString(variableName), - MSDPScan(root, array.SkipUntil(x => x is (byte)Trigger.MSDP_VAL).ToImmutableArray(), Trigger.MSDP_VAL)); - } - else if (type == Trigger.MSDP_VAL) - { - var nextType = array.FirstOrDefault(x => x is - (byte)Trigger.MSDP_ARRAY_OPEN or - (byte)Trigger.MSDP_TABLE_OPEN or - (byte)Trigger.MSDP_ARRAY_CLOSE or - (byte)Trigger.MSDP_TABLE_CLOSE or - (byte)Trigger.MSDP_VAL); - dynamic result = root; - - if (nextType == default) // We have hit the end. - { - result = CurrentEncoding.GetString(array.ToArray()); - } - else if (nextType is (byte)Trigger.MSDP_VAL) - { - var value = array.TakeWhile(x => x != nextType); - var startOfRest = array.SkipUntil(x => x is (byte)Trigger.MSDP_VAL).ToImmutableArray(); - result = MSDPScan(((ImmutableList)root).Add(CurrentEncoding.GetString(value.ToArray())), startOfRest, Trigger.MSDP_VAL); - } - else if (nextType is (byte)Trigger.MSDP_ARRAY_OPEN) - { - var startOfArray = array.SkipUntil(x => x is (byte)Trigger.MSDP_ARRAY_OPEN).ToImmutableArray(); - result = MSDPScan(root, startOfArray, Trigger.MSDP_ARRAY_OPEN); - } - else if (nextType is (byte)Trigger.MSDP_TABLE_OPEN) - { - var startOfTable = array.SkipUntil(x => x is (byte)Trigger.MSDP_TABLE_OPEN).ToImmutableArray(); - result = MSDPScan(root, startOfTable, Trigger.MSDP_ARRAY_OPEN); - } - else if (nextType is (byte)Trigger.MSDP_ARRAY_CLOSE) - { - result = root; - } - else if (nextType is (byte)Trigger.MSDP_TABLE_CLOSE) - { - result = root; - } - - return result; - } - else if (type == Trigger.MSDP_ARRAY_OPEN) - { - return MSDPScan(ImmutableList.Empty, array.Skip(1).ToImmutableArray(), Trigger.MSDP_VAL); - } - else if (type == Trigger.MSDP_TABLE_OPEN) - { - return MSDPScan(new ExpandoObject(), array.Skip(1).ToImmutableArray(), Trigger.MSDP_VAR); - } - - return root; - } - /// /// Announce we do MSDP negotiation to the client. /// diff --git a/TelnetNegotiationCore/TelnetNegotiationCore.csproj b/TelnetNegotiationCore/TelnetNegotiationCore.csproj index f020ffa..470a225 100644 --- a/TelnetNegotiationCore/TelnetNegotiationCore.csproj +++ b/TelnetNegotiationCore/TelnetNegotiationCore.csproj @@ -53,4 +53,8 @@ + + + +