julid-rs/src/serde.rs

121 lines
3.2 KiB
Rust
Raw Normal View History

//! Serialization and deserialization.
//!
//! By default, serialization and deserialization go through Julid's big-endian
//! bytes representation.
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
use crate::Julid;
impl Serialize for Julid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.to_bytes())
}
}
struct JulidVisitor;
impl<'de> Visitor<'de> for JulidVisitor {
type Value = Julid;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("16 bytes")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match std::convert::TryInto::<[u8; 16]>::try_into(v) {
Ok(v) => Ok(v.into()),
Err(_) => Err(serde::de::Error::invalid_length(v.len(), &self)),
}
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let len = v.len();
match std::convert::TryInto::<[u8; 16]>::try_into(v) {
Ok(v) => Ok(v.into()),
Err(_) => Err(serde::de::Error::invalid_length(len, &self)),
}
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut bytes = [0u8; 16];
let size = seq.size_hint().unwrap_or(0);
let mut count = 0;
while let Some(val) = seq.next_element()? {
if count > 15 {
break;
}
bytes[count] = val;
count += 1;
}
if count != 16 || size > 16 {
let sz = if count < 16 { count } else { size };
Err(serde::de::Error::invalid_length(sz, &self))
} else {
Ok(bytes.into())
}
}
}
impl<'de> Deserialize<'de> for Julid {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_bytes(JulidVisitor)
}
}
/// Serialization and deserialization of Julids through their string
/// representation.
///
/// To use it, annotate a field with
/// `#[serde(with = "julid_as_str")]`,
/// `#[serde(serialize_with = "julid_as_str")]`, or
/// `#[serde(deserialize_with = "julid_as_str")]`.
///
/// # Examples
/// ```
/// # use julid::Julid;
/// # use julid::serde::ulid_as_str;
/// # use serde::{Serialize, Deserialize};
/// #[derive(Serialize, Deserialize)]
/// struct StrExample {
/// #[serde(with = "julid_as_str")]
/// identifier: Julid
/// }
/// ```
pub mod julid_as_str {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::Julid;
pub fn serialize<S>(value: &Julid, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let text = value.to_string();
text.serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Julid, D::Error>
where
D: Deserializer<'de>,
{
let deserialized_str = String::deserialize(deserializer)?;
Julid::from_string(&deserialized_str).map_err(serde::de::Error::custom)
}
}