diff --git a/Cargo.toml b/Cargo.toml index 6f072e6..d87fe42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ keywords = ["enum", "open", "integer", "newtype"] include = ["/src", "/LICENSE", "Cargo.toml"] [features] +# This is not named libc because it would require "dep:libc" +# which doesn't work with trybuild: https://github.com/dtolnay/trybuild/issues/171. +libc_ = ["libc", "open-enum-derive/repr_c"] +std = ["open-enum-derive/repr_c"] # Needed to test #[deny(missing_docs)], which doesn't trigger in unit or integration tests. [[bin]] @@ -19,8 +23,7 @@ path = "src/test-lints.rs" [dependencies] open-enum-derive = { path = "derive", version = "0.2.0" } -# TODO: consider making this optional - I tried and trybuild started failing -libc = { version = "0.2" } +libc = { version = "0.2", optional = true } [dev-dependencies] trybuild = "1" diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 459a795..f0a5cd4 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -13,9 +13,10 @@ include = ["/src", "../LICENSE", "Cargo.toml"] proc-macro = true [features] +# Enable #[repr(C)] open enums +repr_c = [] [dependencies] syn = { version = "1", features = ["full"] } quote = "1" proc-macro2 = "1.0.43" -libc = { version = "0.2" } diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 6224e86..0840b3a 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -113,6 +113,7 @@ enum Repr { I64, Usize, Isize, + #[cfg(feature = "repr_c")] C, } @@ -157,6 +158,7 @@ impl Repr { Repr::I64 => "i64", Repr::Usize => "usize", Repr::Isize => "isize", + #[cfg(feature = "repr_c")] Repr::C => "C", } } @@ -167,6 +169,7 @@ impl ToTokens for Repr { tokens.extend([match self { // Technically speaking, #[repr(C)] on an enum isn't always `c_int`, // but those who care can fix it if they need. + #[cfg(feature = "repr_c")] Repr::C => quote!(::open_enum::__private::c_int), x => x.name().parse::().unwrap(), }]) @@ -187,7 +190,15 @@ impl Parse for Repr { "u64" => Repr::U64, "usize" => Repr::Usize, "isize" => Repr::Isize, + #[cfg(feature = "repr_c")] "C" => Repr::C, + #[cfg(not(feature = "repr_c"))] + "C" => { + return Err(Error::new( + ident.span(), + "#[repr(C)] requires either the `std` or `libc_` feature", + )) + } _ => { return Err(Error::new( ident.span(), diff --git a/src/lib.rs b/src/lib.rs index 77041a1..79a817c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,5 +199,12 @@ pub use open_enum_derive::open_enum; /// Utility items only to be used by macros. Do not expect API stability. #[doc(hidden)] pub mod __private { + #[cfg(all(feature = "libc", not(feature = "std")))] pub use libc::c_int; + + #[cfg(feature = "std")] + extern crate std; + + #[cfg(feature = "std")] + pub use std::os::raw::c_int; } diff --git a/tests/basic.rs b/tests/basic.rs index 22e3658..b82c6de 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -59,7 +59,6 @@ enum Color { Azure, } - #[test] fn values() { assert_eq!(Fruit::Apple.0, 0); @@ -114,6 +113,7 @@ fn other_derive() { HasHash(20).hash(&mut hasher); } +#[cfg(any(feature = "libc", feature = "std"))] #[test] fn repr_c() { use core::mem::size_of; @@ -121,12 +121,16 @@ fn repr_c() { #[repr(C)] #[open_enum] enum AnimalSound { - Moo, Honk, Bahhh, + Moo, + Honk, + Bahhh, } - use libc::c_int; assert_eq!(AnimalSound::Moo.0, 0); - assert_eq!(size_of::(), size_of::()); + assert_eq!( + size_of::(), + size_of::() + ); } #[test]