mirror of
https://github.com/kristoferssolo/filecaster.git
synced 2025-10-21 19:00:34 +00:00
docs: add readme
This commit is contained in:
parent
62f48cf3cd
commit
4a0ac666ac
22
Cargo.toml
22
Cargo.toml
@ -2,6 +2,23 @@
|
|||||||
name = "from_file"
|
name = "from_file"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
||||||
|
description = "Procedural macro to derive configuration from files, with optional merging capabilities."
|
||||||
|
repository = "https://github.com/kristoferssolo/from_file"
|
||||||
|
documentation = "https://docs.rs/from_file"
|
||||||
|
homepage = "https://github.com/kristoferssolo/from_file"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
keywords = [
|
||||||
|
"proc-macro",
|
||||||
|
"derive",
|
||||||
|
"configuration",
|
||||||
|
"file-parsing",
|
||||||
|
"defaults",
|
||||||
|
"merge",
|
||||||
|
]
|
||||||
|
categories = ["development-tools::procedural-macro", "parsing", "config"]
|
||||||
|
exclude = ["/.github", "/.gitignore", "/tests", "*.png", "*.md"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
@ -17,3 +34,8 @@ merge = { version = "0.2", optional = true }
|
|||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
|
[lints.clippy]
|
||||||
|
pedantic = "warn"
|
||||||
|
nursery = "warn"
|
||||||
|
unwrap_used = "warn"
|
||||||
|
|||||||
63
README.md
Normal file
63
README.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# `from_file`
|
||||||
|
|
||||||
|
Procedural macro to derive configuration from files, with optional merging capabilities.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Derive Configuration:** Easily load configuration from files into your Rust structs.
|
||||||
|
- **Default Values:** Specify default values for struct fields using the `#[default = "..."]` attribute.
|
||||||
|
- **Optional Merging:** When the `merge` feature is enabled, allows merging multiple configuration sources.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo add hexlab
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use from_file::FromFile;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Deserialize, Serialize, FromFile)]
|
||||||
|
pub struct MyConfig {
|
||||||
|
pub host: String,
|
||||||
|
#[default = "8080"]
|
||||||
|
pub port: u16,
|
||||||
|
#[default = "false"]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Simulate loading from a file (e.g., JSON, YAML)
|
||||||
|
let file_content = r#"
|
||||||
|
{
|
||||||
|
"host": "localhost"
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let config_from_file: MyConfig = serde_json::from_str(file_content).unwrap();
|
||||||
|
let config = MyConfig::from_file(Some(config_from_file));
|
||||||
|
|
||||||
|
println!("Config: {:?}", config);
|
||||||
|
// Expected output: Config { host: "localhost", port: 8080, enabled: false }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Full documentation is available at [docs.rs](https://docs.rs/from_file).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is dual-licensed under either:
|
||||||
|
|
||||||
|
- MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
|
||||||
|
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
|
||||||
|
|
||||||
|
at your option.
|
||||||
@ -1,8 +1,8 @@
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{
|
use syn::{
|
||||||
Attribute, Data, DeriveInput, Error, Expr, Fields, GenericParam, Generics, Meta, Result,
|
Attribute, Data, DeriveInput, Error, Expr, Fields, GenericParam, Generics, Meta, Result,
|
||||||
parse_quote,
|
WherePredicate, parse_quote, parse2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const WITH_MERGE: bool = cfg!(feature = "merge");
|
const WITH_MERGE: bool = cfg!(feature = "merge");
|
||||||
@ -78,8 +78,11 @@ pub fn impl_from_file(input: &DeriveInput) -> Result<TokenStream> {
|
|||||||
} else {
|
} else {
|
||||||
let mut where_clause = where_clause.cloned();
|
let mut where_clause = where_clause.cloned();
|
||||||
if let Some(wc) = &mut where_clause {
|
if let Some(wc) = &mut where_clause {
|
||||||
wc.predicates
|
wc.predicates.extend(
|
||||||
.extend(default_bounds.into_iter().map(|bound| parse_quote!(#bound)));
|
default_bounds
|
||||||
|
.into_iter()
|
||||||
|
.map(|bound| parse2::<WherePredicate>(bound).unwrap()),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
where_clause = Some(parse_quote!(where #(#default_bounds),*));
|
where_clause = Some(parse_quote!(where #(#default_bounds),*));
|
||||||
}
|
}
|
||||||
@ -117,8 +120,7 @@ pub fn impl_from_file(input: &DeriveInput) -> Result<TokenStream> {
|
|||||||
Self::from_file(value)
|
Self::from_file(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}.into())
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_trait_bouts(mut generics: Generics) -> Generics {
|
fn add_trait_bouts(mut generics: Generics) -> Generics {
|
||||||
@ -136,9 +138,8 @@ fn parse_default_attr(attr: &Attribute) -> Result<Option<Expr>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let meta = attr.parse_args::<Meta>()?;
|
let meta = attr.parse_args::<Meta>()?;
|
||||||
let name_value = match meta {
|
let Meta::NameValue(name_value) = meta else {
|
||||||
Meta::NameValue(nv) => nv,
|
return Err(Error::new_spanned(attr, "Expected #[default = \"value\"]"));
|
||||||
_ => return Err(Error::new_spanned(attr, "Expected #[default = \"value\"]")),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match name_value.value {
|
match name_value.value {
|
||||||
|
|||||||
@ -9,8 +9,5 @@ use syn::{DeriveInput, parse_macro_input};
|
|||||||
#[proc_macro_derive(FromFile, attributes(from_file))]
|
#[proc_macro_derive(FromFile, attributes(from_file))]
|
||||||
pub fn derive_from_file(input: TokenStream) -> TokenStream {
|
pub fn derive_from_file(input: TokenStream) -> TokenStream {
|
||||||
let inp = parse_macro_input!(input as DeriveInput);
|
let inp = parse_macro_input!(input as DeriveInput);
|
||||||
match impl_from_file(&inp) {
|
impl_from_file(&inp).unwrap_or_else(|e| e.to_compile_error().into())
|
||||||
Ok(ts) => ts.into(),
|
|
||||||
Err(e) => e.to_compile_error().into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user