# Features

[![Crate version](https://img.shields.io/crates/v/features.svg)][crate]
[![Crate downloads](https://img.shields.io/crates/d/features.svg)][crate]
[![Crate license](https://img.shields.io/crates/l/features.svg)][github]
[![Documentation](https://img.shields.io/badge/documentation-docs.rs-df3600.svg?style=flat-square)][docs]

[![AppVeyor](https://img.shields.io/appveyor/ci/fnichol/features-rs.svg)][build-windows] <sup>(Windows)</sup>
[![Travis](https://img.shields.io/travis/fnichol/features-rs.svg)][build-unix] <sup>(Linux and OS X)</sup>

[build-unix]: https://travis-ci.org/fnichol/features-rs
[build-windows]: https://ci.appveyor.com/project/fnichol/features-rs
[crate]: https://crates.io/crates/features
[docs]: https://docs.rs/features
[github]: https://github.com/fnichol/features-rs
[lic-apachev2]: https://github.com/fnichol/features-rs/blob/master/LICENSE-APACHE
[lic-mit]: https://github.com/fnichol/features-rs/blob/master/LICENSE-MIT

## About

`features` is a small library that implements runtime [feature toggles][fowler_toggles] for
your library or program allowing behavior to be changed on boot or dynamically at runtime using
the same compiled binary artifact. This is different from cargo's [feature][cargo_feature]
support which uses conditional compilation.

At its core, it is a macro (`features!`) that takes a collection of feature flag names which it
uses to generate a module containing a function to enable a feature toggle (`::enable()`), a
function to disable a feature toggle (`::disable()`) and a function to check if a feature
toggle is enabled (`::is_enabled()`).

[fowler_toggles]: https://martinfowler.com/articles/feature-toggles.html
[cargo_feature]: http://doc.crates.io/manifest.html#the-features-section

## Example

Basic example:

```rust
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate features;

features! {
    pub mod feature {
        const Alpha = 0b00000001,
        const Beta = 0b00000010
    }
}

fn main() {
    assert_eq!(false, feature::is_enabled(feature::Alpha));
    assert_eq!(false, feature::is_enabled(feature::Beta));

    feature::enable(feature::Beta);
    assert_eq!(false, feature::is_enabled(feature::Alpha));
    assert_eq!(true, feature::is_enabled(feature::Beta));
}
```

Multiple feature sets:

```rust
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate features;

features! {
    pub mod ux {
        const JsonOutput = 0b10000000,
        const VerboseOutput = 0b01000000
    }
}

features! {
    pub mod srv {
        const Http2Downloading = 0b10000000,
        const BitTorrentDownloading = 0b01000000
    }
}

fn main() {
    // Parse CLI args, environment, read config file etc...
    srv::enable(srv::BitTorrentDownloading);
    ux::enable(ux::JsonOutput);

    if srv::is_enabled(srv::Http2Downloading) {
        println!("Downloading via http2...");
    } else if srv::is_enabled(srv::BitTorrentDownloading) {
        println!("Downloading via bit torrent...");
    } else {
        println!("Downloading the old fashioned way...");
    }

    if ux::is_enabled(ux::VerboseOutput) {
        println!("COOL");
    }
}
```

## Feature Toggle References

Here are some articles and projects which insipred the implementation of `features`:

* [Feature Toggles](https://martinfowler.com/articles/feature-toggles.html) (Martin Fowler's
blog)
* [Using Feature Flags to Ship Changes with
Confidence](https://blog.travis-ci.com/2014-03-04-use-feature-flags-to-ship-changes-with-confidence/)
(TravisCI's blog)
* [Feature Toggles are one of the worst kinds of Technical
Debt](http://swreflections.blogspot.ca/2014/08/feature-toggles-are-one-of-worst-kinds.html)
(excellent cautionary tale and warning)
* [Feature toggle](https://en.wikipedia.org/wiki/Feature_toggle) (Wikipedia article)
* [Ruby feature gem](https://github.com/mgsnova/feature) (nice prior art)

## License

Features is licensed under the Apache License, Version 2.0 and the MIT license. Please read the [LICENSE-APACHE] and [LICENSE-MIT] for details

[LICENSE-APACHE]: https://github.com/fnichol/features-rs/blob/master/LICENSE-MIT
[LICENSE-MIT]: https://github.com/fnichol/features-rs/blob/master/MIT-MIT
