Run cargo fmt, minor code cleanup
This commit is contained in:
1 parent
4317afa003
commit
f9a9db2e9a
8 files changed
+353
-201
No files matched your search
@@ -2,9 +2,9 @@ use std::collections::HashMap;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use syn::{Attribute, Ident, Lit, Token};
|
|
||||||
use syn::parse::{Parse, ParseBuffer, ParseStream};
|
|
||||||
use syn::parse::discouraged::Speculative;
|
use syn::parse::discouraged::Speculative;
|
||||||
|
use syn::parse::{Parse, ParseBuffer, ParseStream};
|
||||||
|
use syn::{Attribute, Ident, Lit, Token};
|
||||||
|
|
||||||
use crate::error::{MacroError, MacroResult, ValueTypeError, ValueTypeResult};
|
use crate::error::{MacroError, MacroResult, ValueTypeError, ValueTypeResult};
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ impl Value {
|
|||||||
Value::None => Ok(true),
|
Value::None => Ok(true),
|
||||||
Value::Lit(Lit::Bool(lit_bool)) => Ok(lit_bool.value),
|
Value::Lit(Lit::Bool(lit_bool)) => Ok(lit_bool.value),
|
||||||
val => Err(ValueTypeError {
|
val => Err(ValueTypeError {
|
||||||
message: format!("expected boolean but found {}", val.type_name()).into()
|
message: format!("expected boolean but found {}", val.type_name()).into(),
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +51,8 @@ impl Value {
|
|||||||
match self {
|
match self {
|
||||||
Value::Lit(Lit::Str(lit_str)) => Ok(lit_str.value()),
|
Value::Lit(Lit::Str(lit_str)) => Ok(lit_str.value()),
|
||||||
val => Err(ValueTypeError {
|
val => Err(ValueTypeError {
|
||||||
message: format!("expected string but found {}", val.type_name()).into()
|
message: format!("expected string but found {}", val.type_name()).into(),
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,13 +97,16 @@ struct KeyValPair {
|
|||||||
|
|
||||||
impl Dict {
|
impl Dict {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Dict { inner: HashMap::new() }
|
Dict {
|
||||||
|
inner: HashMap::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_attrs(name: &str, attrs: &[Attribute]) -> MacroResult<Self> {
|
pub(crate) fn from_attrs(name: &str, attrs: &[Attribute]) -> MacroResult<Self> {
|
||||||
let mut dict = Dict::new();
|
let mut dict = Dict::new();
|
||||||
|
|
||||||
let attribute_tags = attrs.iter()
|
let attribute_tags = attrs
|
||||||
|
.iter()
|
||||||
.filter(|attr| attr.path.is_ident(name))
|
.filter(|attr| attr.path.is_ident(name))
|
||||||
.map(|attr| attr.parse_args::<AttributeTag>());
|
.map(|attr| attr.parse_args::<AttributeTag>());
|
||||||
|
|
||||||
@@ -112,9 +115,10 @@ impl Dict {
|
|||||||
|
|
||||||
for (key, val, span) in tag.inner {
|
for (key, val, span) in tag.inner {
|
||||||
if dict.inner.contains_key(&key) {
|
if dict.inner.contains_key(&key) {
|
||||||
return Err(MacroError::new(format!(
|
return Err(MacroError::new(
|
||||||
"key appears more than once: {}", key
|
format!("key appears more than once: {}", key),
|
||||||
), span));
|
span,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
dict.inner.insert(key, (val, span));
|
dict.inner.insert(key, (val, span));
|
||||||
@@ -124,9 +128,13 @@ impl Dict {
|
|||||||
Ok(dict)
|
Ok(dict)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove_typed<T, F>(&mut self, key: &str, converter: F) -> MacroResult<Option<(T, Span)>>
|
pub(crate) fn remove_typed<T, F>(
|
||||||
|
&mut self,
|
||||||
|
key: &str,
|
||||||
|
converter: F,
|
||||||
|
) -> MacroResult<Option<(T, Span)>>
|
||||||
where
|
where
|
||||||
F: Fn(&Value) -> ValueTypeResult<T>
|
F: Fn(&Value) -> ValueTypeResult<T>,
|
||||||
{
|
{
|
||||||
match self.inner.remove(key) {
|
match self.inner.remove(key) {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
@@ -135,14 +143,19 @@ impl Dict {
|
|||||||
Err(ValueTypeError { message }) => Err(MacroError::new(
|
Err(ValueTypeError { message }) => Err(MacroError::new(
|
||||||
format!("{} for key: {}", message, key),
|
format!("{} for key: {}", message, key),
|
||||||
span,
|
span,
|
||||||
))
|
)),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove_typed_or_default<T, F>(&mut self, key: &str, default: (T, Span), converter: F) -> MacroResult<(T, Span)>
|
pub(crate) fn remove_typed_or_default<T, F>(
|
||||||
|
&mut self,
|
||||||
|
key: &str,
|
||||||
|
default: (T, Span),
|
||||||
|
converter: F,
|
||||||
|
) -> MacroResult<(T, Span)>
|
||||||
where
|
where
|
||||||
F: Fn(&Value) -> ValueTypeResult<T>
|
F: Fn(&Value) -> ValueTypeResult<T>,
|
||||||
{
|
{
|
||||||
match self.remove_typed(key, converter) {
|
match self.remove_typed(key, converter) {
|
||||||
Ok(Some(value)) => Ok(value),
|
Ok(Some(value)) => Ok(value),
|
||||||
@@ -171,15 +184,14 @@ impl Parse for AttributeTag {
|
|||||||
.parse_terminated::<KeyValPair, Token![,]>(KeyValPair::parse)?
|
.parse_terminated::<KeyValPair, Token![,]>(KeyValPair::parse)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|pair| (pair.key, pair.val, pair.span))
|
.map(|pair| (pair.key, pair.val, pair.span))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for KeyValPair {
|
impl Parse for KeyValPair {
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
let key = input
|
let key = input.parse::<Ident>()?;
|
||||||
.parse::<Ident>()?;
|
|
||||||
|
|
||||||
let val = if input.peek(Token![=]) {
|
let val = if input.peek(Token![=]) {
|
||||||
input.parse::<Token![=]>()?;
|
input.parse::<Token![=]>()?;
|
||||||
@@ -190,7 +202,8 @@ impl Parse for KeyValPair {
|
|||||||
Value::Ident(ident)
|
Value::Ident(ident)
|
||||||
} else {
|
} else {
|
||||||
return Err(input.error(format!(
|
return Err(input.error(format!(
|
||||||
"could not parse value corresponding to key: {}", key
|
"could not parse value corresponding to key: {}",
|
||||||
|
key
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -205,17 +218,23 @@ impl Parse for KeyValPair {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn speculative_parse<T>(input: ParseStream) -> syn::Result<T> where T: Parse {
|
fn speculative_parse<T>(input: ParseStream) -> syn::Result<T>
|
||||||
|
where
|
||||||
|
T: Parse,
|
||||||
|
{
|
||||||
match fork_and_parse(input) {
|
match fork_and_parse(input) {
|
||||||
Ok((fork, parsed)) => {
|
Ok((fork, parsed)) => {
|
||||||
input.advance_to(&fork);
|
input.advance_to(&fork);
|
||||||
Ok(parsed)
|
Ok(parsed)
|
||||||
}
|
}
|
||||||
Err(err) => Err(err)
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fork_and_parse<T>(input: ParseStream) -> syn::Result<(ParseBuffer, T)> where T: Parse {
|
fn fork_and_parse<T>(input: ParseStream) -> syn::Result<(ParseBuffer, T)>
|
||||||
|
where
|
||||||
|
T: Parse,
|
||||||
|
{
|
||||||
let fork = input.fork();
|
let fork = input.fork();
|
||||||
T::parse(&fork).map(move |parsed| (fork, parsed))
|
T::parse(&fork).map(move |parsed| (fork, parsed))
|
||||||
}
|
}
|
||||||
@@ -2,13 +2,13 @@ use std::collections::HashSet;
|
|||||||
|
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{DataEnum, Fields};
|
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::{DataEnum, Fields};
|
||||||
|
|
||||||
use crate::{CASE_INSENSITIVE, CRATE_ATTR, IGNORE, NAME, OTHER};
|
|
||||||
use crate::TokenStream2;
|
|
||||||
use crate::attribute::{Dict, Value};
|
use crate::attribute::{Dict, Value};
|
||||||
use crate::error::{MacroError, MacroResult};
|
use crate::error::{MacroError, MacroResult};
|
||||||
|
use crate::TokenStream2;
|
||||||
|
use crate::{CASE_INSENSITIVE, CRATE_ATTR, IGNORE, NAME, OTHER};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct Enum<'a> {
|
pub(crate) struct Enum<'a> {
|
||||||
@@ -31,7 +31,7 @@ pub(crate) enum VariantType<'a> {
|
|||||||
case_insensitive: bool,
|
case_insensitive: bool,
|
||||||
},
|
},
|
||||||
Other {
|
Other {
|
||||||
field_name: Option<&'a Ident>
|
field_name: Option<&'a Ident>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,18 +47,20 @@ impl<'a> Variant<'a> {
|
|||||||
&self,
|
&self,
|
||||||
enum_ident: &Ident,
|
enum_ident: &Ident,
|
||||||
named_fn: &F,
|
named_fn: &F,
|
||||||
other_fn: &G
|
other_fn: &G,
|
||||||
) -> MacroResult<Option<(TokenStream2, TokenStream2)>>
|
) -> MacroResult<Option<(TokenStream2, TokenStream2)>>
|
||||||
where
|
where
|
||||||
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
||||||
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>
|
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>,
|
||||||
{
|
{
|
||||||
let variant_ident = &self.data.ident;
|
let variant_ident = &self.data.ident;
|
||||||
|
|
||||||
match &self.v_type {
|
match &self.v_type {
|
||||||
VariantType::Ignore => Ok(None),
|
VariantType::Ignore => Ok(None),
|
||||||
|
|
||||||
VariantType::Named { name, constructor, .. } => {
|
VariantType::Named {
|
||||||
|
name, constructor, ..
|
||||||
|
} => {
|
||||||
let constructor_tokens = constructor.empty();
|
let constructor_tokens = constructor.empty();
|
||||||
let pattern = quote! { #enum_ident::#variant_ident #constructor_tokens };
|
let pattern = quote! { #enum_ident::#variant_ident #constructor_tokens };
|
||||||
Ok(Some((pattern, named_fn(self, enum_ident, name)?)))
|
Ok(Some((pattern, named_fn(self, enum_ident, name)?)))
|
||||||
@@ -67,13 +69,16 @@ impl<'a> Variant<'a> {
|
|||||||
VariantType::Other { field_name } => {
|
VariantType::Other { field_name } => {
|
||||||
let field_name_tokens = match field_name {
|
let field_name_tokens = match field_name {
|
||||||
Some(field_name) => field_name.to_token_stream(),
|
Some(field_name) => field_name.to_token_stream(),
|
||||||
None => quote! { __enumscribe_other_inner }
|
None => quote! { __enumscribe_other_inner },
|
||||||
};
|
};
|
||||||
let pattern = match field_name {
|
let pattern = match field_name {
|
||||||
Some(_) => quote! { #enum_ident::#variant_ident{#field_name_tokens} },
|
Some(_) => quote! { #enum_ident::#variant_ident{#field_name_tokens} },
|
||||||
None => quote! { #enum_ident::#variant_ident(#field_name_tokens) }
|
None => quote! { #enum_ident::#variant_ident(#field_name_tokens) },
|
||||||
};
|
};
|
||||||
Ok(Some((pattern, other_fn(self, enum_ident, field_name_tokens)?)))
|
Ok(Some((
|
||||||
|
pattern,
|
||||||
|
other_fn(self, enum_ident, field_name_tokens)?,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +89,7 @@ impl VariantConstructor {
|
|||||||
match self {
|
match self {
|
||||||
VariantConstructor::None => quote! {},
|
VariantConstructor::None => quote! {},
|
||||||
VariantConstructor::Paren => quote! { () },
|
VariantConstructor::Paren => quote! { () },
|
||||||
VariantConstructor::Brace => quote! { {} }
|
VariantConstructor::Brace => quote! { {} },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,9 +109,15 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
|
|
||||||
// Convert the values in the Dict to the appropriate types
|
// Convert the values in the Dict to the appropriate types
|
||||||
let name_opt = dict.remove_typed(NAME, Value::value_string)?;
|
let name_opt = dict.remove_typed(NAME, Value::value_string)?;
|
||||||
let (other, other_span) = dict.remove_typed_or_default(OTHER, (false, variant_span), Value::value_bool)?;
|
let (other, other_span) =
|
||||||
let (ignore, _) = dict.remove_typed_or_default(IGNORE, (false, variant_span), Value::value_bool)?;
|
dict.remove_typed_or_default(OTHER, (false, variant_span), Value::value_bool)?;
|
||||||
let (case_insensitive, _) = dict.remove_typed_or_default(CASE_INSENSITIVE, (false, variant_span), Value::value_bool)?;
|
let (ignore, _) =
|
||||||
|
dict.remove_typed_or_default(IGNORE, (false, variant_span), Value::value_bool)?;
|
||||||
|
let (case_insensitive, _) = dict.remove_typed_or_default(
|
||||||
|
CASE_INSENSITIVE,
|
||||||
|
(false, variant_span),
|
||||||
|
Value::value_bool,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Return an error if there are any unrecognised keys in the Dict
|
// Return an error if there are any unrecognised keys in the Dict
|
||||||
dict.assert_empty()?;
|
dict.assert_empty()?;
|
||||||
@@ -121,10 +132,7 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
// Return an error if there is already an "other" variant for this enum
|
// Return an error if there is already an "other" variant for this enum
|
||||||
if other_variant {
|
if other_variant {
|
||||||
return Err(MacroError::new(
|
return Err(MacroError::new(
|
||||||
format!(
|
format!("cannot have multiple variants marked as {}", OTHER),
|
||||||
"cannot have multiple variants marked as {}",
|
|
||||||
OTHER
|
|
||||||
),
|
|
||||||
other_span,
|
other_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -136,7 +144,9 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
return Err(MacroError::new(
|
return Err(MacroError::new(
|
||||||
format!(
|
format!(
|
||||||
"cannot use {} for variant {} because it is marked as {}",
|
"cannot use {} for variant {} because it is marked as {}",
|
||||||
NAME, variant.ident.to_string(), OTHER
|
NAME,
|
||||||
|
variant.ident,
|
||||||
|
OTHER
|
||||||
),
|
),
|
||||||
name_span,
|
name_span,
|
||||||
));
|
));
|
||||||
@@ -147,14 +157,18 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
return Err(MacroError::new(
|
return Err(MacroError::new(
|
||||||
format!(
|
format!(
|
||||||
"the variant {} must have exactly one field because it is marked as {}",
|
"the variant {} must have exactly one field because it is marked as {}",
|
||||||
variant.ident.to_string(), OTHER
|
variant.ident,
|
||||||
|
OTHER
|
||||||
),
|
),
|
||||||
variant_span,
|
variant_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the name of the variant's field (or None if it is unnamed)
|
// Get the name of the variant's field (or None if it is unnamed)
|
||||||
let field_name = variant.fields.iter().next()
|
let field_name = variant
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
.and_then(|field| field.ident.as_ref());
|
.and_then(|field| field.ident.as_ref());
|
||||||
|
|
||||||
Variant {
|
Variant {
|
||||||
@@ -166,7 +180,7 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
// Use the str name if one is provided, otherwise use the variant's name
|
// Use the str name if one is provided, otherwise use the variant's name
|
||||||
let (name, name_span) = match name_opt {
|
let (name, name_span) = match name_opt {
|
||||||
Some((name, name_span)) => (name, name_span),
|
Some((name, name_span)) => (name, name_span),
|
||||||
None => (variant.ident.to_string(), variant.ident.span())
|
None => (variant.ident.to_string(), variant.ident.span()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Do not allow duplicate names
|
// Do not allow duplicate names
|
||||||
@@ -181,7 +195,9 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
|
|
||||||
// Extra duplicate checking for case-insensitive names
|
// Extra duplicate checking for case-insensitive names
|
||||||
let lowercase_name = name.to_lowercase();
|
let lowercase_name = name.to_lowercase();
|
||||||
if taken_insensitive_names.contains(&lowercase_name) || (case_insensitive && taken_sensitive_names.contains(&lowercase_name)) {
|
if taken_insensitive_names.contains(&lowercase_name)
|
||||||
|
|| (case_insensitive && taken_sensitive_names.contains(&lowercase_name))
|
||||||
|
{
|
||||||
return Err(MacroError::new(
|
return Err(MacroError::new(
|
||||||
format!("duplicate name \"{}\"", name),
|
format!("duplicate name \"{}\"", name),
|
||||||
name_span,
|
name_span,
|
||||||
@@ -192,17 +208,17 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
&mut taken_insensitive_names
|
&mut taken_insensitive_names
|
||||||
} else {
|
} else {
|
||||||
&mut taken_sensitive_names
|
&mut taken_sensitive_names
|
||||||
}.insert(lowercase_name);
|
}
|
||||||
|
.insert(lowercase_name);
|
||||||
|
|
||||||
// Return an error if the variant has any fields
|
// Return an error if the variant has any fields
|
||||||
if !variant.fields.is_empty() {
|
if !variant.fields.is_empty() {
|
||||||
let variant_ident = variant.ident.to_string();
|
|
||||||
return Err(MacroError::new(
|
return Err(MacroError::new(
|
||||||
format!(
|
format!(
|
||||||
"the variant {} must not have any fields\n\
|
"the variant {} must not have any fields\n\
|
||||||
hint: if you do not want to remove {}\'s fields, try using \
|
hint: if you do not want to remove {}\'s fields, try using \
|
||||||
#[enumscribe(ignore)] for {}",
|
#[enumscribe(ignore)] for {}",
|
||||||
variant_ident, variant_ident, variant_ident
|
variant.ident, variant.ident, variant.ident
|
||||||
),
|
),
|
||||||
variant_span,
|
variant_span,
|
||||||
));
|
));
|
||||||
@@ -218,7 +234,11 @@ pub(crate) fn parse_enum(data: &DataEnum) -> MacroResult<Enum> {
|
|||||||
|
|
||||||
Variant {
|
Variant {
|
||||||
data: variant,
|
data: variant,
|
||||||
v_type: VariantType::Named { name, constructor, case_insensitive },
|
v_type: VariantType::Named {
|
||||||
|
name,
|
||||||
|
constructor,
|
||||||
|
case_insensitive,
|
||||||
|
},
|
||||||
span: variant_span,
|
span: variant_span,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ pub(crate) struct MacroError {
|
|||||||
pub(crate) type MacroResult<T> = result::Result<T, MacroError>;
|
pub(crate) type MacroResult<T> = result::Result<T, MacroError>;
|
||||||
|
|
||||||
impl MacroError {
|
impl MacroError {
|
||||||
pub(crate) fn new<T>(message: T, span: Span) -> Self where T: Into<Cow<'static, str>> {
|
pub(crate) fn new<T>(message: T, span: Span) -> Self
|
||||||
|
where
|
||||||
|
T: Into<Cow<'static, str>>,
|
||||||
|
{
|
||||||
MacroError {
|
MacroError {
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
span,
|
span,
|
||||||
|
|||||||
+154
-115
@@ -14,10 +14,10 @@ use syn::{Data, DataEnum, DeriveInput};
|
|||||||
|
|
||||||
use error::{MacroError, MacroResult};
|
use error::{MacroError, MacroResult};
|
||||||
|
|
||||||
use crate::enums::{Variant, VariantType, Enum};
|
use crate::enums::{Enum, Variant, VariantType};
|
||||||
|
|
||||||
mod enums;
|
|
||||||
mod attribute;
|
mod attribute;
|
||||||
|
mod enums;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
const CRATE_ATTR: &'static str = "enumscribe";
|
const CRATE_ATTR: &'static str = "enumscribe";
|
||||||
@@ -33,7 +33,7 @@ macro_rules! proc_try {
|
|||||||
($x:expr) => {
|
($x:expr) => {
|
||||||
match $x {
|
match $x {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(err) => return err.into()
|
Err(err) => return err.into(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -46,13 +46,12 @@ fn gen_scribe_impl<F, G, E>(
|
|||||||
other_fn: G,
|
other_fn: G,
|
||||||
ignore_err_fn: E,
|
ignore_err_fn: E,
|
||||||
) -> TokenStream
|
) -> TokenStream
|
||||||
where
|
where
|
||||||
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
||||||
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>,
|
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>,
|
||||||
E: Fn(&Variant, &Ident) -> MacroError
|
E: Fn(&Variant, &Ident) -> MacroError,
|
||||||
{
|
{
|
||||||
let input: DeriveInput = syn::parse(input)
|
let input: DeriveInput = syn::parse(input).expect("failed to parse input");
|
||||||
.expect("failed to parse input");
|
|
||||||
|
|
||||||
let enum_data = proc_try!(get_enum_data(&input));
|
let enum_data = proc_try!(get_enum_data(&input));
|
||||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||||
@@ -65,7 +64,7 @@ fn gen_scribe_impl<F, G, E>(
|
|||||||
match variant.match_variant(enum_ident, &named_fn, &other_fn) {
|
match variant.match_variant(enum_ident, &named_fn, &other_fn) {
|
||||||
Ok(Some((pattern, result))) => match_arms.push(quote! { #pattern => #result }),
|
Ok(Some((pattern, result))) => match_arms.push(quote! { #pattern => #result }),
|
||||||
Ok(None) => return ignore_err_fn(variant, enum_ident).into(),
|
Ok(None) => return ignore_err_fn(variant, enum_ident).into(),
|
||||||
Err(err) => return err.into()
|
Err(err) => return err.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +76,8 @@ fn gen_scribe_impl<F, G, E>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into()
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_try_scribe_impl<F, G>(
|
fn gen_try_scribe_impl<F, G>(
|
||||||
@@ -88,12 +88,11 @@ fn gen_try_scribe_impl<F, G>(
|
|||||||
other_fn: G,
|
other_fn: G,
|
||||||
ignore_result: TokenStream2,
|
ignore_result: TokenStream2,
|
||||||
) -> TokenStream
|
) -> TokenStream
|
||||||
where
|
where
|
||||||
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
F: Fn(&Variant, &Ident, &str) -> MacroResult<TokenStream2>,
|
||||||
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>
|
G: Fn(&Variant, &Ident, TokenStream2) -> MacroResult<TokenStream2>,
|
||||||
{
|
{
|
||||||
let input: DeriveInput = syn::parse(input)
|
let input: DeriveInput = syn::parse(input).expect("failed to parse input");
|
||||||
.expect("failed to parse input");
|
|
||||||
|
|
||||||
let enum_data = proc_try!(get_enum_data(&input));
|
let enum_data = proc_try!(get_enum_data(&input));
|
||||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||||
@@ -107,7 +106,7 @@ fn gen_try_scribe_impl<F, G>(
|
|||||||
match variant.match_variant(enum_ident, &named_fn, &other_fn) {
|
match variant.match_variant(enum_ident, &named_fn, &other_fn) {
|
||||||
Ok(Some((pattern, result))) => match_arms.push(quote! { #pattern => #result }),
|
Ok(Some((pattern, result))) => match_arms.push(quote! { #pattern => #result }),
|
||||||
Ok(None) => ignore_variant = true,
|
Ok(None) => ignore_variant = true,
|
||||||
Err(err) => return err.into()
|
Err(err) => return err.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +125,8 @@ fn gen_try_scribe_impl<F, G>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into()
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_unscribe_impl<F, G, E>(
|
fn gen_unscribe_impl<F, G, E>(
|
||||||
@@ -138,13 +138,12 @@ fn gen_unscribe_impl<F, G, E>(
|
|||||||
other_fn: G,
|
other_fn: G,
|
||||||
other_missing_fn: E,
|
other_missing_fn: E,
|
||||||
) -> TokenStream
|
) -> TokenStream
|
||||||
where
|
where
|
||||||
F: Fn(TokenStream2) -> TokenStream2,
|
F: Fn(TokenStream2) -> TokenStream2,
|
||||||
G: Fn(TokenStream2) -> TokenStream2,
|
G: Fn(TokenStream2) -> TokenStream2,
|
||||||
E: Fn(&Ident) -> MacroResult<TokenStream2>
|
E: Fn(&Ident) -> MacroResult<TokenStream2>,
|
||||||
{
|
{
|
||||||
let input: DeriveInput = syn::parse(input)
|
let input: DeriveInput = syn::parse(input).expect("failed to parse input");
|
||||||
.expect("failed to parse input");
|
|
||||||
|
|
||||||
let enum_data = proc_try!(get_enum_data(&input));
|
let enum_data = proc_try!(get_enum_data(&input));
|
||||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||||
@@ -154,7 +153,12 @@ fn gen_unscribe_impl<F, G, E>(
|
|||||||
let to_unscribe_ident = quote! { __enumscribe_to_unscribe };
|
let to_unscribe_ident = quote! { __enumscribe_to_unscribe };
|
||||||
|
|
||||||
let main_match = proc_try!(gen_unscribe_match(
|
let main_match = proc_try!(gen_unscribe_match(
|
||||||
enum_ident, &parsed_enum, &to_unscribe_ident, named_fn, other_fn, other_missing_fn
|
enum_ident,
|
||||||
|
&parsed_enum,
|
||||||
|
&to_unscribe_ident,
|
||||||
|
named_fn,
|
||||||
|
other_fn,
|
||||||
|
other_missing_fn
|
||||||
));
|
));
|
||||||
|
|
||||||
(quote! {
|
(quote! {
|
||||||
@@ -163,7 +167,8 @@ fn gen_unscribe_impl<F, G, E>(
|
|||||||
#main_match
|
#main_match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into()
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_unscribe_match<F, G, E>(
|
fn gen_unscribe_match<F, G, E>(
|
||||||
@@ -174,10 +179,10 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
other_fn: G,
|
other_fn: G,
|
||||||
other_missing_fn: E,
|
other_missing_fn: E,
|
||||||
) -> MacroResult<TokenStream2>
|
) -> MacroResult<TokenStream2>
|
||||||
where
|
where
|
||||||
F: Fn(TokenStream2) -> TokenStream2,
|
F: Fn(TokenStream2) -> TokenStream2,
|
||||||
G: Fn(TokenStream2) -> TokenStream2,
|
G: Fn(TokenStream2) -> TokenStream2,
|
||||||
E: Fn(&Ident) -> MacroResult<TokenStream2>
|
E: Fn(&Ident) -> MacroResult<TokenStream2>,
|
||||||
{
|
{
|
||||||
let mut other_arm = None;
|
let mut other_arm = None;
|
||||||
let mut case_sensitive_arms = Vec::new();
|
let mut case_sensitive_arms = Vec::new();
|
||||||
@@ -189,7 +194,11 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
match &variant.v_type {
|
match &variant.v_type {
|
||||||
VariantType::Ignore => (),
|
VariantType::Ignore => (),
|
||||||
|
|
||||||
VariantType::Named { name, constructor, case_insensitive } => {
|
VariantType::Named {
|
||||||
|
name,
|
||||||
|
constructor,
|
||||||
|
case_insensitive,
|
||||||
|
} => {
|
||||||
let match_pattern = if *case_insensitive {
|
let match_pattern = if *case_insensitive {
|
||||||
let lowercase_name = name.to_lowercase();
|
let lowercase_name = name.to_lowercase();
|
||||||
quote! { #lowercase_name }
|
quote! { #lowercase_name }
|
||||||
@@ -198,18 +207,21 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let constructor_tokens = constructor.empty();
|
let constructor_tokens = constructor.empty();
|
||||||
let constructed_variant = quote! { #enum_ident::#variant_ident #constructor_tokens };
|
let constructed_variant =
|
||||||
|
quote! { #enum_ident::#variant_ident #constructor_tokens };
|
||||||
let match_result = named_fn(constructed_variant);
|
let match_result = named_fn(constructed_variant);
|
||||||
|
|
||||||
if *case_insensitive {
|
if *case_insensitive {
|
||||||
&mut case_insensitive_arms
|
&mut case_insensitive_arms
|
||||||
} else {
|
} else {
|
||||||
&mut case_sensitive_arms
|
&mut case_sensitive_arms
|
||||||
}.push(quote! { #match_pattern => #match_result });
|
}
|
||||||
|
.push(quote! { #match_pattern => #match_result });
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantType::Other { field_name } => {
|
VariantType::Other { field_name } => {
|
||||||
let unscribe_value = quote! { <_ as ::std::convert::Into<_>>::into(#match_against) };
|
let unscribe_value =
|
||||||
|
quote! { <_ as ::std::convert::Into<_>>::into(#match_against) };
|
||||||
|
|
||||||
let constructed_variant = match field_name {
|
let constructed_variant = match field_name {
|
||||||
None => quote! {
|
None => quote! {
|
||||||
@@ -217,7 +229,7 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
},
|
},
|
||||||
Some(field_name) => quote! {
|
Some(field_name) => quote! {
|
||||||
#enum_ident::#variant_ident { #field_name: #unscribe_value }
|
#enum_ident::#variant_ident { #field_name: #unscribe_value }
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let match_result = other_fn(constructed_variant);
|
let match_result = other_fn(constructed_variant);
|
||||||
@@ -229,7 +241,7 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
|
|
||||||
let other_arm = match other_arm {
|
let other_arm = match other_arm {
|
||||||
Some(other_arm) => other_arm,
|
Some(other_arm) => other_arm,
|
||||||
None => other_missing_fn(enum_ident)?
|
None => other_missing_fn(enum_ident)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let case_insensitive_match = if case_insensitive_arms.is_empty() {
|
let case_insensitive_match = if case_insensitive_arms.is_empty() {
|
||||||
@@ -258,16 +270,14 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
(true, Some(case_insensitive_match)) => {
|
(true, Some(case_insensitive_match)) => case_insensitive_match,
|
||||||
case_insensitive_match
|
|
||||||
}
|
|
||||||
|
|
||||||
(false, Some(case_insensitive_match)) => quote! {
|
(false, Some(case_insensitive_match)) => quote! {
|
||||||
match #match_against {
|
match #match_against {
|
||||||
#(#case_sensitive_arms,)*
|
#(#case_sensitive_arms,)*
|
||||||
_ => { #case_insensitive_match },
|
_ => { #case_insensitive_match },
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(main_match)
|
Ok(main_match)
|
||||||
@@ -301,26 +311,32 @@ fn gen_unscribe_match<F, G, E>(
|
|||||||
pub fn derive_scribe_static_str(input: TokenStream) -> TokenStream {
|
pub fn derive_scribe_static_str(input: TokenStream) -> TokenStream {
|
||||||
gen_scribe_impl(
|
gen_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::ScribeStaticStr },
|
quote! { ::enumscribe::ScribeStaticStr },
|
||||||
quote! { &'static str },
|
quote! { &'static str },
|
||||||
|
|
||||||
|_, _, name| Ok(quote! { #name }),
|
|_, _, name| Ok(quote! { #name }),
|
||||||
|
|variant, enum_ident, _| {
|
||||||
|variant, enum_ident, _| Err(MacroError::new(format!(
|
Err(MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive ScribeStaticStr for {} because the variant {} is marked as {}, so \
|
"cannot derive ScribeStaticStr for {} because the variant {} is marked as {}, so \
|
||||||
there is no &'static str associated with it\n\
|
there is no &'static str associated with it\n\
|
||||||
hint: try deriving ScribeCowStr instead",
|
hint: try deriving ScribeCowStr instead",
|
||||||
enum_ident, variant.data.ident, OTHER
|
enum_ident, variant.data.ident, OTHER
|
||||||
), variant.span)),
|
),
|
||||||
|
variant.span,
|
||||||
|variant, enum_ident| MacroError::new(format!(
|
))
|
||||||
|
},
|
||||||
|
|variant, enum_ident| {
|
||||||
|
MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive ScribeStaticStr for {} because the variant {} is marked as {}\n\
|
"cannot derive ScribeStaticStr for {} because the variant {} is marked as {}\n\
|
||||||
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
||||||
always be successfully converted to a String\n\
|
always be successfully converted to a String\n\
|
||||||
hint: try deriving TryScribeStaticStr instead",
|
hint: try deriving TryScribeStaticStr instead",
|
||||||
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
||||||
), variant.span),
|
),
|
||||||
|
variant.span,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,21 +359,24 @@ pub fn derive_scribe_static_str(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_try_scribe_static_str(input: TokenStream) -> TokenStream {
|
pub fn derive_try_scribe_static_str(input: TokenStream) -> TokenStream {
|
||||||
gen_try_scribe_impl(
|
gen_try_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::TryScribeStaticStr },
|
quote! { ::enumscribe::TryScribeStaticStr },
|
||||||
quote! { ::std::option::Option<&'static str> },
|
quote! { ::std::option::Option<&'static str> },
|
||||||
|
|_, _, name| {
|
||||||
|_, _, name| Ok(quote! {
|
Ok(quote! {
|
||||||
::std::option::Option::Some(#name)
|
::std::option::Option::Some(#name)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|variant, enum_ident, _| Err(MacroError::new(format!(
|
|variant, enum_ident, _| {
|
||||||
|
Err(MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive TryScribeStaticStr for {} because the variant {} is marked as {}, so \
|
"cannot derive TryScribeStaticStr for {} because the variant {} is marked as {}, so \
|
||||||
there is no &'static str associated with it\n\
|
there is no &'static str associated with it\n\
|
||||||
hint: try deriving TryScribeCowStr instead",
|
hint: try deriving TryScribeCowStr instead",
|
||||||
enum_ident, variant.data.ident, OTHER
|
enum_ident, variant.data.ident, OTHER
|
||||||
), variant.span)),
|
),
|
||||||
|
variant.span,
|
||||||
|
))
|
||||||
|
},
|
||||||
quote! { ::std::option::Option::None },
|
quote! { ::std::option::Option::None },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -375,25 +394,30 @@ pub fn derive_try_scribe_static_str(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_scribe_string(input: TokenStream) -> TokenStream {
|
pub fn derive_scribe_string(input: TokenStream) -> TokenStream {
|
||||||
gen_scribe_impl(
|
gen_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::ScribeString },
|
quote! { ::enumscribe::ScribeString },
|
||||||
quote! { ::std::string::String },
|
quote! { ::std::string::String },
|
||||||
|
|_, _, name| {
|
||||||
|_, _, name| Ok(quote! {
|
Ok(quote! {
|
||||||
<_ as ::std::borrow::ToOwned>::to_owned(#name)
|
<_ as ::std::borrow::ToOwned>::to_owned(#name)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|_, _, field| Ok(quote! {
|
|_, _, field| {
|
||||||
|
Ok(quote! {
|
||||||
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|variant, enum_ident| MacroError::new(format!(
|
|variant, enum_ident| {
|
||||||
|
MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive ScribeString for {} because the variant {} is marked as {}\n\
|
"cannot derive ScribeString for {} because the variant {} is marked as {}\n\
|
||||||
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
||||||
always be successfully converted to a String\n\
|
always be successfully converted to a String\n\
|
||||||
hint: try deriving TryScribeString instead",
|
hint: try deriving TryScribeString instead",
|
||||||
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
||||||
), variant.span),
|
),
|
||||||
|
variant.span,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,22 +434,22 @@ pub fn derive_scribe_string(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_try_scribe_string(input: TokenStream) -> TokenStream {
|
pub fn derive_try_scribe_string(input: TokenStream) -> TokenStream {
|
||||||
gen_try_scribe_impl(
|
gen_try_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::TryScribeString },
|
quote! { ::enumscribe::TryScribeString },
|
||||||
quote! { ::std::option::Option<::std::string::String> },
|
quote! { ::std::option::Option<::std::string::String> },
|
||||||
|
|_, _, name| {
|
||||||
|_, _, name| Ok(quote! {
|
Ok(quote! {
|
||||||
::std::option::Option::Some(
|
::std::option::Option::Some(
|
||||||
<_ as ::std::borrow::ToOwned>::to_owned(#name)
|
<_ as ::std::borrow::ToOwned>::to_owned(#name)
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|_, _, field| Ok(quote! {
|
|_, _, field| {
|
||||||
|
Ok(quote! {
|
||||||
::std::option::Option::Some(
|
::std::option::Option::Some(
|
||||||
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
quote! { ::std::option::Option::None },
|
quote! { ::std::option::Option::None },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -453,27 +477,32 @@ pub fn derive_try_scribe_string(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_scribe_cow_str(input: TokenStream) -> TokenStream {
|
pub fn derive_scribe_cow_str(input: TokenStream) -> TokenStream {
|
||||||
gen_scribe_impl(
|
gen_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::ScribeCowStr },
|
quote! { ::enumscribe::ScribeCowStr },
|
||||||
quote! { ::std::borrow::Cow<'static, str> },
|
quote! { ::std::borrow::Cow<'static, str> },
|
||||||
|
|_, _, name| {
|
||||||
|_, _, name| Ok(quote! {
|
Ok(quote! {
|
||||||
::std::borrow::Cow::Borrowed(#name)
|
::std::borrow::Cow::Borrowed(#name)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|_, _, field| Ok(quote! {
|
|_, _, field| {
|
||||||
|
Ok(quote! {
|
||||||
::std::borrow::Cow::Owned(
|
::std::borrow::Cow::Owned(
|
||||||
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|variant, enum_ident| MacroError::new(format!(
|
|variant, enum_ident| {
|
||||||
|
MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive ScribeCowStr for {} because the variant {} is marked as {}\n\
|
"cannot derive ScribeCowStr for {} because the variant {} is marked as {}\n\
|
||||||
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
explanation: since {} is ignored, it cannot be guaranteed that the enum can \
|
||||||
always be successfully converted to a String\n\
|
always be successfully converted to a String\n\
|
||||||
hint: try deriving TryScribeCowStr instead",
|
hint: try deriving TryScribeCowStr instead",
|
||||||
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
enum_ident, variant.data.ident, IGNORE, variant.data.ident
|
||||||
), variant.span),
|
),
|
||||||
|
variant.span,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,24 +530,24 @@ pub fn derive_scribe_cow_str(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_try_scribe_cow_str(input: TokenStream) -> TokenStream {
|
pub fn derive_try_scribe_cow_str(input: TokenStream) -> TokenStream {
|
||||||
gen_try_scribe_impl(
|
gen_try_scribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::TryScribeCowStr },
|
quote! { ::enumscribe::TryScribeCowStr },
|
||||||
quote! { ::std::option::Option<::std::borrow::Cow<'static, str>> },
|
quote! { ::std::option::Option<::std::borrow::Cow<'static, str>> },
|
||||||
|
|_, _, name| {
|
||||||
|_, _, name| Ok(quote! {
|
Ok(quote! {
|
||||||
::std::option::Option::Some(
|
::std::option::Option::Some(
|
||||||
::std::borrow::Cow::Borrowed(#name)
|
::std::borrow::Cow::Borrowed(#name)
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
|_, _, field| Ok(quote! {
|
|_, _, field| {
|
||||||
|
Ok(quote! {
|
||||||
::std::option::Option::Some(
|
::std::option::Option::Some(
|
||||||
::std::borrow::Cow::Owned(
|
::std::borrow::Cow::Owned(
|
||||||
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
<_ as ::std::convert::Into<::std::string::String>>::into(#field)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
quote! { ::std::option::Option::None },
|
quote! { ::std::option::Option::None },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -548,22 +577,23 @@ pub fn derive_try_scribe_cow_str(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_unscribe(input: TokenStream) -> TokenStream {
|
pub fn derive_unscribe(input: TokenStream) -> TokenStream {
|
||||||
gen_unscribe_impl(
|
gen_unscribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::Unscribe },
|
quote! { ::enumscribe::Unscribe },
|
||||||
quote! { unscribe },
|
quote! { unscribe },
|
||||||
quote! { Self },
|
quote! { Self },
|
||||||
|
|
||||||
|constructed_named_variant| constructed_named_variant,
|
|constructed_named_variant| constructed_named_variant,
|
||||||
|
|
||||||
|constructed_other_variant| constructed_other_variant,
|
|constructed_other_variant| constructed_other_variant,
|
||||||
|
|enum_ident| {
|
||||||
|enum_ident| Err(MacroError::new(format!(
|
Err(MacroError::new(
|
||||||
|
format!(
|
||||||
"cannot derive Unscribe for {} because no variant is marked as {}\n\
|
"cannot derive Unscribe for {} because no variant is marked as {}\n\
|
||||||
explanation: since there is no {} variant, it cannot be guaranteed that every string \
|
explanation: since there is no {} variant, it cannot be guaranteed that every string \
|
||||||
can be successfully converted to a variant of {}\n\
|
can be successfully converted to a variant of {}\n\
|
||||||
hint: either introduce an {} variant, or try deriving TryUnscribe instead",
|
hint: either introduce an {} variant, or try deriving TryUnscribe instead",
|
||||||
enum_ident, OTHER, OTHER, enum_ident, OTHER
|
enum_ident, OTHER, OTHER, enum_ident, OTHER
|
||||||
), enum_ident.span())),
|
),
|
||||||
|
enum_ident.span(),
|
||||||
|
))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,15 +619,11 @@ pub fn derive_unscribe(input: TokenStream) -> TokenStream {
|
|||||||
pub fn derive_try_unscribe(input: TokenStream) -> TokenStream {
|
pub fn derive_try_unscribe(input: TokenStream) -> TokenStream {
|
||||||
gen_unscribe_impl(
|
gen_unscribe_impl(
|
||||||
input,
|
input,
|
||||||
|
|
||||||
quote! { ::enumscribe::TryUnscribe },
|
quote! { ::enumscribe::TryUnscribe },
|
||||||
quote! { try_unscribe },
|
quote! { try_unscribe },
|
||||||
quote! { ::std::option::Option<Self> },
|
quote! { ::std::option::Option<Self> },
|
||||||
|
|
||||||
|constructed_named_variant| quote! { ::std::option::Option::Some(#constructed_named_variant) },
|
|constructed_named_variant| quote! { ::std::option::Option::Some(#constructed_named_variant) },
|
||||||
|
|
||||||
|constructed_other_variant| quote! { ::std::option::Option::Some(#constructed_other_variant) },
|
|constructed_other_variant| quote! { ::std::option::Option::Some(#constructed_other_variant) },
|
||||||
|
|
||||||
|_| Ok(quote! { _ => ::std::option::Option::None }),
|
|_| Ok(quote! { _ => ::std::option::Option::None }),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -614,8 +640,7 @@ pub fn derive_try_unscribe(input: TokenStream) -> TokenStream {
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[proc_macro_derive(EnumSerialize, attributes(enumscribe))]
|
#[proc_macro_derive(EnumSerialize, attributes(enumscribe))]
|
||||||
pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
||||||
let input: DeriveInput = syn::parse(input)
|
let input: DeriveInput = syn::parse(input).expect("failed to parse input");
|
||||||
.expect("failed to parse input");
|
|
||||||
|
|
||||||
let enum_data = proc_try!(get_enum_data(&input));
|
let enum_data = proc_try!(get_enum_data(&input));
|
||||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||||
@@ -632,7 +657,9 @@ pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
|||||||
match &variant.v_type {
|
match &variant.v_type {
|
||||||
VariantType::Ignore => ignore_variant = true,
|
VariantType::Ignore => ignore_variant = true,
|
||||||
|
|
||||||
VariantType::Named { name, constructor, .. } => {
|
VariantType::Named {
|
||||||
|
name, constructor, ..
|
||||||
|
} => {
|
||||||
let constructor_tokens = constructor.empty();
|
let constructor_tokens = constructor.empty();
|
||||||
match_arms.push(quote! {
|
match_arms.push(quote! {
|
||||||
#enum_ident::#variant_ident #constructor_tokens =>
|
#enum_ident::#variant_ident #constructor_tokens =>
|
||||||
@@ -640,14 +667,11 @@ pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantType::Other { field_name } => {
|
VariantType::Other { field_name } => match field_name {
|
||||||
match field_name {
|
Some(field_name) => match_arms.push(quote! {
|
||||||
Some(field_name) => {
|
|
||||||
match_arms.push(quote! {
|
|
||||||
#enum_ident::#variant_ident { #field_name } =>
|
#enum_ident::#variant_ident { #field_name } =>
|
||||||
#serializer_ident.serialize_str(&#field_name)
|
#serializer_ident.serialize_str(&#field_name)
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
let field_name = quote! { __enumscribe_other_inner };
|
let field_name = quote! { __enumscribe_other_inner };
|
||||||
match_arms.push(quote! {
|
match_arms.push(quote! {
|
||||||
@@ -655,8 +679,7 @@ pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
|||||||
#serializer_ident.serialize_str(&#field_name)
|
#serializer_ident.serialize_str(&#field_name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,7 +708,8 @@ pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into()
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives `serde::Deserialize` for an enum.
|
/// Derives `serde::Deserialize` for an enum.
|
||||||
@@ -707,8 +731,7 @@ pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[proc_macro_derive(EnumDeserialize, attributes(enumscribe))]
|
#[proc_macro_derive(EnumDeserialize, attributes(enumscribe))]
|
||||||
pub fn derive_enum_deserialize(input: TokenStream) -> TokenStream {
|
pub fn derive_enum_deserialize(input: TokenStream) -> TokenStream {
|
||||||
let input: DeriveInput = syn::parse(input)
|
let input: DeriveInput = syn::parse(input).expect("failed to parse input");
|
||||||
.expect("failed to parse input");
|
|
||||||
|
|
||||||
let enum_data = proc_try!(get_enum_data(&input));
|
let enum_data = proc_try!(get_enum_data(&input));
|
||||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||||
@@ -719,10 +742,12 @@ pub fn derive_enum_deserialize(input: TokenStream) -> TokenStream {
|
|||||||
let deserialized_string_ident = quote! { __enumscribe_deserialized_string };
|
let deserialized_string_ident = quote! { __enumscribe_deserialized_string };
|
||||||
let deserialized_str_ident = quote! { __enumscribe_deserialized_str };
|
let deserialized_str_ident = quote! { __enumscribe_deserialized_str };
|
||||||
|
|
||||||
let variant_strings = parsed_enum.variants.iter()
|
let variant_strings = parsed_enum
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
.map(|variant| match &variant.v_type {
|
.map(|variant| match &variant.v_type {
|
||||||
VariantType::Named { name, .. } => Some(name.as_str()),
|
VariantType::Named { name, .. } => Some(name.as_str()),
|
||||||
_ => None
|
_ => None,
|
||||||
})
|
})
|
||||||
.filter(|name| name.is_some())
|
.filter(|name| name.is_some())
|
||||||
.map(|name| name.unwrap())
|
.map(|name| name.unwrap())
|
||||||
@@ -759,18 +784,32 @@ pub fn derive_enum_deserialize(input: TokenStream) -> TokenStream {
|
|||||||
#main_match
|
#main_match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).into()
|
})
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_enum_data(input: &DeriveInput) -> MacroResult<&DataEnum> {
|
fn get_enum_data(input: &DeriveInput) -> MacroResult<&DataEnum> {
|
||||||
let enum_data = match &input.data {
|
let enum_data = match &input.data {
|
||||||
Data::Enum(enum_data) => enum_data,
|
Data::Enum(enum_data) => enum_data,
|
||||||
Data::Struct(_) => return Err(MacroError::new("enumscribe cannot be used for structs", input.ident.span())),
|
Data::Struct(_) => {
|
||||||
Data::Union(_) => return Err(MacroError::new("enumscribe cannot be used for unions", input.ident.span()))
|
return Err(MacroError::new(
|
||||||
|
"enumscribe cannot be used for structs",
|
||||||
|
input.ident.span(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Data::Union(_) => {
|
||||||
|
return Err(MacroError::new(
|
||||||
|
"enumscribe cannot be used for unions",
|
||||||
|
input.ident.span(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if enum_data.variants.is_empty() {
|
if enum_data.variants.is_empty() {
|
||||||
return Err(MacroError::new("enumscribe cannot be used for empty enums", input.ident.span()));
|
return Err(MacroError::new(
|
||||||
|
"enumscribe cannot be used for empty enums",
|
||||||
|
input.ident.span(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(enum_data)
|
Ok(enum_data)
|
||||||
|
|||||||
@@ -39,12 +39,16 @@ fn main() {
|
|||||||
|
|
||||||
let info = AirportInfo {
|
let info = AirportInfo {
|
||||||
airport: Airport::Gatwick(),
|
airport: Airport::Gatwick(),
|
||||||
info: "It's somewhere in London, innit".to_owned()
|
info: "It's somewhere in London, innit".to_owned(),
|
||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string(&info).unwrap());
|
println!("{}", serde_json::to_string(&info).unwrap());
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
let info_str = r#"{ "airport": "lgw", "info": "Fun Gatwick fact: I'm fresh out of Gatwick facts" }"#;
|
let info_str =
|
||||||
println!("{:?}", serde_json::from_str::<AirportInfo>(info_str).unwrap());
|
r#"{ "airport": "lgw", "info": "Fun Gatwick fact: I'm fresh out of Gatwick facts" }"#;
|
||||||
|
println!(
|
||||||
|
"{:?}",
|
||||||
|
serde_json::from_str::<AirportInfo>(info_str).unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ fn case_insensitivity_example() {
|
|||||||
fn other_example() {
|
fn other_example() {
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use enumscribe::{Unscribe, ScribeCowStr};
|
use enumscribe::{ScribeCowStr, Unscribe};
|
||||||
|
|
||||||
#[derive(ScribeCowStr, Unscribe, PartialEq, Eq, Debug)]
|
#[derive(ScribeCowStr, Unscribe, PartialEq, Eq, Debug)]
|
||||||
enum Website {
|
enum Website {
|
||||||
@@ -61,12 +61,21 @@ fn other_example() {
|
|||||||
assert_eq!(Website::unscribe("github.com"), Website::Github);
|
assert_eq!(Website::unscribe("github.com"), Website::Github);
|
||||||
|
|
||||||
// Unbelievably, there exist websites other than github and crates.io
|
// Unbelievably, there exist websites other than github and crates.io
|
||||||
assert_eq!(Website::unscribe("stackoverflow.com"), Website::Other("stackoverflow.com".to_owned()));
|
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
|
// 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::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()));
|
assert_eq!(
|
||||||
|
Website::Other("owasp.org".to_owned()).scribe(),
|
||||||
|
Cow::Owned::<'static, str>("owasp.org".to_owned())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ignore_example() {
|
fn ignore_example() {
|
||||||
@@ -90,9 +99,9 @@ fn ignore_example() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serde_example() {
|
fn serde_example() {
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use enumscribe::{EnumSerialize, EnumDeserialize};
|
use enumscribe::{EnumDeserialize, EnumSerialize};
|
||||||
|
|
||||||
#[derive(EnumSerialize, EnumDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
|
#[derive(EnumSerialize, EnumDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
enum Airport {
|
enum Airport {
|
||||||
@@ -118,7 +127,10 @@ fn serde_example() {
|
|||||||
|
|
||||||
let flight_json = r#"{"takeoff":"LHR","landing":"LGW"}"#;
|
let flight_json = r#"{"takeoff":"LHR","landing":"LGW"}"#;
|
||||||
|
|
||||||
assert_eq!(serde_json::to_string(&flight).unwrap(), flight_json.to_owned());
|
assert_eq!(
|
||||||
|
serde_json::to_string(&flight).unwrap(),
|
||||||
|
flight_json.to_owned()
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(serde_json::from_str::<Flight>(flight_json).unwrap(), flight);
|
assert_eq!(serde_json::from_str::<Flight>(flight_json).unwrap(), flight);
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use enumscribe::{
|
use enumscribe::{
|
||||||
ScribeCowStr,
|
ScribeCowStr, ScribeStaticStr, ScribeString, TryScribeCowStr, TryScribeStaticStr,
|
||||||
ScribeStaticStr,
|
|
||||||
ScribeString,
|
|
||||||
TryScribeCowStr,
|
|
||||||
TryScribeStaticStr,
|
|
||||||
TryScribeString,
|
TryScribeString,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_STRINGS: [&'static str; 6] = [
|
const TEST_STRINGS: [&'static str; 6] =
|
||||||
"", "\0", "foo", "baa", "Hello, world!", "こんにちは、世界"
|
["", "\0", "foo", "baa", "Hello, world!", "こんにちは、世界"];
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scribe_static_str() {
|
fn test_scribe_static_str() {
|
||||||
@@ -54,7 +49,10 @@ fn test_try_scribe_static_str() {
|
|||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V7(i32, i32),
|
V7(i32, i32),
|
||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V8 { s: &'static str, x: i32 },
|
V8 {
|
||||||
|
s: &'static str,
|
||||||
|
x: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(E0::V0.try_scribe(), Some("V0"));
|
assert_eq!(E0::V0.try_scribe(), Some("V0"));
|
||||||
@@ -65,7 +63,14 @@ fn test_try_scribe_static_str() {
|
|||||||
assert_eq!(E0::V5 {}.try_scribe(), Some("baz"));
|
assert_eq!(E0::V5 {}.try_scribe(), Some("baz"));
|
||||||
assert_eq!(E0::V6.try_scribe(), None);
|
assert_eq!(E0::V6.try_scribe(), None);
|
||||||
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
||||||
assert_eq!(E0::V8 { s: "lorem ipsum", x: 246 }.try_scribe(), None);
|
assert_eq!(
|
||||||
|
E0::V8 {
|
||||||
|
s: "lorem ipsum",
|
||||||
|
x: 246
|
||||||
|
}
|
||||||
|
.try_scribe(),
|
||||||
|
None
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -135,7 +140,10 @@ fn test_try_scribe_string() {
|
|||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V7(i32, i32),
|
V7(i32, i32),
|
||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V8 { s: &'static str, x: i32 },
|
V8 {
|
||||||
|
s: &'static str,
|
||||||
|
x: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(E0::V0.try_scribe(), Some("V0".to_owned()));
|
assert_eq!(E0::V0.try_scribe(), Some("V0".to_owned()));
|
||||||
@@ -146,7 +154,14 @@ fn test_try_scribe_string() {
|
|||||||
assert_eq!(E0::V5 {}.try_scribe(), Some("baz".to_owned()));
|
assert_eq!(E0::V5 {}.try_scribe(), Some("baz".to_owned()));
|
||||||
assert_eq!(E0::V6.try_scribe(), None);
|
assert_eq!(E0::V6.try_scribe(), None);
|
||||||
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
||||||
assert_eq!(E0::V8 { s: "lorem ipsum", x: 246 }.try_scribe(), None);
|
assert_eq!(
|
||||||
|
E0::V8 {
|
||||||
|
s: "lorem ipsum",
|
||||||
|
x: 246
|
||||||
|
}
|
||||||
|
.try_scribe(),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(TryScribeString, Eq, PartialEq, Debug)]
|
#[derive(TryScribeString, Eq, PartialEq, Debug)]
|
||||||
enum E1 {
|
enum E1 {
|
||||||
@@ -213,7 +228,10 @@ fn test_scribe_cow_str() {
|
|||||||
|
|
||||||
assert_eq!(E1::V0.scribe(), Cow::Borrowed("foo"));
|
assert_eq!(E1::V0.scribe(), Cow::Borrowed("foo"));
|
||||||
for &x in &TEST_STRINGS {
|
for &x in &TEST_STRINGS {
|
||||||
assert_eq!(E1::V1(x.to_owned()).scribe(), Cow::Owned::<'static, str>(x.to_owned()));
|
assert_eq!(
|
||||||
|
E1::V1(x.to_owned()).scribe(),
|
||||||
|
Cow::Owned::<'static, str>(x.to_owned())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ScribeCowStr, Eq, PartialEq, Debug)]
|
#[derive(ScribeCowStr, Eq, PartialEq, Debug)]
|
||||||
@@ -226,7 +244,10 @@ fn test_scribe_cow_str() {
|
|||||||
|
|
||||||
assert_eq!(E2::V0.scribe(), "foo".to_owned());
|
assert_eq!(E2::V0.scribe(), "foo".to_owned());
|
||||||
for &x in &TEST_STRINGS {
|
for &x in &TEST_STRINGS {
|
||||||
assert_eq!(E2::V1 { s: x.to_owned() }.scribe(), Cow::Owned::<'static, str>(x.to_owned()));
|
assert_eq!(
|
||||||
|
E2::V1 { s: x.to_owned() }.scribe(),
|
||||||
|
Cow::Owned::<'static, str>(x.to_owned())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +269,10 @@ fn test_try_scribe_cow_str() {
|
|||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V7(i32, i32),
|
V7(i32, i32),
|
||||||
#[enumscribe(ignore)]
|
#[enumscribe(ignore)]
|
||||||
V8 { s: &'static str, x: i32 },
|
V8 {
|
||||||
|
s: &'static str,
|
||||||
|
x: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(E0::V0.try_scribe(), Some(Cow::Borrowed("V0")));
|
assert_eq!(E0::V0.try_scribe(), Some(Cow::Borrowed("V0")));
|
||||||
@@ -259,7 +283,14 @@ fn test_try_scribe_cow_str() {
|
|||||||
assert_eq!(E0::V5 {}.try_scribe(), Some(Cow::Borrowed("baz")));
|
assert_eq!(E0::V5 {}.try_scribe(), Some(Cow::Borrowed("baz")));
|
||||||
assert_eq!(E0::V6.try_scribe(), None);
|
assert_eq!(E0::V6.try_scribe(), None);
|
||||||
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
assert_eq!(E0::V7(123, 456).try_scribe(), None);
|
||||||
assert_eq!(E0::V8 { s: "lorem ipsum", x: 246 }.try_scribe(), None);
|
assert_eq!(
|
||||||
|
E0::V8 {
|
||||||
|
s: "lorem ipsum",
|
||||||
|
x: 246
|
||||||
|
}
|
||||||
|
.try_scribe(),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(TryScribeCowStr, Eq, PartialEq, Debug)]
|
#[derive(TryScribeCowStr, Eq, PartialEq, Debug)]
|
||||||
enum E1 {
|
enum E1 {
|
||||||
@@ -273,7 +304,10 @@ fn test_try_scribe_cow_str() {
|
|||||||
|
|
||||||
assert_eq!(E1::V0.try_scribe(), Some(Cow::Borrowed("foo")));
|
assert_eq!(E1::V0.try_scribe(), Some(Cow::Borrowed("foo")));
|
||||||
for &x in &TEST_STRINGS {
|
for &x in &TEST_STRINGS {
|
||||||
assert_eq!(E1::V1(x.to_owned()).try_scribe(), Some(Cow::Owned::<'static, str>(x.to_owned())));
|
assert_eq!(
|
||||||
|
E1::V1(x.to_owned()).try_scribe(),
|
||||||
|
Some(Cow::Owned::<'static, str>(x.to_owned()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(E1::V2.try_scribe(), None);
|
assert_eq!(E1::V2.try_scribe(), None);
|
||||||
|
|
||||||
@@ -289,7 +323,10 @@ fn test_try_scribe_cow_str() {
|
|||||||
|
|
||||||
assert_eq!(E2::V0.try_scribe(), Some(Cow::Borrowed("foo")));
|
assert_eq!(E2::V0.try_scribe(), Some(Cow::Borrowed("foo")));
|
||||||
for &x in &TEST_STRINGS {
|
for &x in &TEST_STRINGS {
|
||||||
assert_eq!(E2::V1 { s: x.to_owned() }.try_scribe(), Some(Cow::Owned::<'static, str>(x.to_owned())));
|
assert_eq!(
|
||||||
|
E2::V1 { s: x.to_owned() }.try_scribe(),
|
||||||
|
Some(Cow::Owned::<'static, str>(x.to_owned()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(E2::V2.try_scribe(), None);
|
assert_eq!(E2::V2.try_scribe(), None);
|
||||||
}
|
}
|
||||||
@@ -279,24 +279,42 @@ fn test_try_unscribe() {
|
|||||||
assert_eq!(E1::try_unscribe("loREM"), Some(E1::V7));
|
assert_eq!(E1::try_unscribe("loREM"), Some(E1::V7));
|
||||||
assert_eq!(E1::try_unscribe("larem"), Some(E1::V12("larem".to_owned())));
|
assert_eq!(E1::try_unscribe("larem"), Some(E1::V12("larem".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("lore"), Some(E1::V12("lore".to_owned())));
|
assert_eq!(E1::try_unscribe("lore"), Some(E1::V12("lore".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("llorem"), Some(E1::V12("llorem".to_owned())));
|
assert_eq!(
|
||||||
assert_eq!(E1::try_unscribe("loremm"), Some(E1::V12("loremm".to_owned())));
|
E1::try_unscribe("llorem"),
|
||||||
|
Some(E1::V12("llorem".to_owned()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
E1::try_unscribe("loremm"),
|
||||||
|
Some(E1::V12("loremm".to_owned()))
|
||||||
|
);
|
||||||
assert_eq!(E1::try_unscribe("ipsum"), Some(E1::V9()));
|
assert_eq!(E1::try_unscribe("ipsum"), Some(E1::V9()));
|
||||||
assert_eq!(E1::try_unscribe("IPSUM"), Some(E1::V9()));
|
assert_eq!(E1::try_unscribe("IPSUM"), Some(E1::V9()));
|
||||||
assert_eq!(E1::try_unscribe("IpSuM"), Some(E1::V9()));
|
assert_eq!(E1::try_unscribe("IpSuM"), Some(E1::V9()));
|
||||||
assert_eq!(E1::try_unscribe("ipSUM"), Some(E1::V9()));
|
assert_eq!(E1::try_unscribe("ipSUM"), Some(E1::V9()));
|
||||||
assert_eq!(E1::try_unscribe("ipdum"), Some(E1::V12("ipdum".to_owned())));
|
assert_eq!(E1::try_unscribe("ipdum"), Some(E1::V12("ipdum".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("ipsu"), Some(E1::V12("ipsu".to_owned())));
|
assert_eq!(E1::try_unscribe("ipsu"), Some(E1::V12("ipsu".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("iipsum"), Some(E1::V12("iipsum".to_owned())));
|
assert_eq!(
|
||||||
assert_eq!(E1::try_unscribe("ipsumm"), Some(E1::V12("ipsumm".to_owned())));
|
E1::try_unscribe("iipsum"),
|
||||||
|
Some(E1::V12("iipsum".to_owned()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
E1::try_unscribe("ipsumm"),
|
||||||
|
Some(E1::V12("ipsumm".to_owned()))
|
||||||
|
);
|
||||||
assert_eq!(E1::try_unscribe("dolor"), Some(E1::V11 {}));
|
assert_eq!(E1::try_unscribe("dolor"), Some(E1::V11 {}));
|
||||||
assert_eq!(E1::try_unscribe("DOLOR"), Some(E1::V11 {}));
|
assert_eq!(E1::try_unscribe("DOLOR"), Some(E1::V11 {}));
|
||||||
assert_eq!(E1::try_unscribe("DoLoR"), Some(E1::V11 {}));
|
assert_eq!(E1::try_unscribe("DoLoR"), Some(E1::V11 {}));
|
||||||
assert_eq!(E1::try_unscribe("doLOR"), Some(E1::V11 {}));
|
assert_eq!(E1::try_unscribe("doLOR"), Some(E1::V11 {}));
|
||||||
assert_eq!(E1::try_unscribe("doler"), Some(E1::V12("doler".to_owned())));
|
assert_eq!(E1::try_unscribe("doler"), Some(E1::V12("doler".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("dolo"), Some(E1::V12("dolo".to_owned())));
|
assert_eq!(E1::try_unscribe("dolo"), Some(E1::V12("dolo".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("ddolor"), Some(E1::V12("ddolor".to_owned())));
|
assert_eq!(
|
||||||
assert_eq!(E1::try_unscribe("dolorr"), Some(E1::V12("dolorr".to_owned())));
|
E1::try_unscribe("ddolor"),
|
||||||
|
Some(E1::V12("ddolor".to_owned()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
E1::try_unscribe("dolorr"),
|
||||||
|
Some(E1::V12("dolorr".to_owned()))
|
||||||
|
);
|
||||||
assert_eq!(E1::try_unscribe(""), Some(E1::V12("".to_owned())));
|
assert_eq!(E1::try_unscribe(""), Some(E1::V12("".to_owned())));
|
||||||
assert_eq!(E1::try_unscribe("\0"), Some(E1::V12("\0".to_owned())));
|
assert_eq!(E1::try_unscribe("\0"), Some(E1::V12("\0".to_owned())));
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user