Crate enumscribe
source ·Expand description
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<Airport>
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));
The same attribute can be used on the enum itself to make all variants case-insensitive. Individual fields may opt back
in to case sensitivity with #[enumscribe(case_sensitive)]
.
use enumscribe::TryUnscribe;
#[derive(TryUnscribe, PartialEq, Eq, Debug)]
#[enumscribe(case_insensitive)]
enum Website {
#[enumscribe(str = "github.com")]
Github,
#[enumscribe(str = "crates.io")]
CratesDotIo,
}
assert_eq!(Website::try_unscribe("CrAtEs.Io"), Some(Website::CratesDotIo));
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, websites exist 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
and
serde::Deserialize
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)?,
flight_json.to_owned());
assert_eq!(serde_json::from_str::<Flight>(flight_json)?,
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 |
---|---|---|---|
No | No | ScribeStaticStr | TryUnscribe |
No | Yes | ScribeCowStr | Unscribe |
Yes | No | TryScribeStaticStr | TryUnscribe |
Yes | Yes | TryScribeCowStr | Unscribe |
There are also ScribeString and TryScribeString traits which can be used in the same
situations as ScribeCowStr and TryScribeCowStr, respectively. These traits produce a
String
rather than a Cow<'static, str>
, so they will always perform an allocation.
Therefore, you should prefer the ScribeCowStr
traits over the ScribeString
traits, unless
you really don’t want to use a Cow
for whatever reason.
Traits
None
if the conversion fails.None
if the conversion fails.None
if the conversion fails.
Generally, TryScribeCowStr should be preferred over this trait because it avoids unnecessary
allocations.None
if the conversion fails.Derive Macros
serde::Deserialize
for an enum.serde::Serialize
for an enum.enumscribe::ScribeCowStr
for an enum. This allows the enum to be converted to
a Cow<'static, str>
using the scribe()
method.enumscribe::ScribeStaticStr
for an enum. This allows the enum to be converted to
a &'static str
using the scribe()
method.enumscribe::ScribeString
for an enum. This allows the enum to be converted to
a String
using the scribe()
method.enumscribe::TryScribeCowStr
for an enum. This allows the enum to be converted to
a Option<Cow<'static, str>>
using the try_scribe()
method.enumscribe::TryScribeStaticStr
for an enum. This allows the enum to be converted to
a Option<&'static str>
using the try_scribe()
method.enumscribe::TryScribeString
for an enum. This allows the enum to be converted to
a Option<String>
using the try_scribe()
method.enumscribe::TryUnscribe
for an enum. This allows a &str
to be converted to an
Option
of the enum using the try_unscribe()
associated function.enumscribe::Unscribe
for an enum. This allows a &str
to be converted to the
enum using the unscribe()
associated function.