#flags #toggle #features #flipper

feattle-core

Featture toggles for Rust, extensible and with background synchronization and administration UI

14 releases (1 stable)

1.0.0 Jun 28, 2023
0.9.0 Jul 11, 2022
0.8.0 Mar 16, 2022
0.7.0 Sep 9, 2021
0.2.5 Oct 23, 2020

#778 in Configuration

Download history 182/week @ 2023-11-25 95/week @ 2023-12-02 296/week @ 2023-12-09 193/week @ 2023-12-16 83/week @ 2023-12-23 133/week @ 2023-12-30 246/week @ 2024-01-06 172/week @ 2024-01-13 23/week @ 2024-01-20 18/week @ 2024-01-27 238/week @ 2024-02-03 260/week @ 2024-02-10 331/week @ 2024-02-17 180/week @ 2024-02-24 102/week @ 2024-03-02 66/week @ 2024-03-09

722 downloads per month
Used in 3 crates

MIT/Apache

64KB
1K SLoC

feattle-core

Crates.io Docs.rs CI Coverage Status

This crate is the core implementation of the feature flags (called "feattles", for short).

Its main parts are the macro feattles! together with the trait Feattles. Please refer to the main package - feattle for more information.

Usage example

use feattle_core::{feattles, Feattles};
use feattle_core::persist::NoPersistence;

// Declare the struct
feattles! {
    struct MyFeattles {
        /// Is this usage considered cool?
        is_cool: bool = true,
        /// Limit the number of "blings" available.
        /// This will not change the number of "blengs", though!
        max_blings: i32,
        /// List the actions that should not be available
        blocked_actions: Vec<String>,
    }
}

// Create a new instance (`NoPersistence` is just a mock for the persistence layer)
let my_feattles = MyFeattles::new(NoPersistence);

// Read values (note the use of `*`)
assert_eq!(*my_feattles.is_cool(), true);
assert_eq!(*my_feattles.max_blings(), 0);
assert_eq!(*my_feattles.blocked_actions(), Vec::<String>::new());

How it works

The macro will generate a struct with the given name and visibility modifier (assuming private by default). The generated struct implements Feattles and also exposes one method for each feattle.

The methods created for each feattle allow reading their current value. For example, for a feattle is_cool: bool, there will be a method like pub fn is_cool(&self) -> MappedRwLockReadGuard<bool>. Note the use of parking_lot::MappedRwLockReadGuard because the interior of the struct is stored behind a RwLock to control concurrent access.

A feattle is created with the syntax $key: $type [= $default]. You can use doc coments ( starting with ///) to describe nicely what they do in your system. You can use any type that implements FeattleValue and optionally provide a default. If not provided, the default will be created with Default::default().

Updating values

This crate only disposes of low-level methods to load current feattles with [Feattles::reload()] and update their values with [Feattles::update()]. Please look for the crates feattle-sync and feattle-ui for higher-level functionalities.

Limitations

Due to some restrictions on how the macro is written, you can only use feattles! once per module. For example, the following does not compile:

use feattle_core::feattles;

feattles! { struct A { } }
feattles! { struct B { } }

You can work around this limitation by creating a sub-module and then re-exporting the generated struct. Note the use of pub struct in the second case.

use feattle_core::feattles;

feattles! { struct A { } }

mod b {
    use feattle_core::feattles;
    feattles! { pub struct B { } }
}

use b::B;

Optional features

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

See CONTRIBUTING.md.

Dependencies

~2.1–9.5MB
~66K SLoC