diff options
Diffstat (limited to 'third_party/rust/enum-primitive-derive')
-rw-r--r-- | third_party/rust/enum-primitive-derive/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/enum-primitive-derive/CHANGELOG.md | 33 | ||||
-rw-r--r-- | third_party/rust/enum-primitive-derive/Cargo.toml | 37 | ||||
-rw-r--r-- | third_party/rust/enum-primitive-derive/LICENSE | 20 | ||||
-rw-r--r-- | third_party/rust/enum-primitive-derive/README.md | 110 | ||||
-rw-r--r-- | third_party/rust/enum-primitive-derive/src/lib.rs | 278 |
6 files changed, 479 insertions, 0 deletions
diff --git a/third_party/rust/enum-primitive-derive/.cargo-checksum.json b/third_party/rust/enum-primitive-derive/.cargo-checksum.json new file mode 100644 index 0000000000..fda1620185 --- /dev/null +++ b/third_party/rust/enum-primitive-derive/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"75976e8cf25b724bd1db6d176d3bd98ad19554a2d64a57aaffa1b14c64a55f7a","Cargo.toml":"3d3e91b17cb7b10e130d8db6ebcfff05f37d799a8d5039d67aca802998501ae7","LICENSE":"819e0555b295079201b0670bb3302855303bdbbcc739f3819b13e1b3d2ec03bb","README.md":"a0d505b975f799d351e539720d26ed64f2022adcc8257d63c343c32a0c88f5de","src/lib.rs":"3751e744d351269d320cdc58e7fefd0f4bf657ed3a09b0fca68205696a1927c0"},"package":"c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e"}
\ No newline at end of file diff --git a/third_party/rust/enum-primitive-derive/CHANGELOG.md b/third_party/rust/enum-primitive-derive/CHANGELOG.md new file mode 100644 index 0000000000..33ad10c31e --- /dev/null +++ b/third_party/rust/enum-primitive-derive/CHANGELOG.md @@ -0,0 +1,33 @@ +# ChangeLog + +## 0.2.2 +### Changed +- Switch to using core instead of std for no-std support + +## 0.2.1 +### Added +- support TryFrom + +## 0.2.0 (yanked) +### Changed +- Upgrade [syn](https://crates.io/crates/syn) and [quote](https://crates.io/crates/quote) to 1.0 +- add a better diagnostic for the case where a discriminant isn't specified for + an enum +- Move unnecessary [`num-traits`](https://crates.io/crates/num-traits) dependency to `dev-dependencies` +- Migrate to Rust 2018 edition + +## 0.1.2 + +### Changed + +- drop `extern crate core;` as core is unused + +## 0.1.1 + +### Added + +- Support for more casts on discriminants + +## 0.1.0 + +Initial version diff --git a/third_party/rust/enum-primitive-derive/Cargo.toml b/third_party/rust/enum-primitive-derive/Cargo.toml new file mode 100644 index 0000000000..96a901e6cc --- /dev/null +++ b/third_party/rust/enum-primitive-derive/Cargo.toml @@ -0,0 +1,37 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "enum-primitive-derive" +version = "0.2.2" +authors = ["Doug Goldstein <cardoe@cardoe.com>"] +description = "enum_primitive implementation using procedural macros to have a custom derive" +homepage = "https://gitlab.com/cardoe/enum-primitive-derive" +readme = "README.md" +keywords = ["derive", "enum", "fromprimitive", "primitive", "ffi"] +categories = ["rust-patterns"] +license = "MIT" +repository = "https://gitlab.com/cardoe/enum-primitive-derive.git" + +[lib] +proc-macro = true +[dependencies.num-traits] +version = "0.2" +default-features = false + +[dependencies.quote] +version = "1" + +[dependencies.syn] +version = "1" +[badges.gitlab] +repository = "cardoe/enum-primitive-derive" diff --git a/third_party/rust/enum-primitive-derive/LICENSE b/third_party/rust/enum-primitive-derive/LICENSE new file mode 100644 index 0000000000..94486be7da --- /dev/null +++ b/third_party/rust/enum-primitive-derive/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017 Doug Goldstein <cardoe@cardoe.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +“Software”), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/enum-primitive-derive/README.md b/third_party/rust/enum-primitive-derive/README.md new file mode 100644 index 0000000000..795af9f501 --- /dev/null +++ b/third_party/rust/enum-primitive-derive/README.md @@ -0,0 +1,110 @@ +[![Build status](https://gitlab.com/cardoe/enum-primitive-derive/badges/master/pipeline.svg)](https://gitlab.com/cardoe/enum-primitive-derive/commits/master) +[![Rust version]( https://img.shields.io/badge/rust-1.34+-blue.svg)]() +[![Documentation](https://docs.rs/enum-primitive-derive/badge.svg)](https://docs.rs/enum-primitive-derive) +[![Latest version](https://img.shields.io/crates/v/enum-primitive-derive.svg)](https://crates.io/crates/enum-primitive-derive) +[![All downloads](https://img.shields.io/crates/d/enum-primitive-derive.svg)](https://crates.io/crates/enum-primitive-derive) +[![Downloads of latest version](https://img.shields.io/crates/dv/enum-primitive-derive.svg)](https://crates.io/crates/enum-primitive-derive) + +This is a custom derive, using procedural macros, implementation of +[enum_primitive](https://crates.io/crates/enum_primitive). + +MSRV is 1.34.0 + +## Documentation + +[https://docs.rs/enum-primitive-derive/](https://docs.rs/enum-primitive-derive/) + +## Usage + +Add the following to `Cargo.toml`: + +``` +[dependencies] +enum-primitive-derive = "^0.1" +num-traits = "^0.1" +``` + +Then to your code add: + +```rust +#[macro_use] +extern crate enum_primitive_derive; +extern crate num_traits; + +#[derive(Primitive)] +enum Variant { + Value = 1, + Another = 2, +} +``` + +To be really useful you need `use num_traits::FromPrimitive` or +`use num_traits::ToPrimitive` or both. You will then be able to +use +[num_traits::FromPrimitive](https://rust-num.github.io/num/num/trait.FromPrimitive.html) +and/or +[num_traits::ToPrimitive](https://rust-num.github.io/num/num/trait.ToPrimitive.html) +on your enum. + +## Full Example + +```rust +#[macro_use] +extern crate enum_primitive_derive; +extern crate num_traits; + +use num_traits::{FromPrimitive, ToPrimitive}; + +#[derive(Primitive)] +enum Foo { + Bar = 32, + Dead = 42, + Beef = 50, +} + +fn main() { + assert_eq!(Foo::from_i32(32), Some(Foo::Bar)); + assert_eq!(Foo::from_i32(42), Some(Foo::Dead)); + assert_eq!(Foo::from_i64(50), Some(Foo::Beef)); + assert_eq!(Foo::from_isize(17), None); + + let bar = Foo::Bar; + assert_eq!(bar.to_i32(), Some(32)); + + let dead = Foo::Dead; + assert_eq!(dead.to_isize(), Some(42)); +} +``` + +# Complex Example + +In this case we attempt to use values created by +[bindgen](https://crates.io/crates/bindgen). + +```rust +#[macro_use] +extern crate enum_primitive_derive; +extern crate num_traits; + +use num_traits::{FromPrimitive, ToPrimitive}; + +pub const ABC: ::std::os::raw::c_uint = 1; +pub const DEF: ::std::os::raw::c_uint = 2; +pub const GHI: ::std::os::raw::c_uint = 4; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Primitive)] +enum BindGenLike { + ABC = ABC as isize, + DEF = DEF as isize, + GHI = GHI as isize, +} + +fn main() { + assert_eq!(BindGenLike::from_isize(4), Some(BindGenLike::GHI)); + assert_eq!(BindGenLike::from_u32(2), Some(BindGenLike::DEF)); + assert_eq!(BindGenLike::from_u32(8), None); + + let abc = BindGenLike::ABC; + assert_eq!(abc.to_u32(), Some(1)); +} +``` diff --git a/third_party/rust/enum-primitive-derive/src/lib.rs b/third_party/rust/enum-primitive-derive/src/lib.rs new file mode 100644 index 0000000000..135f6164c7 --- /dev/null +++ b/third_party/rust/enum-primitive-derive/src/lib.rs @@ -0,0 +1,278 @@ +// Copyright (c) 2017 Doug Goldstein <cardoe@cardoe.com> + +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// “Software”), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: + +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +//! This crate provides a custom derive `Primitive` that helps people +//! providing native Rust bindings to C code by allowing a C-like `enum` +//! declaration to convert to its primitve values and back from them. You +//! can selectively include `num_traits::ToPrimitive` and +//! `num_traits::FromPrimitive` to get these features. +//! +//! # Example +//! +//! ```rust +//! use enum_primitive_derive::Primitive; +//! use num_traits::{FromPrimitive, ToPrimitive}; +//! +//! #[derive(Debug, Eq, PartialEq, Primitive)] +//! enum Foo { +//! Bar = 32, +//! Dead = 42, +//! Beef = 50, +//! } +//! +//! fn main() { +//! assert_eq!(Foo::from_i32(32), Some(Foo::Bar)); +//! assert_eq!(Foo::from_i32(42), Some(Foo::Dead)); +//! assert_eq!(Foo::from_i64(50), Some(Foo::Beef)); +//! assert_eq!(Foo::from_isize(17), None); +//! +//! let bar = Foo::Bar; +//! assert_eq!(bar.to_i32(), Some(32)); +//! +//! let dead = Foo::Dead; +//! assert_eq!(dead.to_isize(), Some(42)); +//! } +//! ``` +//! +//! # Complex Example +//! +//! ```rust +//! use enum_primitive_derive::Primitive; +//! use num_traits::{FromPrimitive, ToPrimitive}; +//! +//! pub const ABC: ::std::os::raw::c_uint = 1; +//! pub const DEF: ::std::os::raw::c_uint = 2; +//! pub const GHI: ::std::os::raw::c_uint = 4; +//! +//! #[derive(Clone, Copy, Debug, Eq, PartialEq, Primitive)] +//! enum BindGenLike { +//! ABC = ABC as isize, +//! DEF = DEF as isize, +//! GHI = GHI as isize, +//! } +//! +//! fn main() { +//! assert_eq!(BindGenLike::from_isize(4), Some(BindGenLike::GHI)); +//! assert_eq!(BindGenLike::from_u32(2), Some(BindGenLike::DEF)); +//! assert_eq!(BindGenLike::from_u32(8), None); +//! +//! let abc = BindGenLike::ABC; +//! assert_eq!(abc.to_u32(), Some(1)); +//! } +//! ``` +//! +//! # TryFrom Example +//! +//! ```rust +//! use enum_primitive_derive::Primitive; +//! use core::convert::TryFrom; +//! +//! #[derive(Debug, Eq, PartialEq, Primitive)] +//! enum Foo { +//! Bar = 32, +//! Dead = 42, +//! Beef = 50, +//! } +//! +//! fn main() { +//! let bar = Foo::try_from(32); +//! assert_eq!(bar, Ok(Foo::Bar)); +//! +//! let dead = Foo::try_from(42); +//! assert_eq!(dead, Ok(Foo::Dead)); +//! +//! let unknown = Foo::try_from(12); +//! assert!(unknown.is_err()); +//! } +//! ``` + +extern crate proc_macro; + +use proc_macro::TokenStream; + +/// Provides implementation of `num_traits::ToPrimitive` and +/// `num_traits::FromPrimitive` +#[proc_macro_derive(Primitive)] +pub fn primitive(input: TokenStream) -> TokenStream { + let ast = syn::parse_macro_input!(input as syn::DeriveInput); + impl_primitive(&ast) +} + +fn impl_primitive(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + + // Check if derive(Primitive) was specified for a struct + if let syn::Data::Enum(ref variant) = ast.data { + let (var_u64, dis_u64): (Vec<_>, Vec<_>) = variant + .variants + .iter() + .map(|v| { + match v.fields { + syn::Fields::Unit => (), + _ => panic!("#[derive(Primitive) can only operate on C-like enums"), + } + if v.discriminant.is_none() { + panic!( + "#[derive(Primitive) requires C-like enums with \ + discriminants for all enum variants" + ); + } + + let discrim = match v.discriminant.clone().map(|(_eq, expr)| expr).unwrap() { + syn::Expr::Cast(real) => *real.expr, + orig => orig, + }; + (v.ident.clone(), discrim) + }) + .unzip(); + + // quote!{} needs this to be a vec since its in #( )* + let enum_u64 = vec![name.clone(); variant.variants.len()]; + + // can't reuse variables in quote!{} body + let var_i64 = var_u64.clone(); + let dis_i64 = dis_u64.clone(); + let enum_i64 = enum_u64.clone(); + + let to_name = name.clone(); + let to_enum_u64 = enum_u64.clone(); + let to_var_u64 = var_u64.clone(); + let to_dis_u64 = dis_u64.clone(); + + let to_enum_i64 = enum_u64.clone(); + let to_var_i64 = var_u64.clone(); + let to_dis_i64 = dis_u64.clone(); + + TokenStream::from(quote::quote! { + impl ::num_traits::FromPrimitive for #name { + fn from_u64(val: u64) -> Option<Self> { + match val as _ { + #( #dis_u64 => Some(#enum_u64::#var_u64), )* + _ => None, + } + } + + fn from_i64(val: i64) -> Option<Self> { + match val as _ { + #( #dis_i64 => Some(#enum_i64::#var_i64), )* + _ => None, + } + } + } + + impl ::num_traits::ToPrimitive for #to_name { + fn to_u64(&self) -> Option<u64> { + match *self { + #( #to_enum_u64::#to_var_u64 => Some(#to_dis_u64 as u64), )* + } + } + + fn to_i64(&self) -> Option<i64> { + match *self { + #( #to_enum_i64::#to_var_i64 => Some(#to_dis_i64 as i64), )* + } + } + } + + impl ::core::convert::TryFrom<u64> for #to_name { + type Error = &'static str; + + fn try_from(value: u64) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_u64(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<u32> for #to_name { + type Error = &'static str; + + fn try_from(value: u32) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_u32(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<u16> for #to_name { + type Error = &'static str; + + fn try_from(value: u16) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_u16(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<u8> for #to_name { + type Error = &'static str; + + fn try_from(value: u8) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_u8(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<i64> for #name { + type Error = &'static str; + + fn try_from(value: i64) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_i64(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<i32> for #name { + type Error = &'static str; + + fn try_from(value: i32) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_i32(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<i16> for #name { + type Error = &'static str; + + fn try_from(value: i16) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_i16(value).ok_or_else(|| "Unknown variant") + } + } + + impl ::core::convert::TryFrom<i8> for #name { + type Error = &'static str; + + fn try_from(value: i8) -> ::core::result::Result<Self, Self::Error> { + use ::num_traits::FromPrimitive; + + #to_name::from_i8(value).ok_or_else(|| "Unknown variant") + } + } + }) + } else { + panic!("#[derive(Primitive)] is only valid for C-like enums"); + } +} |