marc-relators 0.1.1

Parsing and de/serialization for MARC relators
Documentation
//! A crate for serializing and deserializing [MARC relators][marc-relators].
//!
//! A MARC record is a [MA-chine Readable Cataloging record][marc]. This crate does not attempt to
//! deal with records themselves, only with their relators.
//!
//! ```rust
//! use marc_relators::MarcRelator;
//!
//! let relator: MarcRelator = "aut".parse().unwrap();
//! assert_eq!(relator, MarcRelator::Author);
//!
//! assert_eq!(relator.code(), "aut");
//! assert_eq!(relator.name(), "Author");
//! assert_eq!(
//!     // The full descriptions can be quite long FYI
//!     &relator.description().as_bytes()[0..102],
//!     concat!("A person, family, or organization responsible for ",
//!             "creating a work that is primarily textual in content").as_bytes(),
//! );
//! ```
//!
//! This crate tracks the most current MARC specification. At this time, this is MARC 21.
//!
//! ## Features
//!
//! - `serde`: Enables de/serializatin with [`serde`][serde]. Not enabled by default.
//!
//! [marc]: https://www.loc.gov/marc/umb/um01to06.html
//! [marc-relators]: https://www.loc.gov/marc/relators/relaterm.html.
//! [serde]: https://serde.rs/

mod inner;
pub use inner::*;
use thiserror::Error;

/// An error returned when parsing a string.
#[derive(Debug, PartialEq, Eq, Error)]
#[non_exhaustive]
pub enum ParseError {
    /// The string was not a known MARC relator code.
    #[error("unkown code for a MARC relator")]
    UnknownCode,
}

#[cfg(test)]
mod test {
    use super::MarcRelator;

    #[test]
    fn from_str() {
        assert_eq!("aut".parse::<MarcRelator>().unwrap(), MarcRelator::Author);
    }

    #[test]
    fn code() {
        assert_eq!(MarcRelator::Author.code(), "aut");
    }
}

#[cfg(feature = "serde")]
mod marc_serde {
    use crate::MarcRelator;
    use serde::de::{self, Deserialize, Deserializer, Visitor};
    use serde::ser::{Serialize, Serializer};
    use std::fmt;

    impl Serialize for MarcRelator {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            serializer.serialize_str(self.code())
        }
    }

    struct MarcRelatorVisitor {}

    impl<'de> Visitor<'de> for MarcRelatorVisitor {
        type Value = MarcRelator;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("a MARC relator code")
        }

        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
        where
            E: de::Error,
        {
            v.parse()
                .map_err(|_| E::unknown_variant(v, MarcRelator::KNOWN_VARIANTS))
        }
    }

    impl<'de> Deserialize<'de> for MarcRelator {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            deserializer.deserialize_str(MarcRelatorVisitor {})
        }
    }

    #[cfg(test)]
    mod test {
        use crate::MarcRelator;
        #[test]
        fn serialize() {
            assert_eq!(
                serde_json::to_string(&MarcRelator::Author).unwrap(),
                "\"aut\""
            );
        }

        #[test]
        fn deserialize() {
            assert_eq!(
                serde_json::from_str::<MarcRelator>("\"aut\"").unwrap(),
                MarcRelator::Author
            );
        }

        #[test]
        fn deserialize_fail() {
            serde_json::from_str::<MarcRelator>("\"XXX\"").unwrap_err();
        }
    }
}