Skip to content

Commit 696455b

Browse files
authored
Merge pull request #309 from quartiq/shrink
ConstPath{,Iter}, add Seeded
2 parents 10d2067 + 052941d commit 696455b

23 files changed

Lines changed: 494 additions & 153 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010

1111
### Changed
1212

13-
* PathIter takes the separator as a const generic. That allows compile time specialization
14-
of ascii separators.
13+
* Path takes thes separator as a member reducing monomorphization bloat.
14+
15+
### Added
16+
17+
* ConstPath and ConstPathIter taking the separator as a const generic. That allows compile time specialization of ascii separators.
18+
* Seeded trait to enable Transcode/Keys construction from runtime configuration.
1519

1620
## [0.20.1](https://github.com/quartiq/miniconf/compare/miniconf-v0.20.0...miniconf-v0.20.1) - 2026-02-12
1721

miniconf/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ assert!(MAX_DEPTH <= 6);
114114
assert!(MAX_LENGTH <= 32);
115115

116116
// Iterating over all leaf paths
117-
for path in Settings::SCHEMA.nodes::<Path<heapless::String<MAX_LENGTH>, '/'>, MAX_DEPTH>() {
118-
let path = path.unwrap().0;
117+
for path in Settings::SCHEMA.nodes::<Path<heapless::String<MAX_LENGTH>>, MAX_DEPTH>() {
118+
let path = path.unwrap().path;
119119
// Serialize each
120120
match json_core::get(&settings, &path, &mut buf) {
121121
// Full round-trip: deserialize and set again

miniconf/examples/cli.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use anyhow::Context;
2-
use miniconf::{IntoKeys, Keys, Path, SerdeError, TreeSchema, ValueError, json_core};
2+
use miniconf::{ConstPath, IntoKeys, Keys, SerdeError, TreeSchema, ValueError, json_core};
33

44
mod common;
55
use common::Settings;
@@ -8,7 +8,6 @@ use common::Settings;
88
///
99
/// This exposes the leaf nodes in `Settings` as long options, parses the command line,
1010
/// and then prints the settings struct as a list of option key-value pairs.
11-
1211
fn main() -> anyhow::Result<()> {
1312
let mut settings = Settings::new();
1413
settings.enable();
@@ -17,14 +16,14 @@ fn main() -> anyhow::Result<()> {
1716
while let Some(key) = args.next() {
1817
let key = key.strip_prefix('-').context("stripping initial dash")?;
1918
let value = args.next().context("looking for value")?;
20-
json_core::set_by_key(&mut settings, Path::<_, '-'>(key), value.as_bytes())
19+
json_core::set_by_key(&mut settings, ConstPath::<_, '-'>(key), value.as_bytes())
2120
.context("lookup/deserialize")?;
2221
}
2322

2423
// Dump settings
2524
let mut buf = vec![0; 1024];
2625
const MAX_DEPTH: usize = Settings::SCHEMA.shape().max_depth;
27-
for item in Settings::SCHEMA.nodes::<Path<String, '-'>, MAX_DEPTH>() {
26+
for item in Settings::SCHEMA.nodes::<ConstPath<String, '-'>, MAX_DEPTH>() {
2827
let key = item.unwrap();
2928
let mut k = key.into_keys().track();
3029
match json_core::get_by_key(&settings, &mut k, &mut buf[..]) {

miniconf/examples/scpi.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use core::str;
22

33
use miniconf::{
4-
IntoKeys, Keys, Path, PathIter, SerdeError, TreeDeserializeOwned, TreeSchema, TreeSerialize,
5-
ValueError, json_core,
4+
ConstPath, ConstPathIter, IntoKeys, Keys, SerdeError, TreeDeserializeOwned, TreeSchema,
5+
TreeSerialize, ValueError, json_core,
66
};
77

88
mod common;
@@ -32,7 +32,7 @@ impl<T: AsRef<str> + ?Sized> miniconf::Key for ScpiKey<T> {
3232
|| !name
3333
.chars()
3434
.zip(s.chars())
35-
.all(|(n, s)| n.to_ascii_lowercase() == s.to_ascii_lowercase())
35+
.all(|(n, s)| n.eq_ignore_ascii_case(&s))
3636
{
3737
continue;
3838
}
@@ -57,7 +57,7 @@ impl<T: AsRef<str> + ?Sized> miniconf::Key for ScpiKey<T> {
5757
}
5858

5959
#[derive(Clone)]
60-
struct ScpiPathIter<'a>(PathIter<'a, ':'>);
60+
struct ScpiPathIter<'a>(ConstPathIter<'a, ':'>);
6161

6262
impl<'a> Iterator for ScpiPathIter<'a> {
6363
type Item = ScpiKey<&'a str>;
@@ -73,7 +73,7 @@ impl<'a> IntoIterator for ScpiPath<'a> {
7373
type IntoIter = ScpiPathIter<'a>;
7474
type Item = ScpiKey<&'a str>;
7575
fn into_iter(self) -> Self::IntoIter {
76-
ScpiPathIter(PathIter::new(self.0))
76+
ScpiPathIter(ConstPathIter::new(self.0))
7777
}
7878
}
7979

@@ -134,7 +134,7 @@ fn main() -> anyhow::Result<()> {
134134

135135
let mut buf = vec![0; 1024];
136136
const MAX_DEPTH: usize = Settings::SCHEMA.shape().max_depth;
137-
for path in Settings::SCHEMA.nodes::<Path<String, ':'>, MAX_DEPTH>() {
137+
for path in Settings::SCHEMA.nodes::<ConstPath<String, ':'>, MAX_DEPTH>() {
138138
let path = path?;
139139
match json_core::get_by_key(&settings, &path, &mut buf) {
140140
Ok(len) => println!(

miniconf/src/impls/internal.rs

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,44 +98,86 @@ impl<T: TreeSchema, const N: usize> TreeSchema for [T; N] {
9898
const SCHEMA: &'static Schema = &Schema::homogeneous(Homogeneous::new(N, T::SCHEMA));
9999
}
100100

101+
fn serialize_by_key_slice<T: TreeSerialize, S: Serializer>(
102+
values: &[T],
103+
schema: &'static Schema,
104+
mut keys: impl Keys,
105+
ser: S,
106+
) -> Result<S::Ok, SerdeError<S::Error>> {
107+
values[schema.next(&mut keys)?].serialize_by_key(keys, ser)
108+
}
109+
110+
fn deserialize_by_key_slice<'de, T: TreeDeserialize<'de>, D: Deserializer<'de>>(
111+
values: &mut [T],
112+
schema: &'static Schema,
113+
mut keys: impl Keys,
114+
de: D,
115+
) -> Result<(), SerdeError<D::Error>> {
116+
values[schema.next(&mut keys)?].deserialize_by_key(keys, de)
117+
}
118+
119+
fn probe_by_key_slice<'de, T: TreeDeserialize<'de>, D: Deserializer<'de>>(
120+
schema: &'static Schema,
121+
mut keys: impl Keys,
122+
de: D,
123+
) -> Result<(), SerdeError<D::Error>> {
124+
schema.next(&mut keys)?;
125+
T::probe_by_key(keys, de)
126+
}
127+
128+
fn ref_any_by_key_slice<'a, T: TreeAny>(
129+
values: &'a [T],
130+
schema: &'static Schema,
131+
mut keys: impl Keys,
132+
) -> Result<&'a dyn Any, ValueError> {
133+
values[schema.next(&mut keys)?].ref_any_by_key(keys)
134+
}
135+
136+
fn mut_any_by_key_slice<'a, T: TreeAny>(
137+
values: &'a mut [T],
138+
schema: &'static Schema,
139+
mut keys: impl Keys,
140+
) -> Result<&'a mut dyn Any, ValueError> {
141+
values[schema.next(&mut keys)?].mut_any_by_key(keys)
142+
}
143+
101144
impl<T: TreeSerialize, const N: usize> TreeSerialize for [T; N]
102145
where
103146
Self: TreeSchema,
104147
{
105148
fn serialize_by_key<S: Serializer>(
106149
&self,
107-
mut keys: impl Keys,
150+
keys: impl Keys,
108151
ser: S,
109152
) -> Result<S::Ok, SerdeError<S::Error>> {
110-
self[Self::SCHEMA.next(&mut keys)?].serialize_by_key(keys, ser)
153+
serialize_by_key_slice(self.as_slice(), Self::SCHEMA, keys, ser)
111154
}
112155
}
113156

114157
impl<'de, T: TreeDeserialize<'de>, const N: usize> TreeDeserialize<'de> for [T; N] {
115158
fn deserialize_by_key<D: Deserializer<'de>>(
116159
&mut self,
117-
mut keys: impl Keys,
160+
keys: impl Keys,
118161
de: D,
119162
) -> Result<(), SerdeError<D::Error>> {
120-
self[Self::SCHEMA.next(&mut keys)?].deserialize_by_key(keys, de)
163+
deserialize_by_key_slice(self.as_mut_slice(), Self::SCHEMA, keys, de)
121164
}
122165

123166
fn probe_by_key<D: Deserializer<'de>>(
124-
mut keys: impl Keys,
167+
keys: impl Keys,
125168
de: D,
126169
) -> Result<(), SerdeError<D::Error>> {
127-
Self::SCHEMA.next(&mut keys)?;
128-
T::probe_by_key(keys, de)
170+
probe_by_key_slice::<T, _>(Self::SCHEMA, keys, de)
129171
}
130172
}
131173

132174
impl<T: TreeAny, const N: usize> TreeAny for [T; N] {
133-
fn ref_any_by_key(&self, mut keys: impl Keys) -> Result<&dyn Any, ValueError> {
134-
self[Self::SCHEMA.next(&mut keys)?].ref_any_by_key(keys)
175+
fn ref_any_by_key(&self, keys: impl Keys) -> Result<&dyn Any, ValueError> {
176+
ref_any_by_key_slice(self.as_slice(), Self::SCHEMA, keys)
135177
}
136178

137-
fn mut_any_by_key(&mut self, mut keys: impl Keys) -> Result<&mut dyn Any, ValueError> {
138-
self[Self::SCHEMA.next(&mut keys)?].mut_any_by_key(keys)
179+
fn mut_any_by_key(&mut self, keys: impl Keys) -> Result<&mut dyn Any, ValueError> {
180+
mut_any_by_key_slice(self.as_mut_slice(), Self::SCHEMA, keys)
139181
}
140182
}
141183

0 commit comments

Comments
 (0)