1use anyhow::{Result, bail};
44
45use crate::bail_if_none;
46use crate::formats::unicode::{
47 js_like_slice_utf16, string_to_scalars, ucs2encode,
48};
49
50#[derive(Debug, Clone, Copy)]
51struct CpValue {
52 value: u32,
53 cp: u32,
54}
55
56const AS_START: CpValue = CpValue {
59 value: 0x0000,
60 cp: 0xF0000,
61};
62
63fn noncont() -> [CpValue; 4] {
65 [
66 CpValue {
67 value: 0xFFFE,
68 cp: 0xF80A,
69 },
70 CpValue {
71 value: 0xFFFF,
72 cp: 0xF80B,
73 },
74 CpValue {
75 value: 0x1FFFE,
76 cp: 0xF80C,
77 },
78 CpValue {
79 value: 0x1FFFF,
80 cp: 0xF80D,
81 },
82 ]
83}
84
85fn char_bytes(segm_cp: &Vec<u16>) -> usize {
87 if fixed_char_code_at(segm_cp, 0).is_ok()
88 && fixed_char_code_at(segm_cp, 1).is_ok()
89 {
90 2
91 } else {
92 1
93 }
94}
95
96fn char_bytes_fixed(segm_cp: &[u16]) -> u8 {
98 let code = *(segm_cp
99 .first()
100 .expect("Call should have included a segment"));
101 if (0xD800..=0xDBFF).contains(&code) || (0xDC00..=0xDFFF).contains(&code) {
102 2
103 } else {
104 1
105 }
106}
107
108fn invert_val(segm_val: u32, base: u32) -> u32 {
110 2u32.pow(base) - (segm_val + 1)
111}
112
113fn from_code_point(segm_cp: &[u16], bytes: u8) -> Result<u32> {
115 let code = fixed_char_code_at(segm_cp, 0)?;
117 if bytes == 2 {
118 return Ok(code - AS_START.cp);
119 }
120 for nc in &noncont() {
121 if nc.cp == code {
124 return Ok(nc.value);
125 }
126 }
127 bail!(format!("from_code_point: unknown code point {segm_cp:?}"))
128}
129
130fn to_code_point(segm_val: u32, base: u32) -> u32 {
132 if base < 16 {
134 AS_START.cp + segm_val
135 } else {
136 for nc in &noncont() {
137 if nc.value == segm_val {
139 return nc.cp;
140 }
141 }
142 AS_START.cp + segm_val
143 }
144}
145
146fn fixed_from_char_code(code_pt: u32) -> String {
148 std::char::from_u32(code_pt)
149 .map_or_else(|| String::from("\u{FFFD}"), |c| c.to_string())
150}
151
152fn fixed_char_code_at(str_: &[u16], idx: usize) -> Result<u32> {
154 if idx >= str_.len() {
156 return Err(anyhow::anyhow!("index out of bounds"));
157 }
158 let code = u32::from(str_[idx]);
159 if (0xD800..=0xDBFF).contains(&code) {
160 if idx + 1 < str_.len() {
162 let hi = code;
163 let low = u32::from(str_[idx + 1]);
164 return Ok(((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000);
165 }
166 }
167 if (0xDC00..=0xDFFF).contains(&code) {
168 if idx >= 1 {
170 let hi = u32::from(str_[idx - 1]);
171 let low = code;
172 return Ok(((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000);
173 }
174 }
175 Ok(code)
176}
177
178pub fn encode(input_arr: &[u8], base: u32) -> Result<String> {
181 if !(7..=17).contains(&base) {
189 bail!("invalid base".to_string());
190 }
191 let base_usize = usize::try_from(base)?;
192 let mut result_arr: Vec<String> = Vec::new();
193 let full_segments = input_arr.len() / base_usize;
194 let remain_bits = input_arr.len() - (full_segments * base_usize);
195 for segment in 0..full_segments {
196 let segmstart = base_usize * segment;
197 let currsegm = &input_arr[segmstart..segmstart + base_usize];
198 let mut segm_val = 0u32;
199 for (bit_idx, &b) in currsegm.iter().enumerate() {
200 let shift = u32::try_from((base_usize - 1) - bit_idx)?;
201 segm_val += u32::from(b) << shift;
202 }
203 let cp = to_code_point(segm_val, base);
204 result_arr.push(fixed_from_char_code(cp));
205 }
206 let segmstart = base_usize * full_segments;
208 let currsegm = &input_arr[segmstart..];
209 let mut segm_val = 0u32;
212 if remain_bits > 0 {
213 for (bit_idx, &b) in currsegm.iter().enumerate() {
214 let shift = u32::try_from((remain_bits - 1) - bit_idx)?;
215 segm_val += u32::from(b) << shift;
216 }
217 }
218 let term_cp = to_code_point(invert_val(segm_val, base), base);
219 result_arr.push(fixed_from_char_code(term_cp));
220 Ok(result_arr.concat())
221}
222
223pub fn decode(
237 input_str: &str,
238 remainder_length: Option<u32>,
239) -> Result<Vec<u8>> {
240 let input_str = ucs2encode(&string_to_scalars(input_str))?;
241 let original_api = remainder_length.is_none();
242 let mut result_arr: Vec<u8> = Vec::new();
243 let term_char_bytes = char_bytes_fixed(&input_str[input_str.len() - 1..]);
244 let term_char_bytes_usize: usize = term_char_bytes.into();
245 let term_char_cp = &input_str[input_str.len() - term_char_bytes_usize..];
246 let term_char_val = from_code_point(term_char_cp, term_char_bytes)?;
247 let mut bit: u32 = 17;
248 let base: u32;
249 while bit >= 7 && (term_char_val / 2u32.pow(bit - 1)) == 0 {
251 bit -= 1;
252 }
253 if (7..=17).contains(&bit) {
254 base = bit;
255 } else {
256 bail!("invalid base decoded");
257 }
258 let mut bytes_used: usize = 0;
259 let full_bytes = input_str.len() - term_char_bytes_usize;
260 while bytes_used < full_bytes {
261 let curr_char_bytes =
263 char_bytes_fixed(&input_str[bytes_used..=bytes_used]); let curr_char_bytes_usize: usize = curr_char_bytes.into();
265 let segment_bit_length: u32 = if original_api {
266 u32::from(curr_char_bytes) * 8
267 } else {
268 base
269 };
270 let segment =
271 &input_str[bytes_used..bytes_used + curr_char_bytes_usize];
272 let segm_val = from_code_point(segment, curr_char_bytes)?;
273 let sbl_usize = usize::try_from(segment_bit_length)?;
275 for bit_pos_usize in (0..sbl_usize).rev() {
276 let bit_pos = u32::try_from(bit_pos_usize)?;
277 let raw: u32 =
278 u32::try_from(((u64::from(segm_val)) / 2u64.pow(bit_pos)) % 2)?;
279 let decoded_bit = u8::try_from(raw)?;
280 if !original_api && decoded_bit > 1 {
281 bail!("Found incorrect bit while decoding");
282 }
283 result_arr.push(decoded_bit);
284 }
285 bytes_used += curr_char_bytes_usize;
286 }
287 let remain_val = invert_val(term_char_val, base); let mut bit: i16 = i16::from(term_char_bytes * 8) - 1;
290 if (bit > 0) && !original_api {
291 bit = i16::try_from(bail_if_none!(remainder_length))? - 1;
292 }
293 if bit >= 0 {
294 while bit >= 0 {
295 result_arr.push(
296 ((remain_val / 2u32.pow(bit.try_into()?)) % 2).try_into()?,
297 );
298 bit -= 1;
299 }
300 }
301 Ok(result_arr)
302}
303
304pub fn true_length(input_str: &str) -> usize {
306 let str_bytes = ucs2encode(&string_to_scalars(input_str))
312 .expect("Rust string should already be valid")
313 .len();
314 let mut str_length = 0;
315 let mut tally_bytes = 0;
316 while tally_bytes < str_bytes {
317 let slice_end = if tally_bytes + 2 > input_str.len() {
318 input_str.len()
319 } else {
320 tally_bytes + 2
321 };
322 let slice = js_like_slice_utf16(input_str, tally_bytes, slice_end);
325 let char_bytes = char_bytes(&slice);
326 tally_bytes += char_bytes;
327 str_length += 1;
328 }
329 str_length
330}
331
332#[cfg(test)]
333mod tests {
334 use crate::formats::assert_string_ok_eq;
335 use crate::utilities::assert_vec_u8_ok_eq;
336
337 use super::*;
338
339 #[crate::ctb_test]
340 fn test_char_bytes() {
341 assert_eq!(char_bytes(&"a".encode_utf16().collect()), 1);
342 assert_eq!(char_bytes(&"𠜎".encode_utf16().collect()), 2);
343 assert_eq!(char_bytes(&"🥴".encode_utf16().collect()), 2);
344 }
345
346 #[crate::ctb_test]
347 fn test_true_length() {
348 assert_eq!(true_length("aa"), 1);
349 assert_eq!(true_length("a𠜎"), 2);
350 assert_eq!(true_length("a🥴"), 2);
351 }
352
353 #[crate::ctb_test]
354
355 fn test_encode_decode() {
356 let input = vec![
360 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1,
376 ];
377 let expected7 = "\u{f0074}\u{f000b}\u{f005d}\u{f0076}\u{f0000}\u{f0066}\u{f0078}\u{f004a}\u{f0000}\u{f0029}\u{f0009}\u{f0027}\u{f0031}\u{f0068}\u{f0068}\u{f0045}\u{f0060}\u{f005b}\u{f007c}";
378 let expected8 = "\u{f00e8}\u{f002e}\u{f00ef}\u{f0060}\u{f0019}\u{f00bc}\u{f004a}\u{f0000}\u{f00a4}\u{f004a}\u{f0076}\u{f003a}\u{f0034}\u{f0045}\u{f00c1}\u{f006f}\u{f00ff}";
379 let expected9 = "\u{f01d0}\u{f00bb}\u{f017b}\u{f0001}\u{f0137}\u{f0112}\u{f0100}\u{f00a4}\u{f0094}\u{f01d8}\u{f01d1}\u{f0144}\u{f00b8}\u{f005b}\u{f01fc}";
380 let expected10 = "\u{f03a0}\u{f02ee}\u{f03d8}\u{f0019}\u{f02f1}\u{f00a0}\u{f0029}\u{f004a}\u{f01d8}\u{f03a3}\u{f0111}\u{f01c1}\u{f0390}";
381 let expected11 = "\u{f0741}\u{f03bb}\u{f06c0}\u{f019b}\u{f0625}\u{f0002}\u{f0489}\u{f0276}\u{f01d1}\u{f0511}\u{f0382}\u{f0790}";
382 let expected12 = "\u{f0e82}\u{f0eef}\u{f0601}\u{f09bc}\u{f04a0}\u{f00a4}\u{f04a7}\u{f063a}\u{f0344}\u{f05c1}\u{f0f90}";
383 let expected13 = "\u{f1d05}\u{f1bbd}\u{f100c}\u{f1bc4}\u{f1401}\u{f0912}\u{f13b1}\u{f1a34}\u{f08b8}\u{f1e90}";
384 let expected14 = "\u{f3a0b}\u{f2ef6}\u{f0066}\u{f3c4a}\u{f0029}\u{f04a7}\u{f18e8}\u{f3445}\u{f305b}\u{f3ffc}";
385 let expected15 = "\u{f7417}\u{f3bd8}\u{f0337}\u{f44a0}\u{f0522}\u{f29d8}\u{f7468}\u{f45c1}\u{f7f90}";
386 let expected16 = "\u{fe82e}\u{fef60}\u{f19bc}\u{f4a00}\u{fa44a}\u{f763a}\u{f3445}\u{fc16f}\u{f80b}";
387 let expected17 = "\u{10d05d}\u{10bd80}\u{fcde2}\u{fa00a}\u{f894e}\u{108e8d}\u{f22e0}\u{10fe90}";
388
389 assert!(encode(&input, 6).is_err());
390 assert!(encode(&input, 18).is_err());
391 let result7 = assert_string_ok_eq(expected7, encode(&input, 7));
392 let result8 = assert_string_ok_eq(expected8, encode(&input, 8));
393 let result9 = assert_string_ok_eq(expected9, encode(&input, 9));
394 let result10 = assert_string_ok_eq(expected10, encode(&input, 10));
395 let result11 = assert_string_ok_eq(expected11, encode(&input, 11));
396 let result12 = assert_string_ok_eq(expected12, encode(&input, 12));
397 let result13 = assert_string_ok_eq(expected13, encode(&input, 13));
398 let result14 = assert_string_ok_eq(expected14, encode(&input, 14));
399 let result15 = assert_string_ok_eq(expected15, encode(&input, 15));
400 let result16 = assert_string_ok_eq(expected16, encode(&input, 16));
401 let result17 = assert_string_ok_eq(expected17, encode(&input, 17));
402
403 assert!(decode("abcd", None).is_err());
404
405 let input_len = u32::try_from(input.len()).unwrap();
406 assert_vec_u8_ok_eq(&input, decode(&result7, Some(input_len % 7)));
407 assert_vec_u8_ok_eq(&input, decode(&result8, Some(input_len % 8)));
408 assert_vec_u8_ok_eq(&input, decode(&result9, Some(input_len % 9)));
409 assert_vec_u8_ok_eq(&input, decode(&result10, Some(input_len % 10)));
410 assert_vec_u8_ok_eq(&input, decode(&result11, Some(input_len % 11)));
411 assert_vec_u8_ok_eq(&input, decode(&result12, Some(input_len % 12)));
412 assert_vec_u8_ok_eq(&input, decode(&result13, Some(input_len % 13)));
413 assert_vec_u8_ok_eq(&input, decode(&result14, Some(input_len % 14)));
414 assert_vec_u8_ok_eq(&input, decode(&result15, Some(input_len % 15)));
415 assert_vec_u8_ok_eq(&input, decode(&result16, Some(input_len % 16)));
416 assert_vec_u8_ok_eq(&input, decode(&result17, Some(input_len % 17)));
417
418 #[rustfmt::skip]
419 let no_remainder_res7 = &[0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1];
420 #[rustfmt::skip]
421 let no_remainder_res8 = &[0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
422 #[rustfmt::skip]
423 let no_remainder_res9 = &[0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1];
424 #[rustfmt::skip]
425 let no_remainder_res10 = &[0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1];
426 #[rustfmt::skip]
427 let no_remainder_res11 = &[0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1];
428 #[rustfmt::skip]
429 let no_remainder_res12 = &[0,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1];
430 #[rustfmt::skip]
431 let no_remainder_res13 = &[0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,1,0,1,1,1,0,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,0,0,1,1,1,0,1,1,0,0,0,1,0,0,0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,1,1];
432 #[rustfmt::skip]
433 let no_remainder_res14 = &[0,0,1,1,1,0,1,0,0,0,0,0,1,0,1,1,0,0,1,0,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0,1,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1];
434 #[rustfmt::skip]
435 let no_remainder_res15 = &[0,1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,0,1,1,0,0,0,0,1,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1];
436 #[rustfmt::skip]
440 let no_remainder_res16 = &[1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,0,1,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,1,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0];
441 #[rustfmt::skip]
442 let no_remainder_res17 = &[1,1,0,1,0,0,0,0,0,1,0,1,1,1,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,1,1,1,1,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,1,0,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,1,1];
443 assert_vec_u8_ok_eq(no_remainder_res7, decode(&result7, None));
444 assert_vec_u8_ok_eq(no_remainder_res8, decode(&result8, None));
445 assert_vec_u8_ok_eq(no_remainder_res9, decode(&result9, None));
446 assert_vec_u8_ok_eq(no_remainder_res10, decode(&result10, None));
447 assert_vec_u8_ok_eq(no_remainder_res11, decode(&result11, None));
448 assert_vec_u8_ok_eq(no_remainder_res12, decode(&result12, None));
449 assert_vec_u8_ok_eq(no_remainder_res13, decode(&result13, None));
450 assert_vec_u8_ok_eq(no_remainder_res14, decode(&result14, None));
451 assert_vec_u8_ok_eq(no_remainder_res15, decode(&result15, None));
452 assert_vec_u8_ok_eq(no_remainder_res16, decode(&result16, None));
453 assert_vec_u8_ok_eq(no_remainder_res17, decode(&result17, None));
454
455 let input: Vec<u8> = vec![
457 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1,
473 ];
474 let encoded = "\u{f0002}\u{f080c}\u{f2028}\u{f6070}\u{100121}\u{f82c3}\u{f0687}\u{f0f10}\u{f2224}\u{f4c50}\u{fa8b0}\u{107181}\u{102343}\u{fc707}\u{f8f0f}\u{f80c}";
475 let res = assert_string_ok_eq(encoded, encode(&input, 17));
476 crate::log!(res);
477 assert_vec_u8_ok_eq(
478 &input,
479 decode(&res, Some(u32::try_from(input.len() % 17).unwrap())),
480 );
481 }
482}