Skip to content

Commit

Permalink
Add AsStaticRef trait and let derive(AsRefStr) implement it
Browse files Browse the repository at this point in the history
`#[derive(AsRefStr)]` will implement `AsStaticRef<str>`, and it
enables us to get `&'static str` by `AsStaticRef::<str>::as_static()`.

This will solve Peternator7#23.
  • Loading branch information
lo48576 committed May 23, 2018
1 parent e2ed13a commit 08986ae
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
10 changes: 10 additions & 0 deletions strum/src/lib.rs
Expand Up @@ -515,3 +515,13 @@ pub trait EnumProperty {
Option::None
}
}


/// A cheap reference-to-reference conversion. Used to convert a value to a
/// reference value with `'static` lifetime within generic code.
pub trait AsStaticRef<T>
where
T: ?Sized,
{
fn as_static(&self) -> &'static T;
}
12 changes: 11 additions & 1 deletion strum_macros/src/as_ref_str.rs
Expand Up @@ -48,12 +48,22 @@ pub fn as_ref_str_inner(ast: &syn::DeriveInput) -> quote::Tokens {
}

if arms.len() < variants.len() {
arms.push(quote!{ _ => panic!("AsRef<str>::as_ref() called on disabled variant.")})
arms.push(quote!{
_ => panic!("AsRef::<str>::as_ref() or AsStaticRef::<str>::as_static() \
called on disabled variant.")
})
}

let arms = &arms;
quote!{
impl #impl_generics ::std::convert::AsRef<str> for #name #ty_generics #where_clause {
fn as_ref(&self) -> &str {
::strum::AsStaticRef::as_static(self)
}
}

impl #impl_generics ::strum::AsStaticRef<str> for #name #ty_generics #where_clause {
fn as_static(&self) -> &'static str {
match *self {
#(#arms),*
}
Expand Down
6 changes: 6 additions & 0 deletions strum_tests/tests/as_ref_str.rs
Expand Up @@ -4,6 +4,8 @@ extern crate strum_macros;

use std::str::FromStr;

use strum::AsStaticRef;

#[derive(Debug,Eq,PartialEq,EnumString,AsRefStr)]
enum Color {
#[strum(to_string="RedRed")]
Expand All @@ -27,20 +29,24 @@ fn as_red_str() {
(Color::Red).as_ref());
assert_eq!(Color::Red,
Color::from_str((Color::Red).as_ref()).unwrap());
let _: &'static str = Color::Red.as_static();
}

#[test]
fn as_blue_str() {
assert_eq!("blue",
(Color::Blue { hue: 0 }).as_ref());
let _: &'static str = (Color::Blue { hue: 0 }).as_static();
}

#[test]
fn as_yellow_str() {
assert_eq!("yellow", (Color::Yellow).as_ref());
let _: &'static str = Color::Yellow.as_static();
}

#[test]
fn as_green_str() {
assert_eq!("Green", (Color::Green(String::default())).as_ref());
let _: &'static str = Color::Green(String::default()).as_static();
}

0 comments on commit 08986ae

Please sign in to comment.