Skip to content

Commit

Permalink
Did a little bit of refactoring and added some docs around AsStaticStr (
Browse files Browse the repository at this point in the history
#28)

* Did a little bit of refactoring and added some docs around AsStaticStr

* Revving the version in the cargoo.toml

* Managing Cargo.toml is a bit tedious when deploying packages that depend on each other

* Updated Cargo.toml
  • Loading branch information
Peternator7 committed Jun 26, 2018
1 parent c91854c commit b6e4e66
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 30 deletions.
33 changes: 31 additions & 2 deletions README.md
Expand Up @@ -14,8 +14,8 @@ Cargo.toml. Strum_macros contains the macros needed to derive all the traits in

```toml
[dependencies]
strum = "0.9.0"
strum_macros = "0.9.0"
strum = "0.10.0"
strum_macros = "0.10.0"
```

And add these lines to the root of your project, either lib.rs or main.rs.
Expand Down Expand Up @@ -135,6 +135,35 @@ Strum has implemented the following macros:
`ToString` for determining what string is returned. The difference is that `as_ref()` returns
a `&str` instead of a `String` so you don't allocate any additional memory with each call.

4. `AsStaticStr`: this is similar to `AsRefStr`, but returns a `'static` reference to a string which is helpful
in some scenarios. This macro implements `strum::AsStaticRef<str>` which adds a method `.to_static()` that
returns a `&'static str`.

```rust
extern crate strum;
#[macro_use] extern crate strum_macros;

use strum::AsStaticRef;

#[derive(AsStaticStr)]
enum State<'a> {
Initial(&'a str),
Finished
}

fn print_state<'a>(s:&'a str) {
let state = State::Initial(s);
// The following won't work because the lifetime is incorrect so we can use.as_static() instead.
// let wrong: &'static str = state.as_ref();
let right: &'static str = state.as_static();
println!("{}", right);
}

fn main() {
print_state(&"hello world".to_string())
}
```

4. `EnumIter`: iterate over the variants of an Enum. Any additional data on your variants will be
set to `Default::default()`. The macro implements `strum::IntoEnumIter` on your enum and
creates a new type called `YourEnumIter` that is the iterator object. You cannot derive
Expand Down
5 changes: 2 additions & 3 deletions strum/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "strum"
version = "0.9.0"
version = "0.10.0"
authors = ["Peter Glotfelty <peglotfe@microsoft.com>"]
license = "MIT"

Expand All @@ -13,9 +13,8 @@ homepage = "https://github.com/Peternator7/strum"
readme = "../README.md"

[dev-dependencies]
strum_macros = "0.9.0"
strum_macros = "0.10.0"
# strum_macros = { path = "../strum_macros" }


[badges]
travis-ci = { repository = "Peternator7/strum" }
30 changes: 29 additions & 1 deletion strum/src/lib.rs
Expand Up @@ -121,8 +121,36 @@
//!
//! 3. `AsRefStr`: this derive implements `AsRef<str>` on your enum using the same rules as
//! `ToString` for determining what string is returned. The difference is that `as_ref()` returns
//! a `&str` instead of a `String` so you don't allocate any additional memory with each call.
//! a borrowed `str` instead of a `String` so you can save an allocation.
//!
//! 4. `AsStaticStr`: this is similar to `AsRefStr`, but returns a `'static` reference to a string which is helpful
//! in some scenarios. This macro implements `strum::AsStaticRef<str>` which adds a method `.as_static()` that
//! returns a `&'static str`.
//!
//! ```rust
//! # extern crate strum;
//! # #[macro_use] extern crate strum_macros;
//! use strum::AsStaticRef;
//!
//! #[derive(AsStaticStr)]
//! enum State<'a> {
//! Initial(&'a str),
//! Finished
//! }
//!
//! fn print_state<'a>(s:&'a str) {
//! let state = State::Initial(s);
//! // The following won't work because the lifetime is incorrect so we can use.as_static() instead.
//! // let wrong: &'static str = state.as_ref();
//! let right: &'static str = state.as_static();
//! println!("{}", right);
//! }
//!
//! fn main() {
//! print_state(&"hello world".to_string())
//! }
//! ```
//!
//! 4. `EnumIter`: iterate over the variants of an Enum. Any additional data on your variants will be
//! set to `Default::default()`. The macro implements `strum::IntoEnumIter` on your enum and
//! creates a new type called `YourEnumIter` that implements both `Iterator` and `ExactSizeIterator`.
Expand Down
2 changes: 1 addition & 1 deletion strum_macros/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "strum_macros"
version = "0.9.0"
version = "0.10.0"
authors = ["Peter Glotfelty <peglotfe@microsoft.com>"]
license = "MIT"

Expand Down
26 changes: 20 additions & 6 deletions strum_macros/src/as_ref_str.rs
Expand Up @@ -3,15 +3,14 @@ use syn;

use helpers::{unique_attr, extract_attrs, extract_meta, is_disabled};

pub fn as_ref_str_inner(ast: &syn::DeriveInput) -> TokenStream {
fn get_arms(ast: &syn::DeriveInput) -> Vec<TokenStream> {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let mut arms = Vec::new();
let variants = match ast.data {
syn::Data::Enum(ref v) => &v.variants,
_ => panic!("AsRefStr only works on Enums"),
_ => panic!("This macro only works on Enums"),
};

let mut arms = Vec::new();
for variant in variants {
use syn::Fields::*;
let ident = &variant.ident;
Expand Down Expand Up @@ -53,14 +52,29 @@ pub fn as_ref_str_inner(ast: &syn::DeriveInput) -> TokenStream {
})
}

let arms = &arms;
arms
}

pub fn as_ref_str_inner(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let arms = get_arms(ast);
quote!{
impl #impl_generics ::std::convert::AsRef<str> for #name #ty_generics #where_clause {
fn as_ref(&self) -> &str {
::strum::AsStaticRef::as_static(self)
match *self {
#(#arms),*
}
}
}
}
}

