-
Notifications
You must be signed in to change notification settings - Fork 4
/
cbe.dogma
195 lines (178 loc) · 9.59 KB
/
cbe.dogma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
dogma_v1 utf-8
- identifier = cbe_v1
- description = Concise Binary Encoding, version 1
- reference = https://concise-encoding.org
- dogma = https://github.com/kstenerud/dogma/blob/master/v1/dogma_v1.0.md
document = byte_order(lsb, ordered_document);
ordered_document = u8(0x81) & uleb(version)
& (padding | record_type)*
& (data_object ! local_reference)
;
version = 1;
data_object = padding* & (markable(data_type) | reference_type);
keyable_object = padding* & (markable(keyable_type) | local_reference);
non_null_object = padding* & (markable(data_type ! null) | reference_type);
markable(type) = marked_object(type) | type;
data_type = keyable_type | array_type | media | custom_type | list | map | record | edge | node | null;
keyable_type = boolean | integer | uid | date | time | timestamp | string | resource_id;
reference_type = local_reference | remote_reference;
array_type = array_short_s8 | array_chunked_s8
| array_short_s16 | array_chunked_s16
| array_short_s32 | array_chunked_s32
| array_short_s64 | array_chunked_s64
| array_chunked_u8
| array_short_u16 | array_chunked_u16
| array_short_u32 | array_chunked_u32
| array_short_u64 | array_chunked_u64
| array_short_f16 | array_chunked_f16
| array_short_f32 | array_chunked_f32
| array_short_f64 | array_chunked_f64
| array_short_uid | array_chunked_uid
| array_bit
;
null = u8(0x7d);
boolean = true | false;
false = u8(0x78);
true = u8(0x79);
integer = int_small
| int_8_positive
| int_8_negative
| int_16_positive
| int_16_negative
| int_32_positive
| int_32_negative
| int_64_positive
| int_64_negative
| int_vlength_positive
| int_vlength_negative
;
float = decimal_float
| binary_float_16
| binary_float_32
| binary_float_64
;
int_small = s8(-100~100);
int_8_positive = u8(0x68) & u8(~);
int_8_negative = u8(0x69) & u8(~);
int_16_positive = u8(0x6a) & u16(~);
int_16_negative = u8(0x6b) & u16(~);
int_32_positive = u8(0x6c) & u32(~);
int_32_negative = u8(0x6d) & u32(~);
int_64_positive = u8(0x6e) & u64(~);
int_64_negative = u8(0x6f) & u64(~);
int_vlength_positive = u8(0x66) & var(pref,length_prefix) & ordered(uint(pref.length*8, ~));
int_vlength_negative = u8(0x67) & var(pref,length_prefix) & ordered(uint(pref.length*8, ~));
decimal_float = u8(0x76) & compact_float(~);
binary_float_16 = u8(0x70) & f16(~);
binary_float_32 = u8(0x71) & f32(~);
binary_float_64 = u8(0x72) & f64(~);
uid = u8(0x65) & uint(128, ~); # Note: big endian
date = u8(0x7a) & compact_date;
time = u8(0x7b) & compact_time;
timestamp = u8(0x7c) & compact_timestamp;
array_short_uid = u8(0x7f) & u4(0) & array_short(uid(~));
array_short_s8 = u8(0x7f) & u4(1) & array_short(s8(~));
array_short_u16 = u8(0x7f) & u4(2) & array_short(u16(~));
array_short_s16 = u8(0x7f) & u4(3) & array_short(s16(~));
array_short_u32 = u8(0x7f) & u4(4) & array_short(u32(~));
array_short_s32 = u8(0x7f) & u4(5) & array_short(s32(~));
array_short_u64 = u8(0x7f) & u4(6) & array_short(u64(~));
array_short_s64 = u8(0x7f) & u4(7) & array_short(s64(~));
array_short_f16 = u8(0x7f) & u4(8) & array_short(f16(~));
array_short_f32 = u8(0x7f) & u4(9) & array_short(f32(~));
array_short_f64 = u8(0x7f) & u4(10) & array_short(f64(~));
array_chunked_u8 = u8(0x93) & array_chunk(u8(~));
array_chunked_uid = plane7f(0xe0) & array_chunk(uid(~));
array_chunked_s8 = plane7f(0xe1) & array_chunk(s8(~));
array_chunked_u16 = plane7f(0xe2) & array_chunk(u16(~));
array_chunked_s16 = plane7f(0xe3) & array_chunk(s16(~));
array_chunked_u32 = plane7f(0xe4) & array_chunk(u32(~));
array_chunked_s32 = plane7f(0xe5) & array_chunk(s32(~));
array_chunked_u64 = plane7f(0xe6) & array_chunk(u64(~));
array_chunked_s64 = plane7f(0xe7) & array_chunk(s64(~));
array_chunked_f16 = plane7f(0xe8) & array_chunk(f16(~));
array_chunked_f32 = plane7f(0xe9) & array_chunk(f32(~));
array_chunked_f64 = plane7f(0xea) & array_chunk(f64(~));
array_chunk(type) = var(header, array_chunk_header)
& type{header.count}
& [header.continuation = 1: array_chunk(type);]
;
array_chunk_header = uleb128(uany(var(count, ~)) & u1(var(continuation, ~)));
array_short(type) = u4(var(count, ~)) & type{count};
# Non-terminating bit array chunks must be a multiple of 8 bits
array_bit = u8(0x94) & array_bit_chunk* array_bit_chunk_last;
array_bit_chunk = uleb128(uany(var(count, mult_8(~))) & u1(1))
& reversed(1, u1(~){count})
;
array_bit_chunk_last = uleb128(uany(var(count, ~)) & u1(0))
& aligned(8, reversed(1, u1(~){count}), u1(0)*)
;
mult_8(v) = [v%8 = 0: v;]; # Require the value to be a multiple of 8
string_chunk = var(header, array_chunk_header)
& sized(header.count*8, char_string*)
& [header.continuation = 1: string_chunk;]
;
string = string_short | string_chunked;
string_short = u4(8) & u4(var(count, ~)) & sized(count*8, char_string*);
string_chunked = u8(0x90) & string_chunk;
resource_id = u8(0x91) & string_chunk;
media = plane7f(0xf3)
& var(pref,length_prefix)
& sized(pref.length*8, media_type)
& array_chunk(u8(~))
;
media_type = media_type_word & '/' & media_type_word;
media_type_word = char_media_first & char_media_next*;
custom_type = u8(0x92) & custom_type_code & array_chunk(u8(~));
custom_type_code = uleb(~);
list = u8(0x9a) & data_object* & end_container;
map = u8(0x99) & key_value* & end_container;
key_value = keyable_object & data_object;
record = u8(0x96) & identifier & data_object* & end_container;
edge = u8(0x97) & non_null_object & data_object & non_null_object & end_container;
node = u8(0x98) & data_object & (node | data_object)* & end_container;
end_container = u8(0x9b);
local_reference = u8(0x77) & identifier;
remote_reference = plane7f(0xf2) & string_chunk;
padding = u8(0x95);
record_type = plane7f(0xf1) & identifier & keyable_object* & end_container;
marked_object(type) = plane7f(0xf0) & identifier & type;
identifier = var(pref,length_prefix)
& sized(pref.length*8, (char_identifier_first & char_identifier_next*)?)
;
length_prefix = uleb(var(length, 1~));
plane7f(v) = u8(0x7f) & u8(v);
s8(v) = sint(8, v);
s16(v) = ordered(sint(16, v));
s32(v) = ordered(sint(32, v));
s64(v) = ordered(sint(64, v));
u1(v) = uint(1, v);
u4(v) = uint(4, v);
u8(v) = uint(8, v);
u16(v) = ordered(uint(16, v));
u32(v) = ordered(uint(32, v));
u64(v) = ordered(uint(64, v));
uany(v) = uint(~,v);
f16(v) = ordered(bfloat(v));
f32(v) = ordered(float(32, v));
f64(v) = ordered(float(64, v));
uleb(v) = uleb128(uany(v));
# https://www.rfc-editor.org/rfc/rfc2045#section-5.1
char_media_first = 'a'~'z' | 'A'~'Z';
char_media_next = ('!' ~ '~') ! ( '(' | ')' | '<' | '>'
| '@' | ',' | ';' | ':'
| '\\' | '"' | '/' | '['
| ']' | '?' | '='
) # tspecials in RFC 2045
;
char_rid = """https://www.rfc-editor.org/rfc/rfc3987""";
char_sentinel = unicode(L,M,N,P,S);
char_identifier_first = unicode(L,N) | '_';
char_identifier_next = unicode(Cf,L,M,N) | '_' | '.' | '-';
char_string = unicode(C,L,M,N,P,S,Z);
bfloat(v: number): bits = """https://en.wikipedia.org/wiki/Bfloat16_floating-point_format""";
uleb128(v: bits): bits = """https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128""";
compact_float(v: number): bits = """https://github.com/kstenerud/compact-float/blob/master/compact-float-specification.md""";
compact_date: bits = """https://github.com/kstenerud/compact-time/blob/master/compact-time-specification.md#compact-time""";
compact_time: bits = """https://github.com/kstenerud/compact-time/blob/master/compact-time-specification.md#compact-date""";
compact_timestamp: bits = """https://github.com/kstenerud/compact-time/blob/master/compact-time-specification.md#compact-timestamp""";