diff --git a/enumscribe/src/lib.rs b/enumscribe/src/lib.rs index 7dc88a5..d433a54 100644 --- a/enumscribe/src/lib.rs +++ b/enumscribe/src/lib.rs @@ -1,6 +1,143 @@ -//! Traits for converting between enums and strings. This is only useful alongside the +//! Traits for converting between enums and strings. Intended to be used alongside the //! [enumscribe_derive] crate, which provides derive macros for these traits. //! +//! Here is a basic usage example: +//! +//! ``` +//! use enumscribe::{ScribeStaticStr, TryUnscribe}; +//! +//! #[derive(ScribeStaticStr, TryUnscribe, PartialEq, Eq, Debug)] +//! enum Airport { +//! #[enumscribe(str = "LHR")] +//! Heathrow, +//! #[enumscribe(str = "LGW")] +//! Gatwick, +//! #[enumscribe(str = "LTN")] +//! Luton, +//! } +//! +//! // Convert an Airport to a &'static str +//! assert_eq!(Airport::Heathrow.scribe(), "LHR"); +//! +//! // Convert a &str to a Option +//! assert_eq!(Airport::try_unscribe("LGW"), Some(Airport::Gatwick)); +//! ``` +//! +//! The `#[enumscribe(str = "...")]` allows us to specify what string should be used to represent a +//! particular variant. If this is omitted, the name of the variant will be used instead. +//! +//! The `#[enumscribe(case_insensitive)]` attribute can be used to make the "Unscribe" traits +//! perform case-insensitive matching for a variant: +//! +//! ``` +//! use enumscribe::TryUnscribe; +//! +//! #[derive(TryUnscribe, PartialEq, Eq, Debug)] +//! enum Website { +//! #[enumscribe(str = "github.com", case_insensitive)] +//! Github, +//! #[enumscribe(str = "crates.io", case_insensitive)] +//! CratesDotIo, +//! } +//! +//! assert_eq!(Website::try_unscribe("GiThUb.CoM"), Some(Website::Github)); +//! ``` +//! +//! You can also have a variant which stores strings that could not be matched to any other +//! variant. This is done using the `#[enumscribe(other)]` attribute. The variant should have a +//! single field, which is a `String`. +//! +//! ``` +//! use std::borrow::Cow; +//! +//! use enumscribe::{Unscribe, ScribeCowStr}; +//! +//! #[derive(ScribeCowStr, Unscribe, PartialEq, Eq, Debug)] +//! enum Website { +//! #[enumscribe(str = "github.com", case_insensitive)] +//! Github, +//! #[enumscribe(str = "crates.io", case_insensitive)] +//! CratesDotIo, +//! #[enumscribe(other)] +//! Other(String), +//! } +//! +//! // Note that we don't need to use an Option anymore! +//! assert_eq!(Website::unscribe("github.com"), Website::Github); +//! +//! // Unbelievably, there exist websites other than github and crates.io +//! assert_eq!(Website::unscribe("stackoverflow.com"), Website::Other("stackoverflow.com".to_owned())); +//! +//! // We can't scribe to a &'static str anymore, so we use a Cow<'static, str> instead +//! assert_eq!(Website::Github.scribe(), Cow::Borrowed::<'static, str>("github.com")); +//! +//! assert_eq!(Website::Other("owasp.org".to_owned()).scribe(), Cow::Owned::<'static, str>("owasp.org".to_owned())); +//! ``` +//! +//! If you need to, you can use `#[enumscribe(ignore)]` to prevent a variant from being used by +//! Scribe or Unscribe traits. +//! +//! However, this means that converting the enum to a string can fail, so you must use TryScribe +//! instead of Scribe in this case. +//! +//! ``` +//! use enumscribe::TryScribeStaticStr; +//! +//! #[derive(TryScribeStaticStr, PartialEq, Eq, Debug)] +//! enum Airport { +//! #[enumscribe(str = "LHR")] +//! Heathrow, +//! #[enumscribe(str = "LGW")] +//! Gatwick, +//! #[enumscribe(str = "LTN")] +//! Luton, +//! #[enumscribe(ignore)] +//! SecretExtraVariant(i32), // we have to ignore this variant because of the i32 field +//! } +//! +//! assert_eq!(Airport::SecretExtraVariant(123).try_scribe(), None); +//! +//! assert_eq!(Airport::Luton.try_scribe(), Some("LTN")); +//! ``` +//! +//! You can derive [`serde::Serialize`](https://docs.serde.rs/serde/trait.Serialize.html) and +//! [`serde::Deserialize`](https://docs.serde.rs/serde/trait.Deserialize.html) using the same +//! syntax: +//! +//! ``` +//! use serde::{Serialize, Deserialize}; +//! +//! use enumscribe::{EnumSerialize, EnumDeserialize}; +//! +//! #[derive(EnumSerialize, EnumDeserialize, PartialEq, Eq, Clone, Copy, Debug)] +//! enum Airport { +//! #[enumscribe(str = "LHR")] +//! Heathrow, +//! #[enumscribe(str = "LGW")] +//! Gatwick, +//! #[enumscribe(str = "LTN")] +//! Luton, +//! } +//! +//! #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] +//! struct Flight { +//! takeoff: Airport, +//! landing: Airport, +//! } +//! +//! // There are probably much more economical ways of making this journey +//! let flight = Flight { +//! takeoff: Airport::Heathrow, +//! landing: Airport::Gatwick, +//! }; +//! +//! let flight_json = r#"{"takeoff":"LHR","landing":"LGW"}"#; +//! +//! assert_eq!(serde_json::to_string(&flight).unwrap(), flight_json.to_owned()); +//! +//! assert_eq!(serde_json::from_str::(flight_json).unwrap(), flight); +//! ``` +//! //! Here is a table to show which traits you should derive for your enum: //! //! | `ignore` used? | `other` used? | Conversion to string | Conversion from string |