|
1 | | -use aiken/builtin.{ |
2 | | - append_bytearray, choose_data, cons_bytearray, decode_utf8, index_bytearray, |
3 | | - length_of_bytearray, quotient_integer, remainder_integer, serialise_data, |
4 | | - un_b_data, un_constr_data, un_i_data, un_list_data, un_map_data, |
5 | | -} |
6 | | -use aiken/list |
| 1 | +use aiken |
| 2 | +use aiken/builtin.{decode_utf8, serialise_data} |
7 | 3 |
|
8 | 4 | /// Serialise any value to binary, encoding using [CBOR](https://www.rfc-editor.org/rfc/rfc8949). |
9 | 5 | /// |
@@ -88,181 +84,10 @@ test serialise_9() { |
88 | 84 | /// diagnostic(None) == "122([])" |
89 | 85 | /// ``` |
90 | 86 | pub fn diagnostic(self: Data) -> String { |
91 | | - do_diagnostic(self, #"") |
| 87 | + aiken.diagnostic(self, #"") |
92 | 88 | |> decode_utf8 |
93 | 89 | } |
94 | 90 |
|
95 | | -/// UTF-8 lookup table. Comes in handy to decipher the code below. |
96 | | -/// |
97 | | -/// | Symbol | Decimal | Hex | |
98 | | -/// | --- | --- | --- | |
99 | | -/// | | 32 | 0x20 | |
100 | | -/// | ' | 39 | 0x27 | |
101 | | -/// | ( | 40 | 0x28 | |
102 | | -/// | ) | 41 | 0x29 | |
103 | | -/// | , | 44 | 0x2c | |
104 | | -/// | 0 | 48 | 0x30 | |
105 | | -/// | : | 58 | 0x3a | |
106 | | -/// | A | 65 | 0x41 | |
107 | | -/// | [ | 91 | 0x5b | |
108 | | -/// | ] | 93 | 0x5d | |
109 | | -/// | _ | 95 | 0x5f | |
110 | | -/// | h | 104 | 0x68 | |
111 | | -/// | { | 123 | 0x7b | |
112 | | -/// | } | 125 | 0x7d | |
113 | | -fn do_diagnostic(self: Data, builder: ByteArray) -> ByteArray { |
114 | | - choose_data( |
115 | | - self, |
116 | | - { |
117 | | - // -------- Constr |
118 | | - let Pair(constr, fields) = un_constr_data(self) |
119 | | - |
120 | | - // NOTE: This is fundamentally the same logic for serializing list. However, the compiler |
121 | | - // doesn't support mutual recursion just yet, so we can't extract that logic in a separate |
122 | | - // function. |
123 | | - // |
124 | | - // See [aiken-lang/aiken#389](https://github.com/aiken-lang/aiken/pull/389) |
125 | | - let builder = |
126 | | - when fields is { |
127 | | - [] -> append_bytearray(#"5b5d29", builder) |
128 | | - _ -> { |
129 | | - let (_, bytes) = |
130 | | - list.foldr( |
131 | | - fields, |
132 | | - (#"5d", append_bytearray(#"29", builder)), |
133 | | - fn(e: Data, st: (ByteArray, ByteArray)) { |
134 | | - (#"2c20", do_diagnostic(e, append_bytearray(st.1st, st.2nd))) |
135 | | - }, |
136 | | - ) |
137 | | - append_bytearray(#"5b5f20", bytes) |
138 | | - } |
139 | | - } |
140 | | - |
141 | | - let constr_tag = |
142 | | - if constr < 7 { |
143 | | - 121 + constr |
144 | | - } else if constr < 128 { |
145 | | - 1280 + constr - 7 |
146 | | - } else { |
147 | | - fail @"What are you doing? No I mean, seriously." |
148 | | - } |
149 | | - |
150 | | - builder |
151 | | - |> append_bytearray(#"28", _) |
152 | | - |> from_int(constr_tag, _) |
153 | | - }, |
154 | | - { |
155 | | - // -------- Map |
156 | | - |
157 | | - let elems = un_map_data(self) |
158 | | - when elems is { |
159 | | - [] -> append_bytearray(#"7b7d", builder) |
160 | | - _ -> { |
161 | | - let (_, bytes) = |
162 | | - list.foldr( |
163 | | - elems, |
164 | | - (#"207d", builder), |
165 | | - fn(e: Pair<Data, Data>, st: (ByteArray, ByteArray)) { |
166 | | - let value = |
167 | | - do_diagnostic(e.2nd, append_bytearray(st.1st, st.2nd)) |
168 | | - ( |
169 | | - #"2c20", |
170 | | - do_diagnostic(e.1st, append_bytearray(#"3a20", value)), |
171 | | - ) |
172 | | - }, |
173 | | - ) |
174 | | - append_bytearray(#"7b5f20", bytes) |
175 | | - } |
176 | | - } |
177 | | - }, |
178 | | - { |
179 | | - // -------- List |
180 | | - |
181 | | - let elems = un_list_data(self) |
182 | | - when elems is { |
183 | | - [] -> append_bytearray(#"5b5d", builder) |
184 | | - _ -> { |
185 | | - let (_, bytes) = |
186 | | - list.foldr( |
187 | | - elems, |
188 | | - (#"5d", builder), |
189 | | - fn(e: Data, st: (ByteArray, ByteArray)) { |
190 | | - (#"2c20", do_diagnostic(e, append_bytearray(st.1st, st.2nd))) |
191 | | - }, |
192 | | - ) |
193 | | - append_bytearray(#"5b5f20", bytes) |
194 | | - } |
195 | | - } |
196 | | - }, |
197 | | - // -------- Integer |
198 | | - self |
199 | | - |> un_i_data |
200 | | - |> from_int(builder), |
201 | | - { |
202 | | - // -------- ByteArray |
203 | | - let bytes = un_b_data(self) |
204 | | - |
205 | | - bytes |
206 | | - |> encode_base16( |
207 | | - length_of_bytearray(bytes) - 1, |
208 | | - append_bytearray(#"27", builder), |
209 | | - ) |
210 | | - |> append_bytearray(#"6827", _) |
211 | | - }, |
212 | | - ) |
213 | | -} |
214 | | - |
215 | | -fn encode_base16(bytes: ByteArray, ix: Int, builder: ByteArray) -> ByteArray { |
216 | | - if ix < 0 { |
217 | | - builder |
218 | | - } else { |
219 | | - let byte = index_bytearray(bytes, ix) |
220 | | - let msb = byte / 16 |
221 | | - let lsb = byte % 16 |
222 | | - let builder = |
223 | | - cons_bytearray( |
224 | | - msb + if msb < 10 { |
225 | | - 48 |
226 | | - } else { |
227 | | - 55 |
228 | | - }, |
229 | | - cons_bytearray( |
230 | | - lsb + if lsb < 10 { |
231 | | - 48 |
232 | | - } else { |
233 | | - 55 |
234 | | - }, |
235 | | - builder, |
236 | | - ), |
237 | | - ) |
238 | | - encode_base16(bytes, ix - 1, builder) |
239 | | - } |
240 | | -} |
241 | | - |
242 | | -fn from_int(i: Int, digits: ByteArray) -> ByteArray { |
243 | | - if i == 0 { |
244 | | - append_bytearray(#"30", digits) |
245 | | - } else if i < 0 { |
246 | | - append_bytearray(#"2d", from_int(-i, digits)) |
247 | | - } else { |
248 | | - do_from_int( |
249 | | - quotient_integer(i, 10), |
250 | | - cons_bytearray(remainder_integer(i, 10) + 48, digits), |
251 | | - ) |
252 | | - } |
253 | | -} |
254 | | - |
255 | | -fn do_from_int(i: Int, digits: ByteArray) -> ByteArray { |
256 | | - if i <= 0 { |
257 | | - digits |
258 | | - } else { |
259 | | - do_from_int( |
260 | | - quotient_integer(i, 10), |
261 | | - cons_bytearray(remainder_integer(i, 10) + 48, digits), |
262 | | - ) |
263 | | - } |
264 | | -} |
265 | | - |
266 | 91 | test diagnostic_1() { |
267 | 92 | diagnostic(42) == @"42" |
268 | 93 | } |
|
0 commit comments