# cfgmatic-core

[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue)](https://gitlab.opentc.ru/opentc/rust-cfgmatic)
[![Unsafe](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
[![rustc](https://img.shields.io/badge/rustc-1.92+-lightgray.svg)](https://www.rust-lang.org)

Core types and traits for the cfgmatic configuration framework.

## Overview

`cfgmatic-core` provides the foundational types and traits used across all
cfgmatic crates. It defines the common vocabulary for configuration management.

## Features

- **`default`**: Core types and sync traits
- **`async`**: Async trait definitions for async/await workflows

## Types

### Core Traits

- **`Config`**: Synchronous configuration trait with merge and validation
- **`AsyncConfig`**: Async extensions for configurations (requires `async` feature)

### Core Types

- **`ConfigSource`**: Enum representing where configuration originates
- **`Change`**: A single configuration change with path and values
- **`ChangeType`**: The type of change (Create, Update, Delete, NoChange)
- **`ChangeSummary`**: Summary statistics for a set of changes

### Error Handling

- **`Error`**: Unified error type for all cfgmatic operations
- **`Result<T>`**: Type alias for `Result<T, Error>`

## Quick Start

```rust
use cfgmatic_core::{Config, Change, ChangeType};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize)]
struct ServerConfig {
    host: String,
    port: u16,
}

impl Config for ServerConfig {
    fn merge(&mut self, other: Self) -> cfgmatic_core::Result<()> {
        self.host = other.host;
        self.port = other.port;
        Ok(())
    }

    fn validate(&self) -> cfgmatic_core::Result<()> {
        if self.port < 1024 {
            return Err(cfgmatic_core::Error::validation(
                "port must be >= 1024"
            ));
        }
        Ok(())
    }
}
```

## Async Support

With the `async` feature:

```rust
use cfgmatic_core::AsyncConfig;

#[cfg(feature = "async")]
impl AsyncConfig for ServerConfig {
    async fn collect_state(&self) -> cfgmatic_core::Result<serde_json::Value> {
        // Query actual state from running application
        let client = reqwest::Client::new();
        let url = format!("http://{}:{}/api/state", self.host, self.port);
        let state = client.get(&url).send().await?
            .json().await?;
        Ok(state)
    }
}
```

## Configuration Source

Track where your configuration comes from:

```rust
use cfgmatic_core::ConfigSource;

let source = ConfigSource::file("/etc/myapp/config.toml");
// or
let source = ConfigSource::env("MYAPP_PORT");
// or
let source = ConfigSource::remote("consul://config/service");

println!("Config from: {}", source.as_str());
```

## License

This project is licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or <http://opensource.org/licenses/MIT>)

at your option.
