use crate::ParseTable;
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub const PARSE_TABLE_FORMAT_VERSION: u32 = 2;
#[derive(Debug, Error)]
pub enum SerializationError {
#[error("Postcard encoding failed: {0}")]
EncodingFailed(#[from] postcard::Error),
#[error("ParseTable validation failed: {0}")]
ValidationFailed(String),
}
#[derive(Debug, Error)]
pub enum DeserializationError {
#[error("Postcard decoding failed: {0}")]
DecodingFailed(#[from] postcard::Error),
#[error("Incompatible format version: expected {expected}, got {actual}")]
IncompatibleVersion {
expected: u32,
actual: u32,
},
#[error("ParseTable validation failed: {0}")]
ValidationFailed(String),
}
#[derive(Debug, Serialize, Deserialize)]
struct VersionedParseTable {
version: u32,
data: Vec<u8>,
}
impl ParseTable {
pub fn to_bytes(&self) -> Result<Vec<u8>, SerializationError> {
let table_bytes = postcard::to_stdvec(self)?;
let versioned = VersionedParseTable {
version: PARSE_TABLE_FORMAT_VERSION,
data: table_bytes,
};
let bytes = postcard::to_stdvec(&versioned)?;
Ok(bytes)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DeserializationError> {
let versioned: VersionedParseTable = postcard::from_bytes(bytes)?;
if versioned.version != PARSE_TABLE_FORMAT_VERSION {
return Err(DeserializationError::IncompatibleVersion {
expected: PARSE_TABLE_FORMAT_VERSION,
actual: versioned.version,
});
}
let table: ParseTable = postcard::from_bytes(&versioned.data)?;
Ok(table)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version_constant() {
assert_eq!(PARSE_TABLE_FORMAT_VERSION, 2);
}
#[test]
fn test_serialization_error_display() {
let err = SerializationError::ValidationFailed("test".to_string());
assert!(err.to_string().contains("test"));
}
#[test]
fn test_deserialization_error_display() {
let err = DeserializationError::IncompatibleVersion {
expected: 2,
actual: 1,
};
assert!(err.to_string().contains("expected 2"));
assert!(err.to_string().contains("got 1"));
}
}