julid-rs 1.6.1

A library and loadable extension for SQLite that uses it, that provides Joe's ULIDs.
Documentation
/// 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)
    }
}