1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! Featture toggles for Rust (called "feattles", for short), extensible and with background //! synchronization and administration UI. //! //! ## Example //! //! ```no_run //! use rusoto_s3::S3Client; //! use rusoto_core::Region; //! use feattle::*; //! use std::sync::Arc; //! //! /// A struct with your feature toggles: you can use primitive types (like `bool`, `i32`, etc), //! /// standard collections (like `Vec`, `BTreeSet`, etc) or any arbitrary type that implements //! /// the required trait. //! 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>, //! } //! } //! //! // Store their values and history in AWS' S3 //! let s3_client = S3Client::new(Region::default()); //! let persistence = S3::new(s3_client, "my-bucket".to_owned(), "some/s3/prefix/".to_owned()); //! //! // Create a new instance //! let my_feattles = Arc::new(MyFeattles::new(persistence)); //! //! // Poll the storage in the background //! BackgroundSync::new(&my_feattles).spawn(); //! //! // Start the admin UI with `warp` //! let admin_panel = Arc::new(AdminPanel::new(my_feattles.clone(), "Project Panda - DEV".to_owned())); //! tokio::spawn(run_warp_server(admin_panel, ([127, 0, 0, 1], 3030))); //! //! // 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()); //! ``` //! //! You can run a full example locally with: `cargo run --example full --features='s3 uuid warp'`. //! //! With this code, you'll get an Web Admin UI like: //! //! ![Home Web Admin UI](https://raw.githubusercontent.com/sitegui/feattle-rs/master/imgs/home.png) //! //! You can use the UI to edit the current values and see their change history. For example, this //! is what you can expect when editing an `enum`: //! //! ![Edit enum](https://raw.githubusercontent.com/sitegui/feattle-rs/master/imgs/edit_enum.png) //! //! It also supports complex types with a JSON editor and helpful error diagnostics: //! //! ![Edit JSON](https://raw.githubusercontent.com/sitegui/feattle-rs/master/imgs/edit_json.png) //! //! # 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()`. //! //! # Minimum supported Rust version //! //! As of this release, the MSRV is 1.45.0, as tested in the CI. A patch release will never require //! a newer MSRV. //! //! # Optional features //! //! You can easily declare feattles with your custom types, use another persistance storage logic //! or Web Framework (or any at all). For some out-of-the-box functionality, you can activate these //! cargo features: //! //! - **uuid**: will add support for [`uuid::Uuid`]. //! - **s3**: provides [`S3`] to integrate with AWS' S3 //! - **warp**: provides [`run_warp_server`] for a read-to-use integration with [`warp`] //! //! ## Crate's organization //! //! This crate is a simple re-export of these three components: //! //! * `feattle-core`: [![Crates.io](https://img.shields.io/crates/v/feattle-core.svg)](https://crates.io/crates/feattle-core) //! * `feattle-sync`: [![Crates.io](https://img.shields.io/crates/v/feattle-sync.svg)](https://crates.io/crates/feattle-sync) //! * `feattle-ui`: [![Crates.io](https://img.shields.io/crates/v/feattle-ui.svg)](https://crates.io/crates/feattle-ui) //! //! Having them separate allows for leaner lower-level integration. If you're creating a crate to //! provide a different storage or admin, you just need `feattle-core`. pub use feattle_core::*; pub use feattle_sync::*; pub use feattle_ui::*;