Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased] - ReleaseDate

## [0.1.1](https://github.com/Kryptonite-RU/config-manager-rs/releases/tag/0.1.0) - 2023-02-27
### Added
- If a field is not annotated, default source order will be assigned
### Changed
- The default behavior of `env_prefix` is no prefix instead of a binary name now
## [0.1.0](https://github.com/Kryptonite-RU/config-manager-rs/releases/tag/0.1.0) - 2022-12-27
Initial tag
23 changes: 7 additions & 16 deletions config-manager-proc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use quote::{quote, ToTokens};
use syn::{parse::Parser, punctuated::Punctuated, *};

use generator::*;
use utils::{config::*, field::*, field_to_tokens, parser::*, top_level::*};
use utils::{config::*, field::*, parser::*, top_level::*};

/// Macro generating an implementation of the `ConfigInit` trait
/// or constructing global variable. \
Expand Down Expand Up @@ -48,6 +48,7 @@ pub fn config(attrs: TokenStream0, input: TokenStream0) -> TokenStream0 {
global_name,
file,
table,
default_order,
__debug_cmd_input__
)
)]
Expand All @@ -62,6 +63,7 @@ pub fn generate_config(input: TokenStream0) -> TokenStream0 {
configs,
debug_cmd_input,
table_name,
default_order,
} = AppTopLevelInfo::extract(&input.attrs);

let class: DataStruct = match input.data {
Expand All @@ -85,14 +87,8 @@ pub fn generate_config(input: TokenStream0) -> TokenStream0 {
process_flatten_field(field)
} else if field_is_subcommand(&field) {
process_subcommand_field(field, &debug_cmd_input)
} else if field_is_source(&field) {
process_field(field, &table_name)
} else {
panic!(
"Error: each field must be annotated with one of the following: \
source/flatten/subcommand (field's name: \"{}\")",
field_to_tokens(&field)
)
process_field(field, &table_name, &default_order)
};
((name, initialization), clap_field)
})
Expand All @@ -112,11 +108,12 @@ pub fn generate_config(input: TokenStream0) -> TokenStream0 {

/// Annotated with this macro structure can be used
/// as a flatten argument in the [config](attr.config.html) macro.
#[proc_macro_derive(Flatten, attributes(source, flatten, subcommand, table))]
#[proc_macro_derive(Flatten, attributes(source, flatten, subcommand, table, default_order))]
pub fn generate_flatten(input: TokenStream0) -> TokenStream0 {
let input = parse_macro_input!(input as DeriveInput);

let table_name = extract_table_name(&input.attrs);
let default_order = extract_source_order(&input.attrs);

let class_ident = input.ident;
let class: DataStruct = match input.data {
Expand All @@ -140,14 +137,8 @@ pub fn generate_flatten(input: TokenStream0) -> TokenStream0 {
process_flatten_field(field)
} else if field_is_subcommand(&field) {
panic!("subcommands are forbidden in the nested structures")
} else if field_is_source(&field) {
process_field(field, &table_name)
} else {
panic!(
"Error: each field must be annotated with one of the following: \
source/flatten (field's name: \"{}\")",
field_to_tokens(&field)
)
process_field(field, &table_name, &default_order)
};
((name, initialization), clap_field)
})
Expand Down
8 changes: 0 additions & 8 deletions config-manager-proc/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ pub(crate) mod field;
pub(crate) mod parser;
pub(crate) mod top_level;

pub(crate) fn field_to_tokens(field: &Field) -> TokenStream {
field
.ident
.clone()
.expect("Unnamed fields are forbidden")
.to_token_stream()
}

/// Formated string to TokenStream \
/// Same as ```TokenStream::from_str(&format!(...)).unwrap()```
macro_rules! format_to_tokens {
Expand Down
1 change: 1 addition & 0 deletions config-manager-proc/src/utils/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(crate) const SOURCE_KEY: &str = "source";
pub(crate) const CONFIG_FILE_KEY: &str = "file";
pub(crate) const DEBUG_INPUT_KEY: &str = "__debug_cmd_input__";
pub(crate) const TABLE_NAME_KEY: &str = "table";
pub(crate) const SOURCE_ORDER_KEY: &str = "default_order";
pub(crate) const FLATTEN: &str = "flatten";
pub(crate) const SUBCOMMAND: &str = "subcommand";

Expand Down
10 changes: 5 additions & 5 deletions config-manager-proc/src/utils/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ use strum::IntoEnumIterator;
use super::attributes::*;
use crate::*;

fn str_to_config_format_repr<T: AsRef<str>>(s: T) -> String {
match s.as_ref() {
fn str_to_config_format_repr(s: &str) -> String {
match s {
"json" | "json5" | "toml" | "yaml" | "ron" => {
let capitalize_first = |s: &str| -> String {
let mut chars = s.chars();
let first_char = chars.next().unwrap();
first_char.to_uppercase().to_string() + &chars.collect::<String>()
};

let accepted_format = capitalize_first(s.as_ref());
let accepted_format = capitalize_first(s);
let pref = "::config_manager::__private::config::FileFormat::".to_string();
pref + &accepted_format
}
_ => panic!("{} format is not supported", s.as_ref()),
_ => panic!("{} format is not supported", s),
}
}

Expand Down Expand Up @@ -117,7 +117,7 @@ fn handle_file_attribute(
.skip(1)
.take(format_atr.len() - 2)
.collect();
file_format = Some(str_to_config_format_repr(drop_fst_and_lst))
file_format = Some(str_to_config_format_repr(&drop_fst_and_lst))
}
}
}
Expand Down
28 changes: 17 additions & 11 deletions config-manager-proc/src/utils/field.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 JSRPC “Kryptonite”

mod utils;
pub(crate) mod utils;

use super::{attributes::*, format_to_tokens};
use crate::*;
Expand Down Expand Up @@ -29,24 +29,30 @@ pub(crate) struct ProcessFieldResult {
pub(crate) initialization: TokenStream,
}

pub(crate) fn field_is_source(field: &Field) -> bool {
field
.attrs
.iter()
.any(|attr| compare_attribute_name(attr, SOURCE_KEY))
}

pub(crate) fn process_field(field: Field, table_name: &Option<String>) -> ProcessFieldResult {
pub(crate) fn process_field(
field: Field,
table_name: &Option<String>,
default_order: &Option<ExtractedAttributes>,
) -> ProcessFieldResult {
let field_name = field.ident.clone().expect("Unnamed fields are forbidden");
if number_of_crate_attribute(&field) != 1 {
if number_of_crate_attribute(&field) > 1 {
panic!(
"Error: source attribute must be the only attribute of the field (field's name: \
\"{}\")",
&field_name
);
}

let attributes_order = extract_attributes(field, table_name.clone());
let attributes_order = extract_attributes(field, table_name)
.or_else(|| default_order.clone())
.unwrap_or_else(|| ExtractedAttributes {
variables: vec![
FieldAttribute::Clap(std::default::Default::default()),
FieldAttribute::Env(std::default::Default::default()),
FieldAttribute::Config(std::default::Default::default()),
],
..std::default::Default::default()
});

ProcessFieldResult {
initialization: attributes_order.gen_init(&field_name.to_string()),
Expand Down
Loading