Crates.io | is_not |
lib.rs | is_not |
version | 0.1.0 |
source | src |
created_at | 2020-10-27 22:44:09.587251 |
updated_at | 2020-10-27 22:44:09.587251 |
description | A procedural macro much like #[cfg(...)] that can be re-exported from a library based on enabled features |
homepage | |
repository | https://github.com/tylerhawkes/is_not |
max_upload_size | |
id | 306134 |
size | 16,201 |
This crate exports two very simple attribute macros. is
returns the token stream as is and not
returns an empty token stream.
These are very similar to the #[cfg(...)]
attributes, but they can be exported from a crate for things that need to be enabled if
a dependency has certain features enabled. It additionally has the advantage that it also type checks. If you mis-spell something
inside of #[cfg(mis-spelled)]
it will always be disabled, where these attributes must exist in the namespace.
For example, let's say you want to allow different algorithms or implementations inside of a library that can be turned on and off and add expensive compile times due to dependencies or will be in the hot path of an application's main loop.
// algo crate
// This crate ensures that at least one of foo and bar is active using a build script or more fancy cfg attributes.
#[cfg(feature = "foo")]
pub use is_not::{is as is_foo, not as not_foo};
#[cfg(not(feature = "foo"))]
pub use is_not::{not as is_foo, is as not_foo};
#[cfg(feature = "bar")]
pub use is_not::{is as is_bar, not as not_bar};
#[cfg(not(feature = "bar"))]
pub use is_not::{not as is_bar, is as not_bar};
#[cfg(feature = "foo")]
mod foo {
fn foo(a: Foo) -> i32 {
// algorithm
}
struct Foo {
// fields
}
}
#[cfg(feature = "foo")]
mod bar {
fn bar(a: Bar) -> i32 {
// algorithm
}
struct Bar {
// fields
}
}
// app crate
// both of these functions will exist, though compile time flags given to the algo crate will change how they are compiled in the app crate.
// You can ensure that at least one is turned on
#[not_foo]
#[not_bar]
compile_error!("Either foo or bar or both should be enabled in algo crate");
#[is_foo]
fn call_foo() -> i32 {
algo::foo::foo(algo::foo::Foo{})
}
#[not_foo]
fn call_foo() -> i32 {
call_bar()
}
#[is_bar]
fn call_bar() -> i32 {
algo::bar::bar(algo::bar::Bar{})
}
#[not_bar]
fn call_bar() -> i32 {
call_foo()
}
fn call_algo() -> i32 {
if crate::use_foo() {
call_foo()
} else {
call_bar()
}
}