bbd_lib/lib.rs
1#![doc = include_str!("../README.md")]
2
3use std::sync::LazyLock;
4
5// Braille dot values given in LSB to MSB order for each "style"
6const NLBB: &[u32; 8] = &[8, 16, 32, 128, 1, 2, 4, 64];
7const NLBT: &[u32; 8] = &[128, 32, 16, 8, 64, 4, 2, 1];
8const NRBB: &[u32; 8] = &[1, 2, 4, 64, 8, 16, 32, 128];
9const NRBT: &[u32; 8] = &[64, 4, 2, 1, 128, 32, 16, 8];
10
11// BCD
12const TENS: &[u8] = &[0x00, 0x40, 0x04, 0x44, 0x02, 0x42, 0x06, 0x46, 0x01, 0x41];
13const ONES: &[u8] = &[0x00, 0x80, 0x20, 0xA0, 0x10, 0x90, 0x30, 0xB0, 0x08, 0x88];
14
15// Encode
16static ENCODE_NLBB: LazyLock<Vec<(u8, u32)>> = LazyLock::new(|| style_encode(*NLBB));
17static ENCODE_NLBT: LazyLock<Vec<(u8, u32)>> = LazyLock::new(|| style_encode(*NLBT));
18static ENCODE_NRBB: LazyLock<Vec<(u8, u32)>> = LazyLock::new(|| style_encode(*NRBB));
19static ENCODE_NRBT: LazyLock<Vec<(u8, u32)>> = LazyLock::new(|| style_encode(*NRBT));
20
21// Decode
22static DECODE_NLBB: LazyLock<Vec<(u8, u8)>> = LazyLock::new(|| style_decode(*NLBB));
23static DECODE_NLBT: LazyLock<Vec<(u8, u8)>> = LazyLock::new(|| style_decode(*NLBT));
24static DECODE_NRBB: LazyLock<Vec<(u8, u8)>> = LazyLock::new(|| style_decode(*NRBB));
25static DECODE_NRBT: LazyLock<Vec<(u8, u8)>> = LazyLock::new(|| style_decode(*NRBT));
26
27pub type EncodeFn = fn(u8) -> char;
28pub type DecodeFn = fn(char) -> u8;
29
30/**
31Translate a [`u8`] to binary representation using the `bcd` encoding
32
33`bcd`: binary coded decimal
34
35Tens | Ones
36---|---
37n/a | 8
3864 | 4
3932 | 2
4016 | 1
41
42```
43use bbd_lib::*;
44
45assert_eq!(
46 (0..=99).map(|x| encode_bcd(x)).collect::<String>(),
47 "\
48 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊\
49 ⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉\
50 ",
51);
52
53// All byte values greater than 99 panic:
54assert!(
55 (100..=255)
56 .all(|x| std::panic::catch_unwind(|| encode_bcd(x)).is_err()),
57);
58```
59
60# Panics
61
62Panics if the given `u8` is not in the range 0-99 or is not able to convert the calculated `u32`
63value into a `char`
64*/
65#[must_use]
66pub fn encode_bcd(decimal: u8) -> char {
67 assert!(
68 decimal < 100,
69 "Invalid BCD value: {decimal}! Must be in range `0..=99`.",
70 );
71 let d = decimal as usize;
72 let tens = d / 10;
73 let ones = d - tens * 10;
74 char::from_u32(0x2800 + u32::from(TENS[tens]) + u32::from(ONES[ones])).unwrap()
75}
76
77/**
78Translate a binary representation to [`u8`] using the `bcd` encoding
79
80`bcd`: binary coded decimal
81
82Tens | Ones
83---|---
84n/a | 8
8564 | 4
8632 | 2
8716 | 1
88
89```
90use bbd_lib::*;
91
92assert_eq!(
93 "\
94 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊\
95 ⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉\
96 ".chars().map(|x| decode_bcd(x)).collect::<Vec<u8>>(),
97 (0..=99).collect::<Vec<u8>>(),
98);
99```
100
101# Panics
102
103Panics if not able to convert the given BCD `char` to its associated `u8` "value"
104*/
105#[must_use]
106pub fn decode_bcd(c: char) -> u8 {
107 let b = decode_direct(c);
108 let mut decimal: u8 = 0;
109 for (i, tens) in TENS.iter().enumerate().rev() {
110 if b & *tens == *tens {
111 let i = u8::try_from(i).unwrap();
112 decimal += i * 10;
113 break;
114 }
115 }
116 for (i, ones) in ONES.iter().enumerate().rev() {
117 if b & *ones == *ones {
118 let i = u8::try_from(i).unwrap();
119 decimal += i;
120 break;
121 }
122 }
123 decimal
124}
125
126/**
127Translate a [`u8`] to binary representation using the `direct` encoding
128
129Left | Right
130---|---
1311 | 8
1322 | 16
1334 | 32
13464 | 128
135
136```
137use bbd_lib::*;
138
139assert_eq!(
140 (0..=255).map(|x| encode_direct(x)).collect::<String>(),
141 "\
142 ⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿\
143 ⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿\
144 ⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿\
145 ⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿\
146 ",
147);
148```
149*/
150#[allow(clippy::missing_panics_doc)]
151#[must_use]
152pub fn encode_direct(b: u8) -> char {
153 char::from_u32(u32::from(b) + 0x2800).unwrap()
154}
155
156/**
157Translate a binary representation to a [`u8`] using the `direct` encoding
158
159Left | Right
160---|---
1611 | 8
1622 | 16
1634 | 32
16464 | 128
165
166```
167use bbd_lib::*;
168
169assert_eq!(
170 "\
171 ⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿\
172 ⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿\
173 ⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿\
174 ⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿\
175 ".chars().map(|x| decode_direct(x)).collect::<Vec<u8>>(),
176 (0..=255).collect::<Vec<u8>>(),
177);
178```
179
180# Panics
181
182Panics if given `char` is not in the range 0x2800-0x28FF
183*/
184#[must_use]
185pub fn decode_direct(c: char) -> u8 {
186 let v = u32::from(c);
187 assert!(
188 (0x2800..=0x28FF).contains(&v),
189 "char is not in range 0x2800-0x28FF",
190 );
191 u8::try_from(v - 0x2800).unwrap()
192}
193
194/**
195Core of `encode_{nlbb,nlbt,nrbb,nrbt}` functions
196*/
197fn encode_nb(b: u8, values: &[(u8, u32)]) -> char {
198 char::from_u32(values.iter().fold(
199 0x2800,
200 |s, (from, to)| {
201 if b & *from == *from { s + *to } else { s }
202 },
203 ))
204 .unwrap()
205}
206
207/**
208Core of `decode_{nlbb,nlbt,nrbb,nrbt}` functions
209*/
210fn decode_nb(c: char, values: &[(u8, u8)]) -> u8 {
211 let b = decode_direct(c);
212 values.iter().fold(
213 0,
214 |s, (from, to)| {
215 if b & *from == *from { s + *to } else { s }
216 },
217 )
218}
219
220/**
221Translate a [`u8`] to binary representation using the `nlbb` encoding
222
223`nlbb`: most significant nibble left, most significant bit bottom
224
225Left | Right
226---|---
22716 | 1
22832 | 2
22964 | 4
230128 | 8
231
232```
233use bbd_lib::*;
234
235assert_eq!(
236 (0..=255).map(|x| encode_nlbb(x)).collect::<String>(),
237 "\
238 ⠀⠈⠐⠘⠠⠨⠰⠸⢀⢈⢐⢘⢠⢨⢰⢸⠁⠉⠑⠙⠡⠩⠱⠹⢁⢉⢑⢙⢡⢩⢱⢹⠂⠊⠒⠚⠢⠪⠲⠺⢂⢊⢒⢚⢢⢪⢲⢺⠃⠋⠓⠛⠣⠫⠳⠻⢃⢋⢓⢛⢣⢫⢳⢻\
239 ⠄⠌⠔⠜⠤⠬⠴⠼⢄⢌⢔⢜⢤⢬⢴⢼⠅⠍⠕⠝⠥⠭⠵⠽⢅⢍⢕⢝⢥⢭⢵⢽⠆⠎⠖⠞⠦⠮⠶⠾⢆⢎⢖⢞⢦⢮⢶⢾⠇⠏⠗⠟⠧⠯⠷⠿⢇⢏⢗⢟⢧⢯⢷⢿\
240 ⡀⡈⡐⡘⡠⡨⡰⡸⣀⣈⣐⣘⣠⣨⣰⣸⡁⡉⡑⡙⡡⡩⡱⡹⣁⣉⣑⣙⣡⣩⣱⣹⡂⡊⡒⡚⡢⡪⡲⡺⣂⣊⣒⣚⣢⣪⣲⣺⡃⡋⡓⡛⡣⡫⡳⡻⣃⣋⣓⣛⣣⣫⣳⣻\
241 ⡄⡌⡔⡜⡤⡬⡴⡼⣄⣌⣔⣜⣤⣬⣴⣼⡅⡍⡕⡝⡥⡭⡵⡽⣅⣍⣕⣝⣥⣭⣵⣽⡆⡎⡖⡞⡦⡮⡶⡾⣆⣎⣖⣞⣦⣮⣶⣾⡇⡏⡗⡟⡧⡯⡷⡿⣇⣏⣗⣟⣧⣯⣷⣿\
242 ",
243);
244```
245*/
246#[must_use]
247pub fn encode_nlbb(b: u8) -> char {
248 encode_nb(b, &ENCODE_NLBB)
249}
250
251/**
252Translate a binary representation to [`u8`] using the `nlbb` encoding
253
254`nlbb`: most significant nibble left, most significant bit bottom
255
256Left | Right
257---|---
25816 | 1
25932 | 2
26064 | 4
261128 | 8
262
263```
264use bbd_lib::*;
265
266assert_eq!(
267 "\
268 ⠀⠈⠐⠘⠠⠨⠰⠸⢀⢈⢐⢘⢠⢨⢰⢸⠁⠉⠑⠙⠡⠩⠱⠹⢁⢉⢑⢙⢡⢩⢱⢹⠂⠊⠒⠚⠢⠪⠲⠺⢂⢊⢒⢚⢢⢪⢲⢺⠃⠋⠓⠛⠣⠫⠳⠻⢃⢋⢓⢛⢣⢫⢳⢻\
269 ⠄⠌⠔⠜⠤⠬⠴⠼⢄⢌⢔⢜⢤⢬⢴⢼⠅⠍⠕⠝⠥⠭⠵⠽⢅⢍⢕⢝⢥⢭⢵⢽⠆⠎⠖⠞⠦⠮⠶⠾⢆⢎⢖⢞⢦⢮⢶⢾⠇⠏⠗⠟⠧⠯⠷⠿⢇⢏⢗⢟⢧⢯⢷⢿\
270 ⡀⡈⡐⡘⡠⡨⡰⡸⣀⣈⣐⣘⣠⣨⣰⣸⡁⡉⡑⡙⡡⡩⡱⡹⣁⣉⣑⣙⣡⣩⣱⣹⡂⡊⡒⡚⡢⡪⡲⡺⣂⣊⣒⣚⣢⣪⣲⣺⡃⡋⡓⡛⡣⡫⡳⡻⣃⣋⣓⣛⣣⣫⣳⣻\
271 ⡄⡌⡔⡜⡤⡬⡴⡼⣄⣌⣔⣜⣤⣬⣴⣼⡅⡍⡕⡝⡥⡭⡵⡽⣅⣍⣕⣝⣥⣭⣵⣽⡆⡎⡖⡞⡦⡮⡶⡾⣆⣎⣖⣞⣦⣮⣶⣾⡇⡏⡗⡟⡧⡯⡷⡿⣇⣏⣗⣟⣧⣯⣷⣿\
272 ".chars().map(|x| decode_nlbb(x)).collect::<Vec<u8>>(),
273 (0..=255).collect::<Vec<u8>>());
274```
275*/
276#[must_use]
277pub fn decode_nlbb(c: char) -> u8 {
278 decode_nb(c, &DECODE_NLBB)
279}
280
281/**
282Translate a [`u8`] to binary representation using the `nlbt` encoding
283
284`nlbt`: most significant nibble left, most significant bit top
285
286Left | Right
287---|---
288128 | 8
28964 | 4
29032 | 2
29116 | 1
292
293```
294use bbd_lib::*;
295
296assert_eq!(
297 (0..=255).map(|x| encode_nlbt(x)).collect::<String>(),
298 "\
299 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⠨⢨⠘⢘⠸⢸⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⡨⣨⡘⣘⡸⣸⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⠬⢬⠜⢜⠼⢼⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⡬⣬⡜⣜⡼⣼\
300 ⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊⠪⢪⠚⢚⠺⢺⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⡪⣪⡚⣚⡺⣺⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⠮⢮⠞⢞⠾⢾⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⡮⣮⡞⣞⡾⣾\
301 ⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⠩⢩⠙⢙⠹⢹⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉⡩⣩⡙⣙⡹⣹⠅⢅⠥⢥⠕⢕⠵⢵⠍⢍⠭⢭⠝⢝⠽⢽⡅⣅⡥⣥⡕⣕⡵⣵⡍⣍⡭⣭⡝⣝⡽⣽\
302 ⠃⢃⠣⢣⠓⢓⠳⢳⠋⢋⠫⢫⠛⢛⠻⢻⡃⣃⡣⣣⡓⣓⡳⣳⡋⣋⡫⣫⡛⣛⡻⣻⠇⢇⠧⢧⠗⢗⠷⢷⠏⢏⠯⢯⠟⢟⠿⢿⡇⣇⡧⣧⡗⣗⡷⣷⡏⣏⡯⣯⡟⣟⡿⣿\
303 ",
304);
305```
306*/
307#[must_use]
308pub fn encode_nlbt(b: u8) -> char {
309 encode_nb(b, &ENCODE_NLBT)
310}
311
312/**
313Translate a binary representation to [`u8`] using the `nlbt` encoding
314
315`nlbt`: most significant nibble left, most significant bit top
316
317Left | Right
318---|---
319128 | 8
32064 | 4
32132 | 2
32216 | 1
323
324```
325use bbd_lib::*;
326
327assert_eq!(
328 "\
329 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⠨⢨⠘⢘⠸⢸⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⡨⣨⡘⣘⡸⣸⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⠬⢬⠜⢜⠼⢼⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⡬⣬⡜⣜⡼⣼\
330 ⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊⠪⢪⠚⢚⠺⢺⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⡪⣪⡚⣚⡺⣺⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⠮⢮⠞⢞⠾⢾⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⡮⣮⡞⣞⡾⣾\
331 ⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⠩⢩⠙⢙⠹⢹⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉⡩⣩⡙⣙⡹⣹⠅⢅⠥⢥⠕⢕⠵⢵⠍⢍⠭⢭⠝⢝⠽⢽⡅⣅⡥⣥⡕⣕⡵⣵⡍⣍⡭⣭⡝⣝⡽⣽\
332 ⠃⢃⠣⢣⠓⢓⠳⢳⠋⢋⠫⢫⠛⢛⠻⢻⡃⣃⡣⣣⡓⣓⡳⣳⡋⣋⡫⣫⡛⣛⡻⣻⠇⢇⠧⢧⠗⢗⠷⢷⠏⢏⠯⢯⠟⢟⠿⢿⡇⣇⡧⣧⡗⣗⡷⣷⡏⣏⡯⣯⡟⣟⡿⣿\
333 ".chars().map(|x| decode_nlbt(x)).collect::<Vec<u8>>(),
334 (0..=255).collect::<Vec<u8>>());
335```
336*/
337#[must_use]
338pub fn decode_nlbt(c: char) -> u8 {
339 decode_nb(c, &DECODE_NLBT)
340}
341
342/**
343Translate a [`u8`] to binary representation using the `nrbb` encoding
344
345`nrbb`: most significant nibble right, most significant bit bottom
346
347Left | Right
348---|---
3491 | 16
3502 | 32
3514 | 64
3528 | 128
353
354```
355use bbd_lib::*;
356
357assert_eq!(
358 (0..=255).map(|x| encode_nrbb(x)).collect::<String>(),
359 "\
360 ⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟\
361 ⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿\
362 ⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟\
363 ⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿\
364 ",
365);
366```
367*/
368#[must_use]
369pub fn encode_nrbb(b: u8) -> char {
370 encode_nb(b, &ENCODE_NRBB)
371}
372
373/**
374Translate a binary representation to [`u8`] using the `nrbb` encoding
375
376`nrbb`: most significant nibble right, most significant bit bottom
377
378Left | Right
379---|---
3801 | 16
3812 | 32
3824 | 64
3838 | 128
384
385```
386use bbd_lib::*;
387
388assert_eq!(
389 "\
390 ⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟\
391 ⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿\
392 ⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟\
393 ⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿\
394 ".chars().map(|x| decode_nrbb(x)).collect::<Vec<u8>>(),
395 (0..=255).collect::<Vec<u8>>(),
396);
397```
398*/
399#[must_use]
400pub fn decode_nrbb(c: char) -> u8 {
401 decode_nb(c, &DECODE_NRBB)
402}
403
404/**
405Translate a [`u8`] to binary representation using the `nrbt` encoding
406
407`nrbt`: most significant nibble right, most significant bit top
408
409Left | Right
410---|---
4118 | 128
4124 | 64
4132 | 32
4141 | 16
415
416```
417use bbd_lib::*;
418
419assert_eq!(
420 (0..=255).map(|x| encode_nrbt(x)).collect::<String>(),
421 "\
422 ⠀⡀⠄⡄⠂⡂⠆⡆⠁⡁⠅⡅⠃⡃⠇⡇⢀⣀⢄⣄⢂⣂⢆⣆⢁⣁⢅⣅⢃⣃⢇⣇⠠⡠⠤⡤⠢⡢⠦⡦⠡⡡⠥⡥⠣⡣⠧⡧⢠⣠⢤⣤⢢⣢⢦⣦⢡⣡⢥⣥⢣⣣⢧⣧\
423 ⠐⡐⠔⡔⠒⡒⠖⡖⠑⡑⠕⡕⠓⡓⠗⡗⢐⣐⢔⣔⢒⣒⢖⣖⢑⣑⢕⣕⢓⣓⢗⣗⠰⡰⠴⡴⠲⡲⠶⡶⠱⡱⠵⡵⠳⡳⠷⡷⢰⣰⢴⣴⢲⣲⢶⣶⢱⣱⢵⣵⢳⣳⢷⣷\
424 ⠈⡈⠌⡌⠊⡊⠎⡎⠉⡉⠍⡍⠋⡋⠏⡏⢈⣈⢌⣌⢊⣊⢎⣎⢉⣉⢍⣍⢋⣋⢏⣏⠨⡨⠬⡬⠪⡪⠮⡮⠩⡩⠭⡭⠫⡫⠯⡯⢨⣨⢬⣬⢪⣪⢮⣮⢩⣩⢭⣭⢫⣫⢯⣯\
425 ⠘⡘⠜⡜⠚⡚⠞⡞⠙⡙⠝⡝⠛⡛⠟⡟⢘⣘⢜⣜⢚⣚⢞⣞⢙⣙⢝⣝⢛⣛⢟⣟⠸⡸⠼⡼⠺⡺⠾⡾⠹⡹⠽⡽⠻⡻⠿⡿⢸⣸⢼⣼⢺⣺⢾⣾⢹⣹⢽⣽⢻⣻⢿⣿\
426 ",
427);
428```
429*/
430#[must_use]
431pub fn encode_nrbt(b: u8) -> char {
432 encode_nb(b, &ENCODE_NRBT)
433}
434
435/**
436Translate a binary representation to [`u8`] using the `nrbt` encoding
437
438`nrbt`: most significant nibble right, most significant bit top
439
440Left | Right
441---|---
4428 | 128
4434 | 64
4442 | 32
4451 | 16
446
447```
448use bbd_lib::*;
449
450assert_eq!(
451 "\
452 ⠀⡀⠄⡄⠂⡂⠆⡆⠁⡁⠅⡅⠃⡃⠇⡇⢀⣀⢄⣄⢂⣂⢆⣆⢁⣁⢅⣅⢃⣃⢇⣇⠠⡠⠤⡤⠢⡢⠦⡦⠡⡡⠥⡥⠣⡣⠧⡧⢠⣠⢤⣤⢢⣢⢦⣦⢡⣡⢥⣥⢣⣣⢧⣧\
453 ⠐⡐⠔⡔⠒⡒⠖⡖⠑⡑⠕⡕⠓⡓⠗⡗⢐⣐⢔⣔⢒⣒⢖⣖⢑⣑⢕⣕⢓⣓⢗⣗⠰⡰⠴⡴⠲⡲⠶⡶⠱⡱⠵⡵⠳⡳⠷⡷⢰⣰⢴⣴⢲⣲⢶⣶⢱⣱⢵⣵⢳⣳⢷⣷\
454 ⠈⡈⠌⡌⠊⡊⠎⡎⠉⡉⠍⡍⠋⡋⠏⡏⢈⣈⢌⣌⢊⣊⢎⣎⢉⣉⢍⣍⢋⣋⢏⣏⠨⡨⠬⡬⠪⡪⠮⡮⠩⡩⠭⡭⠫⡫⠯⡯⢨⣨⢬⣬⢪⣪⢮⣮⢩⣩⢭⣭⢫⣫⢯⣯\
455 ⠘⡘⠜⡜⠚⡚⠞⡞⠙⡙⠝⡝⠛⡛⠟⡟⢘⣘⢜⣜⢚⣚⢞⣞⢙⣙⢝⣝⢛⣛⢟⣟⠸⡸⠼⡼⠺⡺⠾⡾⠹⡹⠽⡽⠻⡻⠿⡿⢸⣸⢼⣼⢺⣺⢾⣾⢹⣹⢽⣽⢻⣻⢿⣿\
456 ".chars().map(|x| decode_nrbt(x)).collect::<Vec<u8>>(),
457 (0..=255).collect::<Vec<u8>>(),
458);
459```
460*/
461#[must_use]
462pub fn decode_nrbt(c: char) -> u8 {
463 decode_nb(c, &DECODE_NRBT)
464}
465
466/**
467Encode bytes to binary representation using the given function with optional wrapping
468
469```
470use bbd_lib::*;
471
472let bcd_content = (0..=99).collect::<Vec<u8>>();
473let bytes_content = (0..=255).collect::<Vec<u8>>();
474let cases: Vec<(&[u8], EncodeFn, &str)> = vec![
475 (
476 &bcd_content,
477 encode_bcd,
478 "\
479 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊\
480 ⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉\
481 ",
482 ),
483 (
484 &bytes_content,
485 encode_direct,
486 "\
487 ⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿\
488 ⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿\
489 ⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿\
490 ⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿\
491 ",
492 ),
493 (
494 &bytes_content,
495 encode_nlbb,
496 "\
497 ⠀⠈⠐⠘⠠⠨⠰⠸⢀⢈⢐⢘⢠⢨⢰⢸⠁⠉⠑⠙⠡⠩⠱⠹⢁⢉⢑⢙⢡⢩⢱⢹⠂⠊⠒⠚⠢⠪⠲⠺⢂⢊⢒⢚⢢⢪⢲⢺⠃⠋⠓⠛⠣⠫⠳⠻⢃⢋⢓⢛⢣⢫⢳⢻\
498 ⠄⠌⠔⠜⠤⠬⠴⠼⢄⢌⢔⢜⢤⢬⢴⢼⠅⠍⠕⠝⠥⠭⠵⠽⢅⢍⢕⢝⢥⢭⢵⢽⠆⠎⠖⠞⠦⠮⠶⠾⢆⢎⢖⢞⢦⢮⢶⢾⠇⠏⠗⠟⠧⠯⠷⠿⢇⢏⢗⢟⢧⢯⢷⢿\
499 ⡀⡈⡐⡘⡠⡨⡰⡸⣀⣈⣐⣘⣠⣨⣰⣸⡁⡉⡑⡙⡡⡩⡱⡹⣁⣉⣑⣙⣡⣩⣱⣹⡂⡊⡒⡚⡢⡪⡲⡺⣂⣊⣒⣚⣢⣪⣲⣺⡃⡋⡓⡛⡣⡫⡳⡻⣃⣋⣓⣛⣣⣫⣳⣻\
500 ⡄⡌⡔⡜⡤⡬⡴⡼⣄⣌⣔⣜⣤⣬⣴⣼⡅⡍⡕⡝⡥⡭⡵⡽⣅⣍⣕⣝⣥⣭⣵⣽⡆⡎⡖⡞⡦⡮⡶⡾⣆⣎⣖⣞⣦⣮⣶⣾⡇⡏⡗⡟⡧⡯⡷⡿⣇⣏⣗⣟⣧⣯⣷⣿\
501 ",
502 ),
503 (
504 &bytes_content,
505 encode_nlbt,
506 "\
507 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⠨⢨⠘⢘⠸⢸⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⡨⣨⡘⣘⡸⣸⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⠬⢬⠜⢜⠼⢼⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⡬⣬⡜⣜⡼⣼\
508 ⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊⠪⢪⠚⢚⠺⢺⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⡪⣪⡚⣚⡺⣺⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⠮⢮⠞⢞⠾⢾⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⡮⣮⡞⣞⡾⣾\
509 ⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⠩⢩⠙⢙⠹⢹⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉⡩⣩⡙⣙⡹⣹⠅⢅⠥⢥⠕⢕⠵⢵⠍⢍⠭⢭⠝⢝⠽⢽⡅⣅⡥⣥⡕⣕⡵⣵⡍⣍⡭⣭⡝⣝⡽⣽\
510 ⠃⢃⠣⢣⠓⢓⠳⢳⠋⢋⠫⢫⠛⢛⠻⢻⡃⣃⡣⣣⡓⣓⡳⣳⡋⣋⡫⣫⡛⣛⡻⣻⠇⢇⠧⢧⠗⢗⠷⢷⠏⢏⠯⢯⠟⢟⠿⢿⡇⣇⡧⣧⡗⣗⡷⣷⡏⣏⡯⣯⡟⣟⡿⣿\
511 ",
512 ),
513 (
514 &bytes_content,
515 encode_nrbb,
516 "\
517 ⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟\
518 ⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿\
519 ⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟\
520 ⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿\
521 ",
522 ),
523 (
524 &bytes_content,
525 encode_nrbt,
526 "\
527 ⠀⡀⠄⡄⠂⡂⠆⡆⠁⡁⠅⡅⠃⡃⠇⡇⢀⣀⢄⣄⢂⣂⢆⣆⢁⣁⢅⣅⢃⣃⢇⣇⠠⡠⠤⡤⠢⡢⠦⡦⠡⡡⠥⡥⠣⡣⠧⡧⢠⣠⢤⣤⢢⣢⢦⣦⢡⣡⢥⣥⢣⣣⢧⣧\
528 ⠐⡐⠔⡔⠒⡒⠖⡖⠑⡑⠕⡕⠓⡓⠗⡗⢐⣐⢔⣔⢒⣒⢖⣖⢑⣑⢕⣕⢓⣓⢗⣗⠰⡰⠴⡴⠲⡲⠶⡶⠱⡱⠵⡵⠳⡳⠷⡷⢰⣰⢴⣴⢲⣲⢶⣶⢱⣱⢵⣵⢳⣳⢷⣷\
529 ⠈⡈⠌⡌⠊⡊⠎⡎⠉⡉⠍⡍⠋⡋⠏⡏⢈⣈⢌⣌⢊⣊⢎⣎⢉⣉⢍⣍⢋⣋⢏⣏⠨⡨⠬⡬⠪⡪⠮⡮⠩⡩⠭⡭⠫⡫⠯⡯⢨⣨⢬⣬⢪⣪⢮⣮⢩⣩⢭⣭⢫⣫⢯⣯\
530 ⠘⡘⠜⡜⠚⡚⠞⡞⠙⡙⠝⡝⠛⡛⠟⡟⢘⣘⢜⣜⢚⣚⢞⣞⢙⣙⢝⣝⢛⣛⢟⣟⠸⡸⠼⡼⠺⡺⠾⡾⠹⡹⠽⡽⠻⡻⠿⡿⢸⣸⢼⣼⢺⣺⢾⣾⢹⣹⢽⣽⢻⣻⢿⣿\
531 ",
532 ),
533];
534for (content, convert_byte, result) in cases {
535 assert_eq!(encode(content, convert_byte, 0, 0), result);
536}
537```
538*/
539pub fn encode(
540 content: &[u8],
541 convert_byte: EncodeFn,
542 columns: usize,
543 prev_content_length: usize,
544) -> String {
545 let wrapping = columns > 0;
546 let mut c = if wrapping {
547 prev_content_length - (prev_content_length / columns) * columns
548 } else {
549 0
550 };
551
552 let mut r = String::with_capacity(4 * content.len());
553 for b in content {
554 r.push(convert_byte(*b));
555
556 if wrapping {
557 c += 1;
558 if c >= columns {
559 r.push_str("\\\n");
560 c = 0;
561 }
562 }
563 }
564
565 r
566}
567
568/**
569Decode binary representation to bytes using the given function with optional wrapping
570
571```
572use bbd_lib::*;
573
574let bcd_content = (0..=99).collect::<Vec<u8>>();
575let bytes_content = (0..=255).collect::<Vec<u8>>();
576let cases: Vec<(&str, DecodeFn, &[u8])> = vec![
577 (
578 "\
579 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊\
580 ⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉\
581 ",
582 decode_bcd,
583 &bcd_content,
584 ),
585 (
586 "\
587 ⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿\
588 ⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿\
589 ⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿\
590 ⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿\
591 ",
592 decode_direct,
593 &bytes_content,
594 ),
595 (
596 "\
597 ⠀⠈⠐⠘⠠⠨⠰⠸⢀⢈⢐⢘⢠⢨⢰⢸⠁⠉⠑⠙⠡⠩⠱⠹⢁⢉⢑⢙⢡⢩⢱⢹⠂⠊⠒⠚⠢⠪⠲⠺⢂⢊⢒⢚⢢⢪⢲⢺⠃⠋⠓⠛⠣⠫⠳⠻⢃⢋⢓⢛⢣⢫⢳⢻\
598 ⠄⠌⠔⠜⠤⠬⠴⠼⢄⢌⢔⢜⢤⢬⢴⢼⠅⠍⠕⠝⠥⠭⠵⠽⢅⢍⢕⢝⢥⢭⢵⢽⠆⠎⠖⠞⠦⠮⠶⠾⢆⢎⢖⢞⢦⢮⢶⢾⠇⠏⠗⠟⠧⠯⠷⠿⢇⢏⢗⢟⢧⢯⢷⢿\
599 ⡀⡈⡐⡘⡠⡨⡰⡸⣀⣈⣐⣘⣠⣨⣰⣸⡁⡉⡑⡙⡡⡩⡱⡹⣁⣉⣑⣙⣡⣩⣱⣹⡂⡊⡒⡚⡢⡪⡲⡺⣂⣊⣒⣚⣢⣪⣲⣺⡃⡋⡓⡛⡣⡫⡳⡻⣃⣋⣓⣛⣣⣫⣳⣻\
600 ⡄⡌⡔⡜⡤⡬⡴⡼⣄⣌⣔⣜⣤⣬⣴⣼⡅⡍⡕⡝⡥⡭⡵⡽⣅⣍⣕⣝⣥⣭⣵⣽⡆⡎⡖⡞⡦⡮⡶⡾⣆⣎⣖⣞⣦⣮⣶⣾⡇⡏⡗⡟⡧⡯⡷⡿⣇⣏⣗⣟⣧⣯⣷⣿\
601 ",
602 decode_nlbb,
603 &bytes_content,
604 ),
605 (
606 "\
607 ⠀⢀⠠⢠⠐⢐⠰⢰⠈⢈⠨⢨⠘⢘⠸⢸⡀⣀⡠⣠⡐⣐⡰⣰⡈⣈⡨⣨⡘⣘⡸⣸⠄⢄⠤⢤⠔⢔⠴⢴⠌⢌⠬⢬⠜⢜⠼⢼⡄⣄⡤⣤⡔⣔⡴⣴⡌⣌⡬⣬⡜⣜⡼⣼\
608 ⠂⢂⠢⢢⠒⢒⠲⢲⠊⢊⠪⢪⠚⢚⠺⢺⡂⣂⡢⣢⡒⣒⡲⣲⡊⣊⡪⣪⡚⣚⡺⣺⠆⢆⠦⢦⠖⢖⠶⢶⠎⢎⠮⢮⠞⢞⠾⢾⡆⣆⡦⣦⡖⣖⡶⣶⡎⣎⡮⣮⡞⣞⡾⣾\
609 ⠁⢁⠡⢡⠑⢑⠱⢱⠉⢉⠩⢩⠙⢙⠹⢹⡁⣁⡡⣡⡑⣑⡱⣱⡉⣉⡩⣩⡙⣙⡹⣹⠅⢅⠥⢥⠕⢕⠵⢵⠍⢍⠭⢭⠝⢝⠽⢽⡅⣅⡥⣥⡕⣕⡵⣵⡍⣍⡭⣭⡝⣝⡽⣽\
610 ⠃⢃⠣⢣⠓⢓⠳⢳⠋⢋⠫⢫⠛⢛⠻⢻⡃⣃⡣⣣⡓⣓⡳⣳⡋⣋⡫⣫⡛⣛⡻⣻⠇⢇⠧⢧⠗⢗⠷⢷⠏⢏⠯⢯⠟⢟⠿⢿⡇⣇⡧⣧⡗⣗⡷⣷⡏⣏⡯⣯⡟⣟⡿⣿\
611 ",
612 decode_nlbt,
613 &bytes_content,
614 ),
615 (
616 "\
617 ⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙⡚⡛⡜⡝⡞⡟\
618 ⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿\
619 ⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟\
620 ⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿\
621 ",
622 decode_nrbb,
623 &bytes_content,
624 ),
625 (
626 "\
627 ⠀⡀⠄⡄⠂⡂⠆⡆⠁⡁⠅⡅⠃⡃⠇⡇⢀⣀⢄⣄⢂⣂⢆⣆⢁⣁⢅⣅⢃⣃⢇⣇⠠⡠⠤⡤⠢⡢⠦⡦⠡⡡⠥⡥⠣⡣⠧⡧⢠⣠⢤⣤⢢⣢⢦⣦⢡⣡⢥⣥⢣⣣⢧⣧\
628 ⠐⡐⠔⡔⠒⡒⠖⡖⠑⡑⠕⡕⠓⡓⠗⡗⢐⣐⢔⣔⢒⣒⢖⣖⢑⣑⢕⣕⢓⣓⢗⣗⠰⡰⠴⡴⠲⡲⠶⡶⠱⡱⠵⡵⠳⡳⠷⡷⢰⣰⢴⣴⢲⣲⢶⣶⢱⣱⢵⣵⢳⣳⢷⣷\
629 ⠈⡈⠌⡌⠊⡊⠎⡎⠉⡉⠍⡍⠋⡋⠏⡏⢈⣈⢌⣌⢊⣊⢎⣎⢉⣉⢍⣍⢋⣋⢏⣏⠨⡨⠬⡬⠪⡪⠮⡮⠩⡩⠭⡭⠫⡫⠯⡯⢨⣨⢬⣬⢪⣪⢮⣮⢩⣩⢭⣭⢫⣫⢯⣯\
630 ⠘⡘⠜⡜⠚⡚⠞⡞⠙⡙⠝⡝⠛⡛⠟⡟⢘⣘⢜⣜⢚⣚⢞⣞⢙⣙⢝⣝⢛⣛⢟⣟⠸⡸⠼⡼⠺⡺⠾⡾⠹⡹⠽⡽⠻⡻⠿⡿⢸⣸⢼⣼⢺⣺⢾⣾⢹⣹⢽⣽⢻⣻⢿⣿\
631 ",
632 decode_nrbt,
633 &bytes_content,
634 ),
635];
636for (content, convert_byte, result) in cases {
637 assert_eq!(decode(content, convert_byte), result);
638}
639```
640*/
641pub fn decode(content: &str, convert_char: DecodeFn) -> Vec<u8> {
642 let mut r = Vec::with_capacity(content.len() / 4);
643 for c in content.chars() {
644 if !['\\', '\n'].contains(&c) {
645 r.push(convert_char(c));
646 }
647 }
648 r
649}
650
651/**
652Process a style definition into a list of from/to conversion values for encoding
653*/
654fn style_encode(values: [u32; 8]) -> Vec<(u8, u32)> {
655 values
656 .iter()
657 .copied()
658 .enumerate()
659 .map(|(i, v)| (1 << i, v))
660 .collect()
661}
662
663/**
664Process a style definition into a list of from/to conversion values for decoding
665*/
666fn style_decode(values: [u32; 8]) -> Vec<(u8, u8)> {
667 values
668 .iter()
669 .copied()
670 .enumerate()
671 .map(|(i, v)| (u8::try_from(v).unwrap(), 1 << i))
672 .collect()
673}