use crate::Word;
use super::Mutation;
#[cfg(test)]
mod tests;
#[derive(Debug, PartialEq)]
pub enum MutationDecodeError {
WordsTooShort,
NegativeKeyLength,
NegativeValueLength,
}
impl std::error::Error for MutationDecodeError {}
pub fn decode_mutation(bytes: &[Word]) -> Result<Mutation, MutationDecodeError> {
if bytes.len() < 2 {
return Err(MutationDecodeError::WordsTooShort);
}
if bytes[0] < 0 {
return Err(MutationDecodeError::NegativeKeyLength);
}
let key_len: usize = bytes[0].try_into().unwrap_or(usize::MAX);
let key_end = 1usize.saturating_add(key_len);
if bytes.len() < key_end {
return Err(MutationDecodeError::WordsTooShort);
}
let key = bytes[1..key_end].to_vec();
if bytes[key_end] < 0 {
return Err(MutationDecodeError::NegativeValueLength);
}
let value_len: usize = bytes[key_end].try_into().unwrap_or(usize::MAX);
let value_start = 2usize.saturating_add(key_len);
let value_end = value_start.saturating_add(value_len);
if bytes.len() < value_end {
return Err(MutationDecodeError::WordsTooShort);
}
let value = bytes[value_start..value_end].to_vec();
Ok(Mutation { key, value })
}
pub fn decode_mutations(bytes: &[Word]) -> Result<Vec<Mutation>, MutationDecodeError> {
if bytes.is_empty() {
return Err(MutationDecodeError::WordsTooShort);
}
if bytes[0] < 0 {
return Err(MutationDecodeError::NegativeValueLength);
}
let len: usize = bytes[0].try_into().unwrap_or(usize::MAX);
let mut mutations = Vec::with_capacity(len);
if len == 0 {
return Ok(mutations);
}
let mut i = 1;
while i < bytes.len() {
let Some(b) = bytes.get(i..) else {
return Err(MutationDecodeError::WordsTooShort);
};
let mutation = decode_mutation(b)?;
let size = mutation.encode_size();
i += size;
mutations.push(mutation);
}
Ok(mutations)
}