#[derive(FromStr)]
{
// Attributes available to this derive:
#[from_str]
}
from_str only.Expand description
§What #[derive(FromStr)] generates
Deriving FromStr only works for enums/structs with no fields
or newtypes (structs with only a single field). The result is
that you will be able to call the parse() method on a string
to convert it to your newtype. This only works when the wrapped
type implements FromStr itself.
§Forwarding
Deriving forwarding implementation is only supported for newtypes (structs with only a single field).
§Tuple structs
When deriving FromStr for a tuple struct with one field:
#[derive(FromStr, Debug, Eq, PartialEq)]
struct MyInt(i32);
assert_eq!("5".parse::<MyInt>().unwrap(), MyInt(5));Code like this is generated:
impl derive_more::core::str::FromStr for MyInt {
type Err = <i32 as derive_more::core::str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(i32::from_str(s)?))
}
}§Regular structs
When deriving FromStr for a regular struct with one field:
#[derive(FromStr, Debug, Eq, PartialEq)]
struct Point1D {
x: i32,
}
assert_eq!("100".parse::<Point1D>().unwrap(), Point1D { x: 100 });Code like this is generated:
impl derive_more::core::str::FromStr for Point1D {
type Err = <i32 as derive_more::core::str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
x: i32::from_str(s)?,
})
}
}§Flat representation
Deriving flat string representation is only supported for empty enums and structs (with no fields).
§Empty enums
When deriving FromStr for enums with empty variants, it will generate a
from_str() method converting strings matching the variant name to the variant.
If using a case-insensitive match would give a unique variant (i.e. you don’t have
both MyEnum::Foo and MyEnum::foo variants), then case-insensitive matching will
be used, otherwise it will fall back to exact string matching.
Since the string may not match any variants an error type is needed, so the
derive_more::FromStrError is used for that purpose.
Given the following enum:
#[derive(FromStr, Debug, Eq, PartialEq)]
enum EnumNoFields {
Foo,
Bar,
Baz,
BaZ,
}
assert_eq!("foo".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo);
assert_eq!("Foo".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo);
assert_eq!("FOO".parse::<EnumNoFields>().unwrap(), EnumNoFields::Foo);
assert_eq!("Bar".parse::<EnumNoFields>().unwrap(), EnumNoFields::Bar);
assert_eq!("bar".parse::<EnumNoFields>().unwrap(), EnumNoFields::Bar);
assert_eq!("Baz".parse::<EnumNoFields>().unwrap(), EnumNoFields::Baz);
assert_eq!("BaZ".parse::<EnumNoFields>().unwrap(), EnumNoFields::BaZ);
assert_eq!(
"other".parse::<EnumNoFields>().unwrap_err().to_string(),
"Invalid `EnumNoFields` string representation",
);Code like this is generated:
impl derive_more::core::str::FromStr for EnumNoFields {
type Err = derive_more::FromStrError;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
Ok(match s.to_lowercase().as_str() {
"foo" => Self::Foo,
"bar" => Self::Bar,
"baz" if s == "Baz" => Self::Baz,
"baz" if s == "BaZ" => Self::BaZ,
_ => return Err(derive_more::FromStrError::new("EnumNoFields")),
})
}
}§Empty structs
Deriving FromStr for structs with no fields is similar to enums,
but involves only case-insensitive matching by now.
Given the following struct:
#[derive(FromStr, Debug, Eq, PartialEq)]
struct Foo;
assert_eq!("foo".parse::<Foo>().unwrap(), Foo);
assert_eq!("Foo".parse::<Foo>().unwrap(), Foo);
assert_eq!("FOO".parse::<Foo>().unwrap(), Foo);Code like this is generated:
impl derive_more::core::str::FromStr for Foo {
type Err = derive_more::FromStrError;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
Ok(match s.to_lowercase().as_str() {
"foo" => Self,
_ => return Err(derive_more::FromStrError::new("Foo")),
})
}
}§The rename_all attribute
To control the concrete string representation of the name verbatim,
the #[from_str(rename_all = "...")] attribute can be placed on structs,
enums and variants.
The available casings are:
lowercaseUPPERCASEPascalCasecamelCasesnake_caseSCREAMING_SNAKE_CASEkebab-caseSCREAMING-KEBAB-CASE
#[derive(FromStr, Debug, Eq, PartialEq)]
#[from_str(rename_all = "lowercase")]
enum Enum {
VariantOne,
#[from_str(rename_all = "kebab-case")] // overrides the top-level one
VariantTwo
}
assert_eq!("variantone".parse::<Enum>().unwrap(), Enum::VariantOne);
assert_eq!("variant-two".parse::<Enum>().unwrap(), Enum::VariantTwo);NOTE: Using
#[from_str(rename_all = "...")]attribute disables any case-insensitivity where applied. This is also true for any enum variant whose name or string representation is similar to the variant being marked:#[derive(FromStr, Debug, Eq, PartialEq)] enum Enum { Foo, // case-insensitive #[from_str(rename_all = "SCREAMING_SNAKE_CASE")] BaR, // case-sensitive (marked with attribute) Bar, // case-sensitive (name is similar to the marked `BaR` variant) Ba_R, // case-sensitive (string representation is similar to the marked `BaR` variant) }
§Custom error
The #[from_str(error(<ty>[, <conv>]))] attribute can be used to convert the FromStr’ Err type
into a custom error type.
If the conversion function is not provided, the custom error type must implement From<FromStr::Err>.
The conversion function could be provided in the following forms:
- function (like
CustomError::new); - closure (like
|e| CustomError::new(e)); - function call (like
CustomError::factory()).
§Forwarding
Given the following struct:
#[derive(From)]
struct CustomError(core::num::ParseIntError);
#[derive(FromStr, Debug, Eq, PartialEq)]
#[from_str(error(CustomError))]
struct MyInt(i32);Code like this is generated:
impl derive_more::core::str::FromStr for MyInt {
type Err = CustomError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
FromStr::from_str(s)
.map(|v| Self(v))
.map_err(Into::into)
}
}For the explicitly specified error conversion:
struct CustomError(core::num::ParseIntError);
impl CustomError {
fn new(err: core::num::ParseIntError) -> Self {
Self(err)
}
}
#[derive(FromStr, Debug, Eq, PartialEq)]
#[from_str(error(CustomError, CustomError::new))]
struct MyInt(i32);Code like this is generated:
impl derive_more::core::str::FromStr for MyInt {
type Err = CustomError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
FromStr::from_str(s)
.map(|v| Self(v))
.map_err(CustomError::new)
}
}Custom error for a newtype struct with one named field, e.g,
#[derive(From)]
struct CustomError(core::num::ParseIntError);
#[derive(FromStr)]
#[from_str(error(CustomError))]
struct Point1D {
x: i32,
}works similarly.
§Flat representation
Custom error type is also supported for empty enums and unit structs.
Given the following enum:
#[derive(From)]
struct CustomError(derive_more::FromStrError);
#[derive(FromStr, Debug, Eq, PartialEq)]
#[from_str(error(CustomError))]
enum EnumNoFields {
Foo,
Bar,
Baz,
}Code like this is generated:
impl derive_more::core::str::FromStr for EnumNoFields {
type Err = CustomError;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
Ok(match s.to_lowercase().as_str() {
"foo" => Self::Foo,
"bar" => Self::Bar,
"baz" => Self::Baz,
_ => return Err(derive_more::FromStrError::new("EnumNoFields").into()),
})
}
}For the explicitly specified error conversion:
struct CustomError(derive_more::FromStrError);
impl CustomError {
pub fn new(err: derive_more::FromStrError) -> Self {
Self(err)
}
}
#[derive(FromStr, Debug, Eq, PartialEq)]
#[from_str(error(CustomError, CustomError::new))]
enum EnumNoFields {
Foo,
Bar,
Baz,
}Code like this is generated:
impl derive_more::core::str::FromStr for EnumNoFields {
type Err = CustomError;
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
Ok(match s.to_lowercase().as_str() {
"foo" => Self::Foo,
"bar" => Self::Bar,
"baz" => Self::Baz,
_ => return Err(CustomError::new(derive_more::FromStrError::new("EnumNoFields"))),
})
}
}Custom error type for unit structs, e.g,
#[derive(From)]
struct CustomError(derive_more::FromStrError);
#[derive(FromStr)]
#[from_str(error(CustomError))]
struct Foo;works similarly.