an atproto pds written in F# (.NET 9) 馃
pds fsharp giraffe dotnet atproto
at main 2.3 kB view raw
1namespace PDSharp.Core 2 3open System 4open System.Collections.Generic 5open System.Formats.Cbor 6open System.IO 7open System.Text 8 9module DagCbor = 10 type SortKey = { Length : int; Bytes : byte[] } 11 12 let private getSortKey (key : string) = 13 let bytes = Encoding.UTF8.GetBytes(key) 14 { Length = bytes.Length; Bytes = bytes } 15 16 let private compareKeys (a : string) (b : string) = 17 let ka = getSortKey a 18 let kb = getSortKey b 19 20 if ka.Length <> kb.Length then 21 ka.Length.CompareTo kb.Length 22 else 23 let mutable res = 0 24 let mutable i = 0 25 26 while res = 0 && i < ka.Bytes.Length do 27 res <- ka.Bytes.[i].CompareTo(kb.Bytes.[i]) 28 i <- i + 1 29 30 res 31 32 let rec private writeItem (writer : CborWriter) (item : obj) = 33 match item with 34 | null -> writer.WriteNull() 35 | :? bool as b -> writer.WriteBoolean(b) 36 | :? int as i -> writer.WriteInt32(i) 37 | :? int64 as l -> writer.WriteInt64(l) 38 | :? string as s -> writer.WriteTextString(s) 39 | :? (byte[]) as b -> writer.WriteByteString(b) 40 | :? Cid as c -> 41 let tag = LanguagePrimitives.EnumOfValue<uint64, CborTag>(42UL) 42 writer.WriteTag(tag) 43 let rawCid = c.Bytes 44 let linkBytes = Array.zeroCreate<byte> (rawCid.Length + 1) 45 linkBytes.[0] <- 0x00uy 46 Array.Copy(rawCid, 0, linkBytes, 1, rawCid.Length) 47 writer.WriteByteString(linkBytes) 48 49 | :? Map<string, obj> as m -> 50 let keys = m |> Map.toList |> List.map fst |> List.sortWith compareKeys 51 writer.WriteStartMap(keys.Length) 52 53 for k in keys do 54 writer.WriteTextString(k) 55 writeItem writer (m.[k]) 56 57 writer.WriteEndMap() 58 59 | :? IDictionary<string, obj> as d -> 60 let keys = d.Keys |> Seq.toList |> List.sortWith compareKeys 61 writer.WriteStartMap(d.Count) 62 63 for k in keys do 64 writer.WriteTextString(k) 65 writeItem writer (d.[k]) 66 67 writer.WriteEndMap() 68 69 | :? seq<obj> as l -> 70 let arr = l |> Seq.toArray 71 writer.WriteStartArray(arr.Length) 72 73 for x in arr do 74 writeItem writer x 75 76 writer.WriteEndArray() 77 78 | _ -> failwith $"Unsupported type for DAG-CBOR: {item.GetType().Name}" 79 80 let encode (data : obj) : byte[] = 81 let writer = new CborWriter(CborConformanceMode.Strict, false, false) 82 writeItem writer data 83 writer.Encode()