From 3c1f14c2e926493b673d78bde06d9ff6eb9772f4 Mon Sep 17 00:00:00 2001 From: YOSHIOKA Takuma Date: Wed, 23 May 2018 16:13:39 +0900 Subject: [PATCH] Add `AsStaticRef` trait and let `derive(AsRefStr)` implement it `#[derive(AsStaticStr)]` will implement `AsStaticRef`, and it enables us to get `&'static str` by `AsStaticRef::::as_static()`. This will solve #23. --- strum/src/lib.rs | 10 ++++++++++ strum_macros/src/as_ref_str.rs | 11 ++++++++++- strum_tests/tests/as_ref_str.rs | 6 ++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/strum/src/lib.rs b/strum/src/lib.rs index 8aba4a03..15061b3e 100644 --- a/strum/src/lib.rs +++ b/strum/src/lib.rs @@ -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 +where + T: ?Sized, +{ + fn as_static(&self) -> &'static T; +} diff --git a/strum_macros/src/as_ref_str.rs b/strum_macros/src/as_ref_str.rs index f355956f..1f8a9bd2 100644 --- a/strum_macros/src/as_ref_str.rs +++ b/strum_macros/src/as_ref_str.rs @@ -48,12 +48,21 @@ pub fn as_ref_str_inner(ast: &syn::DeriveInput) -> quote::Tokens { } if arms.len() < variants.len() { - arms.push(quote!{ _ => panic!("AsRef::as_ref() called on disabled variant.")}) + arms.push(quote!{ + _ => panic!("AsRef::as_ref() or AsStaticStr::as_str() called on disabled variant.") + }) } + let arms = &arms; quote!{ impl #impl_generics ::std::convert::AsRef for #name #ty_generics #where_clause { fn as_ref(&self) -> &str { + ::strum::AsStaticRef::as_static(self) + } + } + + impl #impl_generics ::strum::AsStaticRef for #name #ty_generics #where_clause { + fn as_static(&self) -> &'static str { match *self { #(#arms),* } diff --git a/strum_tests/tests/as_ref_str.rs b/strum_tests/tests/as_ref_str.rs index a7a54cf7..5d6965d0 100644 --- a/strum_tests/tests/as_ref_str.rs +++ b/strum_tests/tests/as_ref_str.rs @@ -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")] @@ -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(); }