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
108
109
110
111
112
113
114
115
//! Easy HTTP configuration library.
//!
//! `choices` is a library that lets you expose your application's configuration
//! over HTTP with a simple struct!
//!
//! ## Examples
//!
//! Given the following code:
//!
//! ```no_run
//! use choices::Choices;
//! use lazy_static::lazy_static;
//! use std::sync::{Arc, Mutex};
//!
//! #[derive(Choices)]
//! struct Config {
//!     debug: bool,
//!     id: Option<i32>,
//!     log_file: String,
//! }
//!
//! lazy_static! {
//!     static ref CONFIG: Arc<Mutex<Config>> = {
//!         Arc::new(Mutex::new(Config {
//!             debug: false,
//!             id: Some(3),
//!             log_file: "log.txt".to_string()
//!         }))
//!     };
//! }
//!
//! #[tokio::main]
//! async fn main() {
//!     CONFIG.run((std::net::Ipv4Addr::LOCALHOST, 8081)).await;
//! }
//! ```
//!
//! You can see all configuration fields at `localhost:8081/config`
//! and the individual fields' values at `localhost:8081/config/<field name>`\
//! A field's value can be changed with a `PUT`, for instance
//! `curl -X PUT localhost:8081/config/debug -d "true"`.
//!
//! More examples on [github](https://github.com/Trisfald/choices/blob/master/examples/).
//!
//! ## Documentation
//! Check out the documentation on
//! [github](https://github.com/Trisfald/choices/blob/master/documentation.md).

#![forbid(unsafe_code)]
#![deny(missing_docs)]

#[doc(hidden)]
pub use choices_derive::*;

/// Re-export of `bytes`
pub mod bytes {
    pub use bytes::*;
}

/// Re-export of `warp`
pub mod warp {
    pub use warp::*;
}

#[cfg(feature = "json")]
/// Re-export of `serde_json`
pub mod serde_json {
    pub use serde_json::*;
}

#[doc(hidden)]
pub use async_trait::*;

pub mod error;
pub use crate::error::{ChoicesError, ChoicesResult};

pub mod serde;
pub use crate::serde::{ChoicesInput, ChoicesOutput};

use std::net::SocketAddr;
use std::sync::{Arc, Mutex, RwLock};

/// A trait to manage the http server responsible for the configuration.
#[self::async_trait]
pub trait Choices {
    /// Starts the configuration http server on the chosen address.
    async fn run<T: Into<SocketAddr> + Send>(&'static self, addr: T);

    #[doc(hidden)]
    async fn run_mutable<T: Into<SocketAddr> + Send>(_: Arc<Mutex<Self>>, _: T) {
        unimplemented!()
    }

    #[doc(hidden)]
    async fn run_mutable_rw<T: Into<SocketAddr> + Send>(_: Arc<RwLock<Self>>, _: T)
    where
        Self: Sync,
    {
        unimplemented!()
    }
}

#[self::async_trait]
impl<C: Choices + Send> Choices for Arc<Mutex<C>> {
    async fn run<T: Into<SocketAddr> + Send>(&'static self, addr: T) {
        C::run_mutable(self.clone(), addr).await;
    }
}

#[self::async_trait]
impl<C: Choices + Send + Sync> Choices for Arc<RwLock<C>> {
    async fn run<T: Into<SocketAddr> + Send>(&'static self, addr: T) {
        C::run_mutable_rw(self.clone(), addr).await;
    }
}