reikland 0.1.3

A serde-compatible Ruby marshal parser and deserializer
Documentation
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

use serde_core::de::{Deserializer, SeqAccess, Visitor};

/// Type for deserializing Ruby regex values.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RbRegex<P = String> {
    pub pattern: P,
    pub flags: u8,
}

impl<P> Deref for RbRegex<P> {
    type Target = P;
    fn deref(&self) -> &P {
        &self.pattern
    }
}

impl<P> DerefMut for RbRegex<P> {
    fn deref_mut(&mut self) -> &mut P {
        &mut self.pattern
    }
}

impl<'de, P> serde_core::Deserialize<'de> for RbRegex<P>
where
    P: serde_core::Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        struct RbRegexVisitor<P>(PhantomData<P>);

        impl<'de, P> Visitor<'de> for RbRegexVisitor<P>
        where
            P: serde_core::Deserialize<'de>,
        {
            type Value = RbRegex<P>;

            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                f.write_str("a Ruby Regex (2-element sequence: pattern, flags)")
            }

            fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
                let pattern = seq
                    .next_element()?
                    .ok_or_else(|| serde_core::de::Error::invalid_length(0, &self))?;
                let flags = seq
                    .next_element()?
                    .ok_or_else(|| serde_core::de::Error::invalid_length(1, &self))?;
                Ok(RbRegex { pattern, flags })
            }
        }

        deserializer.deserialize_tuple(2, RbRegexVisitor(PhantomData))
    }
}