120 lines
3.2 KiB
Rust
120 lines
3.2 KiB
Rust
/// 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.as_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::julid_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)
|
|
}
|
|
}
|