fixed/src/serdeize.rs

126 lines
4.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright © 20182019 Trevor Spiteri
// This library is free software: you can redistribute it and/or
// modify it under the terms of either
//
// * the Apache License, Version 2.0 or
// * the MIT License
//
// at your option.
//
// You should have recieved copies of the Apache License and the MIT
// License along with the library. If not, see
// <https://www.apache.org/licenses/LICENSE-2.0> and
// <https://opensource.org/licenses/MIT>.
use crate::{
frac::{IsLessOrEqual, True, Unsigned, U128, U16, U32, U64, U8},
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8,
};
use core::fmt::{Formatter, Result as FmtResult};
use serde::{
de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor},
ser::{Serialize, SerializeStruct, Serializer},
};
macro_rules! serde_fixed {
($Fixed:ident($NBits:ident) is $TBits:ident name $Name:expr) => {
impl<Frac> Serialize for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>,
{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bits = self.to_bits();
let mut state = serializer.serialize_struct($Name, 1)?;
state.serialize_field("bits", &bits)?;
state.end()
}
}
impl<'de, Frac> Deserialize<'de> for $Fixed<Frac>
where
Frac: Unsigned + IsLessOrEqual<$NBits, Output = True>,
{
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct FixedVisitor;
impl<'de> Visitor<'de> for FixedVisitor {
type Value = $TBits;
fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
formatter.write_str("struct ")?;
formatter.write_str($Name)
}
fn visit_seq<V: SeqAccess<'de>>(self, mut seq: V) -> Result<$TBits, V::Error> {
let bits = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
Ok(bits)
}
fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> Result<$TBits, V::Error> {
let mut bits = None;
while let Some(key) = map.next_key()? {
match key {
Field::Bits => {
if bits.is_some() {
return Err(de::Error::duplicate_field("bits"));
}
bits = Some(map.next_value()?);
}
}
}
let bits = bits.ok_or_else(|| de::Error::missing_field("bits"))?;
Ok(bits)
}
}
let bits = deserializer.deserialize_struct($Name, FIELDS, FixedVisitor)?;
Ok($Fixed::from_bits(bits))
}
}
};
}
serde_fixed! { FixedI8(U8) is i8 name "FixedI8" }
serde_fixed! { FixedI16(U16) is i16 name "FixedI16" }
serde_fixed! { FixedI32(U32) is i32 name "FixedI32" }
serde_fixed! { FixedI64(U64) is i64 name "FixedI64" }
serde_fixed! { FixedI128(U128) is i128 name "FixedI128" }
serde_fixed! { FixedU8(U8) is u8 name "FixedU8" }
serde_fixed! { FixedU16(U16) is u16 name "FixedU16" }
serde_fixed! { FixedU32(U32) is u32 name "FixedU32" }
serde_fixed! { FixedU64(U64) is u64 name "FixedU64" }
serde_fixed! { FixedU128(U128) is u128 name "FixedU128" }
const FIELDS: &[&str] = &["bits"];
enum Field {
Bits,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Field, D::Error> {
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
formatter.write_str("`bits`")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Field, E> {
match value {
"bits" => Ok(Field::Bits),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}