1pub type Res<T> = Result<T, Box<dyn std::error::Error>>;
13
14pub fn encode_rsv(rows: &Vec<Vec<Option<String>>>) -> Vec<u8> {
15 let mut parts: Vec<&[u8]> = vec![];
16
17 for row in rows {
18 for value in row {
19 match value {
20 None => parts.push(b"\xFE"),
22 Some(str_value) => {
24 if !str_value.is_empty() {
25 parts.push(str_value.as_bytes());
26 }
27 }
28 }
29
30 parts.push(b"\xFF");
31 }
32
33 parts.push(b"\xFD");
34 }
35
36 parts.concat()
38}
39
40pub fn decode_rsv(bytes: &Vec<u8>) -> Res<Vec<Vec<Option<String>>>> {
41 if !bytes.is_empty() && bytes[bytes.len() - 1] != 0xFD {
43 return Err("Incomplete RSV document".into());
44 }
45
46 let mut result: Vec<Vec<Option<String>>> = Vec::new();
47 let mut current_row: Vec<Option<String>> = Vec::new();
48 let mut value_start_index = 0;
49
50 for i in 0..bytes.len() {
51 if bytes[i] == 0xFF {
52 let length = i - value_start_index;
53
54 if length == 0 {
55 current_row.push(Some(String::new()));
56 } else if length == 1 && bytes[value_start_index] == 0xFE {
57 current_row.push(None);
58 } else {
59 let value_bytes = bytes[value_start_index..i].to_vec();
60
61 if let Ok(str_value) = String::from_utf8(value_bytes) {
62 current_row.push(Some(str_value));
63 } else {
64 return Err("Invalid string value".into());
65 }
66 }
67
68 value_start_index = i + 1;
69 } else if bytes[i] == 0xFD {
70 if i > 0 && value_start_index != i {
71 return Err("Incomplete RSV row".into());
72 }
73
74 result.push(current_row);
75 current_row = Vec::new();
76 value_start_index = i + 1;
77 }
78 }
79
80 Ok(result)
82}
83