-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlib.rs
More file actions
74 lines (69 loc) · 2.37 KB
/
lib.rs
File metadata and controls
74 lines (69 loc) · 2.37 KB
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
//! Datacode encoding and decoding.
/// Encode byte slice to datacode string
pub fn encode(bytes: &[u8]) -> String {
let mut datacode = String::new();
for chunk in bytes.chunks(2) {
if chunk.len() == 2 {
let low = u32::from(chunk[0]);
let high = u32::from(chunk[1]) << 8;
let value = 0x40000 | high | low;
datacode.push(char::try_from(value).unwrap());
} else {
let value = 0x1FF00 | u32::from(chunk[0]);
datacode.push(char::try_from(value).unwrap());
}
}
datacode
}
/// Decode datacode string to byte vector
pub fn decode(datacode: &str) -> Result<Vec<u8>, String> {
let mut bytes = Vec::new();
for c in datacode.chars() {
let value = u32::from(c);
match value {
0x40000..=0x4FFFF => {
bytes.extend_from_slice(&value.to_le_bytes()[0..2]);
}
0x1FF00..=0x1FFFF => {
bytes.push(value.to_le_bytes()[0]);
}
_ => return Err(format!("invalid character `{c}`")),
}
}
Ok(bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encoder() {
assert_eq!(encode(&[]), "");
assert_eq!(encode(&[0]), "\u{1FF00}");
assert_eq!(encode(&[1]), "\u{1FF01}");
assert_eq!(encode(&[255]), "\u{1FFFF}");
assert_eq!(encode(&[0, 0]), "\u{40000}");
assert_eq!(encode(&[1, 0]), "\u{40001}");
assert_eq!(encode(&[255, 0]), "\u{400FF}");
assert_eq!(encode(&[255, 1]), "\u{401FF}");
assert_eq!(encode(&[255, 255]), "\u{4FFFF}");
assert_eq!(encode(&[0, 0, 0]), "\u{40000}\u{1FF00}");
assert_eq!(encode(&[0, 0, 1]), "\u{40000}\u{1FF01}");
assert_eq!(encode(&[255, 255, 255]), "\u{4FFFF}\u{1FFFF}");
}
#[test]
fn decoder() {
assert_eq!(decode(""), Ok(vec![]));
assert_eq!(decode("\u{1FF00}"), Ok(vec![0]));
assert_eq!(decode("\u{1FF01}"), Ok(vec![1]));
assert_eq!(decode("\u{1FFFF}"), Ok(vec![255]));
assert_eq!(decode("\u{40000}"), Ok(vec![0, 0]));
assert_eq!(decode("\u{40001}"), Ok(vec![1, 0]));
assert_eq!(decode("\u{400FF}"), Ok(vec![255, 0]));
assert_eq!(decode("\u{401FF}"), Ok(vec![255, 1]));
assert_eq!(decode("\u{4FFFF}"), Ok(vec![255, 255]));
assert_eq!(decode("\u{40000}\u{1FF00}"), Ok(vec![0, 0, 0]));
assert_eq!(decode("\u{40000}\u{1FF01}"), Ok(vec![0, 0, 1]));
assert_eq!(decode("\u{4FFFF}\u{1FFFF}"), Ok(vec![255, 255, 255]));
assert_eq!(decode("hello"), Err("invalid character `h`".into()));
}
}