SpiseMisu.Apache.Thrift.Compact
0.11.5
dotnet add package SpiseMisu.Apache.Thrift.Compact --version 0.11.5
NuGet\Install-Package SpiseMisu.Apache.Thrift.Compact -Version 0.11.5
<PackageReference Include="SpiseMisu.Apache.Thrift.Compact" Version="0.11.5" />
<PackageVersion Include="SpiseMisu.Apache.Thrift.Compact" Version="0.11.5" />
<PackageReference Include="SpiseMisu.Apache.Thrift.Compact" />
paket add SpiseMisu.Apache.Thrift.Compact --version 0.11.5
#r "nuget: SpiseMisu.Apache.Thrift.Compact, 0.11.5"
#:package SpiseMisu.Apache.Thrift.Compact@0.11.5
#addin nuget:?package=SpiseMisu.Apache.Thrift.Compact&version=0.11.5
#tool nuget:?package=SpiseMisu.Apache.Thrift.Compact&version=0.11.5
SpiseMisu.Apache.Thrift.Compact
A .NET (core) encoder/decoder for the Apache Thrift Compact protocol.
Specs
THRIFT-110 > A more compact format
message => protocol-id version-and-type seq-id method-name struct-encoding
protocol-id => 0x82
version-and-type => (5-bit version identifier) (3-bit type identifier)
seq-id => varint
method-name => varint (N-byte string)
struct-encoding => field_list stop
field_list => field field_list
| field
field => type-and-id value
type-and-id => field-id-delta type-header
| 0 type-header zigzag-varint
field-id-delta => (4-bit offset from preceding field id, 1-15)
type-header => boolean-true
| boolean-false
| byte-type-header
| i16-type-header
| i32-type-header
| i64-type-header
| double-type-header
| string-type-header
| binary-type-header
| list-type-header
| set-type-header
| map-type-header
| struct-type-header
| extended-type-header
value => boolean-true
| boolean-false
| byte
| i16
| i32
| i64
| double
| string
| binary
| list
| set
| map
| struct
stop => 0x0
boolean-true => 0x1
boolean-false => 0x2
byte-type-header => 0x3
i16-type-header => 0x4
i32-type-header => 0x5
i64-type-header => 0x6
double-type-header => 0x7
binary-type-header => 0x8
string-type-header => binary-type-header
list-type-header => 0x9
set-type-header => 0xA
map-type-header => 0xB
struct-type-header => 0xC
extended-type-header => 0xF
byte => (1-byte value)
i16 => zigzag-varint
i32 => zigzag-varint
i64 => zigzag-varint
double => (8-byte double)
binary => varint(size) (bytes)
string => (utf-8 encoded) binary
list => short-list
| long-list
short-list => (4-bit size 0-14) (element)type-header
long-list => 0xf type-header varint(size - 15)
set => list
list-body => value list-body
| value
map => varint (key)type-header (value)type-header key-value-pair-list
| 0
key-value-pair-list => key-value-pair key-value-pair-list
| key-value-pair
key-value-pair => (key)value (value)value
Source: https://issues.apache.org/jira/secure/attachment/12399869/compact-proto-spec-2.txt
and
Source: https://github.com/apache/thrift/blob/master/doc/specs/thrift-compact-protocol.md
Project structure
├── SpiseMisu.Apache.Thrift.Compact
│ ├── SpiseMisu.Apache.Thrift.Compact.fsproj
│ └── compact.fs
├── SpiseMisu.Apache.Thrift.Compact.Tests
│ ├── SpiseMisu.Apache.Thrift.Compact.Tests.fsproj
│ ├── program.fs
│ └── tests.fs
├── demo
│ └── couchdb.fsx
├── imgs
│ ├── licenses
│ └── nuget
├── SpiseMisu.Apache.Thrift.Compact.sln
├── global.json
├── license.txt
├── license_cil-bytecode_agpl-3.0-only.txt
├── license_knowhow_cc-by-nc-nd-40.txt
└── readme.md
Demo
#!/usr/bin/env -S dotnet fsi --langversion:10.0 --optimize --warnaserror+:25,26 --nowarn:9,42,60,464
//#I @"../SpiseMisu.Apache.Thrift.Compact/bin/Release/net10.0/"
//#r @"SpiseMisu.Apache.Thrift.Compact.dll"
#r "nuget: SpiseMisu.Apache.Thrift.Compact, 00.11.05"
#time "on"
open System
open SpiseMisu.Apache.Thrift
open SpiseMisu.Apache.Thrift.Compact
[<RequireQualifiedAccess>]
module Hex =
open System.Numerics (* #INumberBase<'a> *)
let inline show pad (n:#INumberBase<'a>) =
let tmp =
let cs =
(int64 n).ToString "X2"
|> Seq.toArray
|> Array.rev
cs[0 .. pad - 1]
|> Array.rev
|> Array.map string
|> Array.fold (+) String.Empty
tmp.PadLeft(pad, '0')
let pprintBytes (bs:byte[]) =
bs
|> Array.chunkBySize 16
|> Array.map (
Array.map (Hex.show 2)
>> Array.reduce (sprintf "%s %s")
)
(* Apache CouchDB Thrift protocol (compact) readme and test cases:
- https://github.com/apache/couchdb-thrift-protocol/blob/main/README.md
- https://github.com/apache/couchdb-thrift-protocol/blob/main/test/
*)
let msgSam : Message =
struct
( protocolId
, Message.Type.Call
, 0
, "foo"B
, [| struct
( 1s
, Bool true
)
struct
( 2s
, I08 -1y
)
|]
)
let bseSam =
[| 0x82uy; 0x21uy; 0x00uy; 0x03uy; 0x66uy; 0x6Fuy; 0x6Fuy; 0x11uy;
0x13uy; 0xFFuy; 0x00uy;
|]
let msgTC0 : Message =
struct
( protocolId
, Message.Type.Call
, 1_000
, "foo"B
, [| struct
( 1s
, Double 123.456
)
|]
)
let bseTC0 =
[| 0x82uy; 0x21uy; 0xE8uy; 0x07uy; 0x03uy; 0x66uy; 0x6Fuy; 0x6Fuy;
0x17uy; 0x77uy; 0xBEuy; 0x9Fuy; 0x1Auy; 0x2Fuy; 0xDDuy; 0x5Euy;
0x40uy; 0x00uy;
|]
let msgTC1 : Message =
struct
( protocolId
, Message.Type.Oneway
, 1
, "emitBatch"B
, [| struct
( 1s
, Struct
[| struct
( 1s
, Struct
[| struct
( 1s
, Binary "foo_service"B
)
struct
( 2s
, Compact.List
struct
( Header.Element.Struct
, [| Struct
[| struct
( 1s
, Binary "jaeger.version"B
)
struct
( 2s
, I32 0
)
struct
( 3s
, Binary "Go-2.9.0"B
)
|];
Struct
[| struct
( 1s
, Binary "hostname"B
)
struct
( 2s
, I32 0
)
struct
( 3s
, Binary "ubu"B
)
|];
Struct
[| struct
( 1s
, Binary "ip"B
)
struct
( 2s
, I32 0
)
struct
( 3s
, Binary "10.0.2.15"B
)
|]
|]
)
)
|]
)
struct
( 2s
, Compact.List
struct
( Header.Element.Struct
, [| Struct
[| struct
( 1s
, I64 1508322611000000L
)
struct
( 2s
, I64 0L
)
struct
( 3s
, I64 789L
)
struct
( 4s
, I64 0L
)
struct
( 5s
, Binary "main"B
)
struct
( 7s
, I32 1
)
struct
( 8s
, I64 1508322611000000L
)
struct
( 9s
, I64 123456L
)
|]
|]
)
)
|]
)
|]
)
let bseTC1 =
[| 0x82uy; 0x81uy; 0x01uy; 0x09uy; 0x65uy; 0x6Duy; 0x69uy; 0x74uy;
0x42uy; 0x61uy; 0x74uy; 0x63uy; 0x68uy; 0x1Cuy; 0x1Cuy; 0x18uy;
0x0Buy; 0x66uy; 0x6Fuy; 0x6Fuy; 0x5Fuy; 0x73uy; 0x65uy; 0x72uy;
0x76uy; 0x69uy; 0x63uy; 0x65uy; 0x19uy; 0x3Cuy; 0x18uy; 0x0Euy;
0x6Auy; 0x61uy; 0x65uy; 0x67uy; 0x65uy; 0x72uy; 0x2Euy; 0x76uy;
0x65uy; 0x72uy; 0x73uy; 0x69uy; 0x6Fuy; 0x6Euy; 0x15uy; 0x00uy;
0x18uy; 0x08uy; 0x47uy; 0x6Fuy; 0x2Duy; 0x32uy; 0x2Euy; 0x39uy;
0x2Euy; 0x30uy; 0x00uy; 0x18uy; 0x08uy; 0x68uy; 0x6Fuy; 0x73uy;
0x74uy; 0x6Euy; 0x61uy; 0x6Duy; 0x65uy; 0x15uy; 0x00uy; 0x18uy;
0x03uy; 0x75uy; 0x62uy; 0x75uy; 0x00uy; 0x18uy; 0x02uy; 0x69uy;
0x70uy; 0x15uy; 0x00uy; 0x18uy; 0x09uy; 0x31uy; 0x30uy; 0x2Euy;
0x30uy; 0x2Euy; 0x32uy; 0x2Euy; 0x31uy; 0x35uy; 0x00uy; 0x00uy;
0x19uy; 0x1Cuy; 0x16uy; 0x80uy; 0xCBuy; 0xFBuy; 0x96uy; 0xF7uy;
0xF3uy; 0xADuy; 0x05uy; 0x16uy; 0x00uy; 0x16uy; 0xAAuy; 0x0Cuy;
0x16uy; 0x00uy; 0x18uy; 0x04uy; 0x6Duy; 0x61uy; 0x69uy; 0x6Euy;
0x25uy; 0x02uy; 0x16uy; 0x80uy; 0xCBuy; 0xFBuy; 0x96uy; 0xF7uy;
0xF3uy; 0xADuy; 0x05uy; 0x16uy; 0x80uy; 0x89uy; 0x0Fuy; 0x00uy;
0x00uy; 0x00uy;
|]
let _ =
let _ =
let txt = "### apache/couchdb-thrift-protocol README sample:"
let msg = msgSam
let bst = bseSam
let struct(bse, _) = Encode.toBytes msg
let struct(dec, _) = Decode.fromBytes bst
printfn "%s" txt
printfn "#### Encoded bytes:"
printfn "```"
bst
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
Seq.toArray bse = bst
|> printfn "#### Encoded message = bytes: %b"
printfn "```"
bse
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
dec = msg
|> printfn "#### Decoded bytes = message: %b"
printfn "```fsharp"
printfn "%A" dec
printfn "```"
printfn "%s" String.Empty
let _ =
let txt = "### apache/couchdb-thrift-protocol Test-case 0:"
let msg = msgTC0
let bst = bseTC0
let struct(bse, _) = Encode.toBytes msg
let struct(dec, _) = Decode.fromBytes bst
printfn "%s" txt
printfn "#### Encoded bytes:"
printfn "```"
bst
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
Seq.toArray bse = bst
|> printfn "#### Encoded message = bytes: %b"
printfn "```"
bse
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
dec = msg
|> printfn "#### Decoded bytes = message: %b"
printfn "```fsharp"
printfn "%A" dec
printfn "```"
printfn "%s" String.Empty
let _ =
let txt = "### apache/couchdb-thrift-protocol Test-case 1:"
let msg = msgTC1
let bst = bseTC1
let struct(bse, _) = Encode.toBytes msg
let struct(dec, _) = Decode.fromBytes bst
printfn "%s" txt
printfn "#### Encoded bytes:"
printfn "```"
bst
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
Seq.toArray bse = bst
|> printfn "#### Encoded message = bytes: %b"
printfn "```"
bse
|> Seq.toArray
|> pprintBytes
|> Array.iter (printfn "%s")
printfn "```"
printfn "%s" String.Empty
dec = msg
|> printfn "#### Decoded bytes = message: %b"
printfn "```fsharp"
printfn "%A" dec
printfn "```"
printfn "%s" String.Empty
00
and
apache/couchdb-thrift-protocol README sample:
Encoded bytes:
82 21 00 03 66 6F 6F 11 13 FF 00
Encoded message = bytes: true
82 21 00 03 66 6F 6F 11 13 FF 00
Decoded bytes = message: true
struct (130uy, Call, 0, [|102uy; 111uy; 111uy|],
[|struct (1s, Bool true); struct (2s, I08 -1y)|])
apache/couchdb-thrift-protocol Test-case 0:
Encoded bytes:
82 21 E8 07 03 66 6F 6F 17 77 BE 9F 1A 2F DD 5E
40 00
Encoded message = bytes: true
82 21 E8 07 03 66 6F 6F 17 77 BE 9F 1A 2F DD 5E
40 00
Decoded bytes = message: true
struct (130uy, Call, 1000, [|102uy; 111uy; 111uy|],
[|struct (1s, Double 123.456)|])
apache/couchdb-thrift-protocol Test-case 1:
Encoded bytes:
82 81 01 09 65 6D 69 74 42 61 74 63 68 1C 1C 18
0B 66 6F 6F 5F 73 65 72 76 69 63 65 19 3C 18 0E
6A 61 65 67 65 72 2E 76 65 72 73 69 6F 6E 15 00
18 08 47 6F 2D 32 2E 39 2E 30 00 18 08 68 6F 73
74 6E 61 6D 65 15 00 18 03 75 62 75 00 18 02 69
70 15 00 18 09 31 30 2E 30 2E 32 2E 31 35 00 00
19 1C 16 80 CB FB 96 F7 F3 AD 05 16 00 16 AA 0C
16 00 18 04 6D 61 69 6E 25 02 16 80 CB FB 96 F7
F3 AD 05 16 80 89 0F 00 00 00
Encoded message = bytes: true
82 81 01 09 65 6D 69 74 42 61 74 63 68 1C 1C 18
0B 66 6F 6F 5F 73 65 72 76 69 63 65 19 3C 18 0E
6A 61 65 67 65 72 2E 76 65 72 73 69 6F 6E 15 00
18 08 47 6F 2D 32 2E 39 2E 30 00 18 08 68 6F 73
74 6E 61 6D 65 15 00 18 03 75 62 75 00 18 02 69
70 15 00 18 09 31 30 2E 30 2E 32 2E 31 35 00 00
19 1C 16 80 CB FB 96 F7 F3 AD 05 16 00 16 AA 0C
16 00 18 04 6D 61 69 6E 25 02 16 80 CB FB 96 F7
F3 AD 05 16 80 89 0F 00 00 00
Decoded bytes = message: true
struct (130uy, Oneway, 1,
[|101uy; 109uy; 105uy; 116uy; 66uy; 97uy; 116uy; 99uy; 104uy|],
[|struct (1s,
Struct
[|struct (1s,
Struct
[|struct (1s,
Binary
[|102uy; 111uy; 111uy; 95uy; 115uy;
101uy; 114uy; 118uy; 105uy; 99uy;
101uy|]);
struct (2s,
List
struct (Struct,
[|Struct
[|struct (1s,
Binary
[|106uy;
97uy;
101uy;
103uy;
101uy;
114uy;
46uy;
118uy;
101uy;
114uy;
115uy;
105uy;
111uy;
110uy|]);
struct (2s, I32 0);
struct (3s,
Binary
[|71uy;
111uy;
45uy; 50uy;
46uy; 57uy;
46uy; 48uy|])|];
Struct
[|struct (1s,
Binary
[|104uy;
111uy;
115uy;
116uy;
110uy;
97uy;
109uy;
101uy|]);
struct (2s, I32 0);
struct (3s,
Binary
[|117uy;
98uy;
117uy|])|];
Struct
[|struct (1s,
Binary
[|105uy;
112uy|]);
struct (2s, I32 0);
struct (3s,
Binary
[|49uy; 48uy;
46uy; 48uy;
46uy; 50uy;
46uy; 49uy;
53uy|])|]|]))|]);
struct (2s,
List
struct (Struct,
[|Struct
[|struct (1s, I64 1508322611000000L);
struct (2s, I64 0L);
struct (3s, I64 789L);
struct (4s, I64 0L);
struct (5s,
Binary
[|109uy; 97uy; 105uy;
110uy|]);
struct (7s, I32 1);
struct (8s, I64 1508322611000000L);
struct (9s, I64 123456L)|]|]))|])|])
Licenses
Source code in this repository is ONLY covered by a Server Side Public License, v 1 while the rest (knowhow, text, media, …), is covered by the
Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International license.
However, as it's not permitted to deploy a nuget package with non OSI nor
FSF licenses. The CIL-bytecode content of the nuget package is therefore
dual-licensed under the GNU Affero General Public License v3.0 only and the rest (knowhow, text, media, …), is covered by
the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International license.
For more info on compatible nuget packages licenses, see SPDX License
List.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FSharp.Core (>= 10.0.100)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.