pub fn as_static_str_inner(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let arms = get_arms(ast);
quote!{
impl #impl_generics ::strum::AsStaticRef<str> for #name #ty_generics #where_clause {
fn as_static(&self) -> &'static str {
match *self {
Expand Down
9 changes: 9 additions & 0 deletions strum_macros/src/lib.rs
Expand Up @@ -58,6 +58,15 @@ pub fn as_ref_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[proc_macro_derive(AsStaticStr,attributes(strum))]
pub fn as_static_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

let toks = as_ref_str::as_static_str_inner(&ast);
debug_print_generated(&ast, &toks);
toks.into()
}

#[proc_macro_derive(ToString,attributes(strum))]
pub fn to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion strum_tests/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "strum_tests"
version = "0.9.0"
version = "0.9.1"
authors = ["Peter Glotfelty <peglotfe@microsoft.com>"]

[dependencies]
Expand Down
34 changes: 34 additions & 0 deletions strum_tests/tests/as_ref_no_strum.rs
@@ -0,0 +1,34 @@
#[macro_use]
extern crate strum_macros;

#[derive(Debug,Eq,PartialEq,AsRefStr)]
enum Color {
#[strum(to_string="RedRed")]
Red,
#[strum(serialize="b", to_string="blue")]
Blue { hue: usize },
#[strum(serialize="y", serialize="yellow")]
Yellow,
#[strum(default="true")]
Green(String),
}

#[test]
fn as_red_str() {
assert_eq!("RedRed", (Color::Red).as_ref());
}

#[test]
fn as_blue_str() {
assert_eq!("blue", (Color::Blue { hue: 0 }).as_ref());
}

#[test]
fn as_yellow_str() {
assert_eq!("yellow", (Color::Yellow).as_ref());
}

#[test]
fn as_green_str() {
assert_eq!("Green", (Color::Green(String::default())).as_ref());
}
22 changes: 6 additions & 16 deletions strum_tests/tests/as_ref_str.rs
Expand Up @@ -3,10 +3,9 @@ extern crate strum;
extern crate strum_macros;

use std::str::FromStr;

use strum::AsStaticRef;

#[derive(Debug,Eq,PartialEq,EnumString,AsRefStr)]
#[derive(Debug,Eq,PartialEq,EnumString,AsRefStr,AsStaticStr)]
enum Color {
#[strum(to_string="RedRed")]
Red,
Expand All @@ -18,35 +17,26 @@ enum Color {
Green(String),
}

#[test]
fn color_simple() {
assert_eq!(Color::Red, Color::from_str("RedRed").unwrap());
}

#[test]
fn as_red_str() {
assert_eq!("RedRed",
(Color::Red).as_ref());
assert_eq!(Color::Red,
Color::from_str((Color::Red).as_ref()).unwrap());
let _: &'static str = Color::Red.as_static();
assert_eq!("RedRed", (Color::Red).as_ref());
assert_eq!(Color::Red, Color::from_str((Color::Red).as_ref()).unwrap());
}

#[test]
fn as_blue_str() {
assert_eq!("blue",
(Color::Blue { hue: 0 }).as_ref());
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();
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();
let _: &'static str = (Color::Green(String::default())).as_static();
}

0 comments on commit b6e4e66

Please sign in to comment.