kosei 0.1.3

A easy-to-use configuration crate with the Rust programming language.
Documentation
<h1 align="center">Kōsei</h1>

<p align="center"><code>こうせい</code></p>
<p align="center">A easy-to-use configuration crate with the Rust programming language.</p>

## Features

- **Supports**:
    - `toml`, `yaml`, `json` configuration type.
    - [Apollo config]https://github.com/apolloconfig/apollo
    - [Nacos]https://nacos.io/zh-cn/

- **Dynamic configuration**
    - hot reload
    - support from local file, [Apollo config]https://github.com/apolloconfig/apollo, [Nacos]https://nacos.io/zh-cn/

[![Crates.io][crates-badge]][crates-url]
[![Crates.io][crates-download]][crates-url]

[crates-badge]: https://flat.badgen.net/crates/v/kosei

[crates-download]: https://flat.badgen.net/crates/d/kosei

[crates-url]: https://crates.io/crates/kosei

## Import

- Default with dynamic file configuration

```toml
[dependencies]
kosei = { version = "0.1" }
```

- Enable Apollo feature

```toml
[dependencies]
kosei = { version = "0.1", features = ["apollo"] }
```

- Enable Nacos feature

```toml
[dependencies]
kosei = { version = "0.1", features = ["nacos"] }
```

## Quickstart

> See [`examples`]examples for further use.

Config Entry

```rust
// `Deserialize` and `Clone` traits should be applied
#[derive(Clone, Debug, Deserialize)]
struct Entry {
    ...
}
```

- **Base file config**

```rust
#[test]
fn base_test() {
    // Panic if no such file `config/config.yaml`
    let config: Config<Entry> = Config::from_file("config/config.yaml");
    let entry: &Entry = config.as_inner(); // borrowed value has the same lifetimes as config
    let entry: Entry = config.to_inner();  // clone a new Entry
    let entry: Entry = config.into_inner(); // take ownership
}
```

- **Dynamic file config**

```rust
#[tokio::test]
async fn dynamic_test() {
    // Create a dynamic config and a watcher
    let (config, mut watcher) = DynamicConfig::<Entry>::watch_file("config/config.yaml");
    // Listen to file modify event
    watcher.watch().unwrap();
    let lock = config.lock();
    let entry: &Entry = lock.as_inner();  // borrow Entry
    let entry: Entry = lock.to_inner();  // clone a new Entry
    // let entry: Entry = lock.into_inner(); panic! cannot take the lock ownership
    let arc = config.as_arc();  // clone a new arc
    // Stop watching
    watcher.stop().unwrap();
    // You can watch twice
    watcher.watch().unwrap();
}
```

- **Dynamic Apollo config**

```rust

#[tokio::test]
async fn apollo_test() {
    // First build a ApolloClient
    let client = ApolloClient::new("http://localhost:8080")
        .appid("114514")
        .namespace("test", ConfigType::TOML);
    // Create a watcher to fetch apollo config changes at a `RealTime` mode.
    // `Entry` indicates how data should be deserialized.
    // The returned config type is `DynamicConfig<Entry>`
    let (config, mut watcher) =
        DynamicConfig::<Entry>::watch_apollo(client, WatchMode::RealTime).await;
    // Enable verbose mode (log messages with INFO level)
    watcher.verbose();
    // Start watching
    watcher.watch().unwrap();

    println!("{:?}", config);
    // Stop watching
    watcher.stop().unwrap();

    // You can start twice even you forget to call stop()
    watcher.watch().unwrap();

    // All changes will be reflected to config in time
    do_somthing(config);
}

```