Kaynağa Gözat

Auto merge of #228 - rust-num:fix/num-macros, r=cuviper

Fix `num-macros` `FromPrimitive` implementation

Current solution follow syntax proposed in rust-lang/rfcs#1681.

Tracking issue rust-lang/rust#35900

Close #227

Code broken after change:

- [ ] https://github.com/kdar/gameboy-rs
- [ ] https://github.com/lemonrock/mbedtls
- [ ] https://github.com/timorantalaiho/kelaa
- [ ] https://github.com/dylanede/cef-rs
- [ ] https://github.com/klutzy/aheui-llvm
- [ ] https://github.com/pcwalton/rust-media
- [ ] https://github.com/PistonDevelopers/hematite_server
Homu 8 yıl önce
ebeveyn
işleme
019c136b8c

+ 1 - 0
.travis/test_nightly.sh

@@ -5,6 +5,7 @@ set -ex
 cargo bench --verbose
 
 cargo test --verbose --manifest-path=macros/Cargo.toml
+cargo test --verbose --manifest-path=derive/Cargo.toml
 
 # Build test for the serde feature
 cargo build --verbose --features "serde"

+ 27 - 0
derive/Cargo.toml

@@ -0,0 +1,27 @@
+[package]
+authors = ["The Rust Project Developers"]
+description = "Numeric syntax extensions"
+documentation = "http://rust-num.github.io/num"
+homepage = "https://github.com/rust-num/num"
+keywords = ["mathematics", "numerics"]
+license = "MIT/Apache-2.0"
+name = "num-derive"
+repository = "https://github.com/rust-num/num"
+version = "0.1.33"
+
+[dependencies]
+quote = "0.1.3"
+syn = "0.7.0"
+
+[dev-dependencies]
+compiletest_rs = "0.2.2"
+
+[dev-dependencies.num]
+path = ".."
+version = "0.1"
+
+[lib]
+crate-type = ["rustc-macro"]
+name = "num_derive"
+rustc-macro = true
+test = false

+ 76 - 0
derive/src/lib.rs

@@ -0,0 +1,76 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rustc-macro"]
+#![feature(rustc_macro, rustc_macro_lib)]
+
+extern crate syn;
+#[macro_use]
+extern crate quote;
+extern crate rustc_macro;
+
+use rustc_macro::TokenStream;
+
+use syn::Body::Enum;
+use syn::VariantData::Unit;
+
+#[rustc_macro_derive(FromPrimitive)]
+pub fn from_primitive(input: TokenStream) -> TokenStream {
+    let source = input.to_string();
+
+    let ast = syn::parse_macro_input(&source).unwrap();
+    let name = &ast.ident;
+
+    let variants = match ast.body {
+        Enum(ref variants) => variants,
+        _ => {
+            panic!("`FromPrimitive` can be applied only to the enums, {} is not an enum",
+                   name)
+        }
+    };
+
+    let mut idx = 0;
+    let variants: Vec<_> = variants.iter()
+        .map(|variant| {
+            let ident = &variant.ident;
+            match variant.data {
+                Unit => (),
+                _ => {
+                    panic!("`FromPrimitive` can be applied only to unitary enums, {}::{} is either struct or tuple", name, ident)
+                },
+            }
+            if let Some(val) = variant.discriminant {
+                idx = val.value;
+            }
+            let tt = quote!(#idx => Some(#name::#ident));
+            idx += 1;
+            tt
+        })
+        .collect();
+
+    let res = quote! {
+        #ast
+
+        impl ::num::traits::FromPrimitive for #name {
+            fn from_i64(n: i64) -> Option<Self> {
+                Self::from_u64(n as u64)
+            }
+
+            fn from_u64(n: u64) -> Option<Self> {
+                match n {
+                    #(variants,)*
+                    _ => None,
+                }
+            }
+        }
+    };
+
+    res.to_string().parse().unwrap()
+}

+ 25 - 0
derive/tests/compile-fail/derive_on_struct.rs

@@ -0,0 +1,25 @@
+
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_macro)]
+
+extern crate num;
+#[macro_use]
+extern crate num_derive;
+
+#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR
+struct Color {
+    r: u8,
+    g: u8,
+    b: u8,
+}
+
+fn main() {}

+ 24 - 0
derive/tests/compile-fail/enum_with_associated_data.rs

@@ -0,0 +1,24 @@
+
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_macro)]
+
+extern crate num;
+#[macro_use]
+extern crate num_derive;
+
+#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR
+enum Color {
+    Rgb(u8, u8, u8),
+    Hsv(u8, u8, u8),
+}
+
+fn main() {}

+ 25 - 0
derive/tests/compiletest.rs

@@ -0,0 +1,25 @@
+extern crate compiletest_rs as compiletest;
+
+use std::path::PathBuf;
+use std::env::var;
+
+fn run_mode(mode: &'static str) {
+    let mut config = compiletest::default_config();
+
+    let cfg_mode = mode.parse().ok().expect("Invalid mode");
+
+    config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
+    if let Ok(name) = var::<&str>("TESTNAME") {
+        let s : String = name.to_owned();
+        config.filter = Some(s)
+    }
+    config.mode = cfg_mode;
+    config.src_base = PathBuf::from(format!("tests/{}", mode));
+
+    compiletest::run_tests(&config);
+}
+
+#[test]
+fn compile_test() {
+    run_mode("compile-fail");
+}

+ 26 - 0
derive/tests/empty_enum.rs

@@ -0,0 +1,26 @@
+
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_macro)]
+
+extern crate num;
+#[macro_use]
+extern crate num_derive;
+
+#[derive(Debug, PartialEq, FromPrimitive)]
+enum Color {}
+
+#[test]
+fn test_empty_enum() {
+    let v: [Option<Color>; 1] = [num::FromPrimitive::from_u64(0)];
+
+    assert_eq!(v, [None]);
+}

+ 33 - 0
derive/tests/trivial.rs

@@ -0,0 +1,33 @@
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_macro)]
+
+extern crate num;
+#[macro_use]
+extern crate num_derive;
+
+#[derive(Debug, PartialEq, FromPrimitive)]
+enum Color {
+    Red,
+    Blue,
+    Green,
+}
+
+#[test]
+fn test_from_primitive_for_trivial_case() {
+    let v: [Option<Color>; 4] = [num::FromPrimitive::from_u64(0),
+                                 num::FromPrimitive::from_u64(1),
+                                 num::FromPrimitive::from_u64(2),
+                                 num::FromPrimitive::from_u64(3)];
+
+    assert_eq!(v,
+               [Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]);
+}

+ 33 - 0
derive/tests/with_custom_values.rs

@@ -0,0 +1,33 @@
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_macro)]
+
+extern crate num;
+#[macro_use]
+extern crate num_derive;
+
+#[derive(Debug, PartialEq, FromPrimitive)]
+enum Color {
+    Red,
+    Blue = 5,
+    Green,
+}
+
+#[test]
+fn test_from_primitive_for_enum_with_custom_value() {
+    let v: [Option<Color>; 4] = [num::FromPrimitive::from_u64(0),
+                                 num::FromPrimitive::from_u64(5),
+                                 num::FromPrimitive::from_u64(6),
+                                 num::FromPrimitive::from_u64(3)];
+
+    assert_eq!(v,
+               [Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]);
+}