pub type Res<T> = Result<T, Box<dyn std::error::Error>>;
pub fn encode_rsv(rows: &Vec<Vec<Option<String>>>) -> Vec<u8> {
let mut parts: Vec<&[u8]> = vec![];
for row in rows {
for value in row {
match value {
None => parts.push(b"\xFE"),
Some(str_value) => {
if !str_value.is_empty() {
parts.push(str_value.as_bytes());
}
}
}
parts.push(b"\xFF");
}
parts.push(b"\xFD");
}
parts.concat()
}
pub fn decode_rsv(bytes: &Vec<u8>) -> Res<Vec<Vec<Option<String>>>> {
if !bytes.is_empty() && bytes[bytes.len() - 1] != 0xFD {
return Err("Incomplete RSV document".into());
}
let mut result: Vec<Vec<Option<String>>> = Vec::new();
let mut current_row: Vec<Option<String>> = Vec::new();
let mut value_start_index = 0;
for i in 0..bytes.len() {
if bytes[i] == 0xFF {
let length = i - value_start_index;
if length == 0 {
current_row.push(Some(String::new()));
} else if length == 1 && bytes[value_start_index] == 0xFE {
current_row.push(None);
} else {
let value_bytes = bytes[value_start_index..i].to_vec();
if let Ok(str_value) = String::from_utf8(value_bytes) {
current_row.push(Some(str_value));
} else {
return Err("Invalid string value".into());
}
}
value_start_index = i + 1;
} else if bytes[i] == 0xFD {
if i > 0 && value_start_index != i {
return Err("Incomplete RSV row".into());
}
result.push(current_row);
current_row = Vec::new();
value_start_index = i + 1;
}
}
Ok(result)
}