use std::io::Write;
use simd_json::{
Error as JsonError, ErrorType, Node, Tape,
derived::{TypedScalarValue, ValueObjectAccessAsScalar},
};
use simd_json_derive::Serialize;
use crate::{Decode, Encode};
pub struct Decoder<'data> {
tape: Option<Tape<'data>>,
}
impl<'data> Decoder<'data> {
pub fn new(data: &'data mut [u8]) -> Result<Self, DecodeError> {
let tape = simd_json::to_tape(data)?;
Ok(Self { tape: Some(tape) })
}
}
impl crate::Decoder for Decoder<'_> {
type Error = DecodeError;
fn decode_version(&mut self) -> Result<u32, Self::Error> {
self.tape
.as_ref()
.ok_or(DecodeError::AlreadyConsumed)?
.as_value()
.get_u32("v")
.ok_or(DecodeError::InvalidVersionField)
}
}
#[derive(Debug)]
pub enum DecodeError {
Json(JsonError),
JsonDerive(simd_json_derive::de::Error),
InvalidVersionField,
InvalidNumberOfFields(usize),
InvalidFormat,
AlreadyConsumed,
}
impl std::error::Error for DecodeError {}
impl std::fmt::Display for DecodeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
DecodeError::Json(error) => error.fmt(f),
DecodeError::JsonDerive(error) => error.fmt(f),
DecodeError::InvalidVersionField => {
write!(f, "`version` field missing or not an intege")
}
DecodeError::InvalidNumberOfFields(n) => write!(
f,
"the versioned struct needs to have exactly two elements but has {n}"
),
DecodeError::InvalidFormat => write!(
f,
"the format is invalid, needs to be an object with version and data key"
),
DecodeError::AlreadyConsumed => write!(f, "the deserializer was already consumed"),
}
}
}
impl From<JsonError> for DecodeError {
fn from(value: JsonError) -> Self {
Self::Json(value)
}
}
impl From<simd_json_derive::de::Error> for DecodeError {
fn from(value: simd_json_derive::de::Error) -> Self {
Self::JsonDerive(value)
}
}
impl<'data, T> Decode<Decoder<'data>> for T
where
T: simd_json_derive::Deserialize<'data> + 'data,
{
fn decode_data(decoder: &mut Decoder<'data>) -> Result<Self, DecodeError> {
let mut tape = decoder
.tape
.take()
.ok_or(DecodeError::AlreadyConsumed)?
.0
.into_iter()
.peekable();
let Some(Node::Object { len, .. }) = tape.next() else {
return Err(JsonError::generic(ErrorType::ExpectedMap).into());
};
if len != 2 {
return Err(DecodeError::InvalidNumberOfFields(len));
}
loop {
let Some(Node::String(key)) = tape.next() else {
return Err(JsonError::generic(ErrorType::Eof).into());
};
if key == "v" {
match tape.next() {
None => return Err(JsonError::generic(ErrorType::Eof).into()),
Some(Node::Static(s)) if !s.is_u32() => {
return Err(DecodeError::InvalidFormat);
}
_ => continue,
}
}
if key != "d" {
return Err(DecodeError::InvalidFormat);
}
return Ok(T::from_tape(&mut tape)?);
}
}
}
#[derive(Debug)]
pub enum EncodeError {
Io(std::io::Error),
VersionAlreadyDefined,
VersionNotDefined,
}
impl std::error::Error for EncodeError {}
impl From<std::io::Error> for EncodeError {
fn from(value: std::io::Error) -> Self {
Self::Io(value)
}
}
impl std::fmt::Display for EncodeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
EncodeError::Io(error) => error.fmt(f),
EncodeError::VersionAlreadyDefined => write!(f, "version already defined"),
EncodeError::VersionNotDefined => write!(f, "version not defined"),
}
}
}
pub struct Encoder<W: Write> {
writer: W,
version: Option<u32>,
}
impl<W: Write> Encoder<W> {
#[must_use]
pub fn new(writer: W) -> Self {
Self {
writer,
version: None,
}
}
}
impl<W: Write> crate::Encoder for Encoder<W> {
type Error = EncodeError;
fn encode_version(&mut self, version: u32) -> Result<(), Self::Error> {
if self.version.replace(version).is_some() {
Err(EncodeError::VersionAlreadyDefined)
} else {
Ok(())
}
}
}
impl<W, T> Encode<Encoder<W>> for T
where
T: simd_json_derive::Serialize,
W: Write,
{
fn encode_data(&self, encoder: &mut Encoder<W>) -> Result<(), EncodeError> {
let Some(version) = encoder.version else {
return Err(EncodeError::VersionNotDefined);
};
encoder.writer.write_all(br#"{"v":"#)?;
version.json_write(&mut encoder.writer)?;
encoder.writer.write_all(br#","d":"#)?;
self.json_write(&mut encoder.writer)?;
encoder.writer.write_all(b"}")?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{DecodeError, Decoder, EncodeError, Encoder};
use crate::{Decodable, Encodable, Upgrade, versioned};
#[derive(Debug, thiserror::Error)]
enum Error {
#[error("Invalid version: {0}")]
InvalidVersion(u32),
#[error(transparent)]
Decode(#[from] DecodeError),
#[error(transparent)]
Encoder(#[from] EncodeError),
}
impl crate::Error for Error {
fn invalid_version(version: u32) -> Self {
Self::InvalidVersion(version)
}
}
#[derive(Debug, PartialEq, Eq, simd_json_derive::Deserialize, simd_json_derive::Serialize)]
struct TestV0 {
data: u8,
}
versioned!(TestV0, 0);
#[derive(Debug, PartialEq, Eq, simd_json_derive::Deserialize, simd_json_derive::Serialize)]
struct TestV1 {
data: u16,
}
versioned!(TestV1, 1);
#[derive(Debug, PartialEq, Eq, simd_json_derive::Deserialize, simd_json_derive::Serialize)]
struct TestV2 {
data: u32,
}
versioned!(TestV2, 2);
impl TryFrom<TestV0> for TestV1 {
type Error = Error;
fn try_from(v0: TestV0) -> Result<Self, Self::Error> {
Ok(Self {
data: u16::from(v0.data),
})
}
}
impl TryFrom<TestV1> for TestV2 {
type Error = Error;
fn try_from(v1: TestV1) -> Result<Self, Self::Error> {
Ok(Self {
data: u32::from(v1.data),
})
}
}
#[test]
fn test_v0() -> Result<(), Error> {
let mut data = Vec::new();
let mut enc = Encoder::new(&mut data);
<TestV0 as Encodable<_, Error>>::encode(&TestV0 { data: 42 }, &mut enc)?;
let mut dec = Decoder::new(data.as_mut_slice())?;
let v0 = <TestV0 as Decodable<_, Error>>::decode(&mut dec)?;
assert_eq!(v0.data, 42);
Ok(())
}
#[test]
fn test_v1() -> Result<(), Error> {
let mut data = Vec::new();
let mut enc = Encoder::new(&mut data);
<TestV1 as Encodable<_, Error>>::encode(&TestV1 { data: 42 }, &mut enc)?;
let mut dec = Decoder::new(data.as_mut_slice())?;
let v1 = <TestV1 as Decodable<_, Error>>::decode(&mut dec)?;
assert_eq!(v1.data, 42);
Ok(())
}
#[test]
fn test_upgrade_v1() -> Result<(), Error> {
type Latest = Upgrade<TestV1, TestV0, Error>;
let mut data = Vec::new();
let mut enc = Encoder::new(&mut data);
<TestV0 as Encodable<_, Error>>::encode(&TestV0 { data: 42 }, &mut enc)?;
let mut dec = Decoder::new(data.as_mut_slice())?;
let v1 = Latest::decode(&mut dec)?;
assert_eq!(v1.data, 42);
Ok(())
}
#[test]
fn test_upgrade_v2() -> Result<(), Error> {
type Latest = Upgrade<TestV2, TestV1, Error>;
let mut data = Vec::new();
let mut enc = Encoder::new(&mut data);
<TestV1 as Encodable<_, Error>>::encode(&TestV1 { data: 42 }, &mut enc)?;
let mut dec = Decoder::new(data.as_mut_slice())?;
let v0 = Latest::decode(&mut dec)?;
assert_eq!(v0.data, 42);
Ok(())
}
#[test]
fn test_upgrade_all() -> Result<(), Error> {
type Latest = Upgrade<TestV2, Upgrade<TestV1, TestV0, Error>, Error>;
let mut data = Vec::new();
let mut enc = Encoder::new(&mut data);
<TestV0 as Encodable<_, Error>>::encode(&TestV0 { data: 42 }, &mut enc)?;
let mut dec = Decoder::new(data.as_mut_slice())?;
let v0 = Latest::decode(&mut dec)?;
assert_eq!(v0.data, 42);
Ok(())
}
}