Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps #158

Merged
merged 14 commits into from
Jul 26, 2023
Merged

deps #158

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
32 changes: 23 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,40 +75,42 @@ jobs:
matrix:
toolchain:
- stable
- beta
- 1.65.0 # keep in sync with manifest MSRV
target:
- thumbv7em-none-eabihf

steps:
- uses: actions/checkout@v2

- name: Install Rust ${{ matrix.toolchain }}
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
target: thumbv7em-none-eabihf
target: ${{ matrix.target }}
override: true

- name: Cargo Check
uses: actions-rs/cargo@v1
with:
command: check
args: --verbose
args: --verbose --target ${{ matrix.target }}

- name: Cargo Build [No-Features]
uses: actions-rs/cargo@v1
with:
command: build
args: --no-default-features
args: --no-default-features --target ${{ matrix.target }}

- name: Cargo Build
uses: actions-rs/cargo@v1
with:
command: build
args: --target ${{ matrix.target }}

- name: Cargo Build [Release]
uses: actions-rs/cargo@v1
with:
command: build
args: --release
args: --release --target ${{ matrix.target }}

- name: Cargo Build [Examples]
uses: actions-rs/cargo@v1
Expand All @@ -117,7 +119,17 @@ jobs:
args: --examples

test:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
matrix:
toolchain:
- stable
- 1.65.0 # keep in sync with manifest MSRV
args:
- --all-features
- --no-default-features
- --no-default-features --features json

steps:
- uses: actions/checkout@v2

Expand All @@ -130,20 +142,22 @@ jobs:
uses: actions-rs/toolchain@v1
with:
override: true
toolchain: stable
toolchain: ${{ matrix.toolchain }}
profile: minimal

- name: Cargo Test
uses: actions-rs/cargo@v1
with:
command: test
args: ${{ matrix.args }}

examples:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
matrix:
example:
- mqtt
- readback
steps:
- uses: actions/checkout@v2

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

* `json` feature to enable the `Serde<JsonCoreSlash>` spec. Enabled by default.

### Changed

* [breaking] The `Miniconf` trait is now generic over the `Deserializer`/`Serializer`. It
Expand All @@ -29,6 +33,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [breaking] `iter_paths`/`MiniconfIter` is now generic over the type
to write the path into. Downstream crates should replace `iter_paths::<L, TS>()` with
`iter_paths::<L, heapless::String<TS>>()`.
* The `mqtt-client` feature has been renamed into `mqtt` with backward compatibility.
* [breaking] Re-exports of `heapless` and `serde-json-core` have been removed as they are
not needed to work with the public API.

## [0.7.1] (https://github.com/quartiq/miniconf/compare/v0.7.0...v0.7.1)

Expand Down
27 changes: 17 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
[package]
name = "miniconf"

# Don't forget to change `miniconf_derive`'s version as well.
version = "0.7.1"

authors = ["James Irwin <[email protected]>", "Ryan Summers <[email protected]", "Robert Jördens <[email protected]>"]
edition = "2021"
license = "MIT"
description = "Inspect serde namespaces by path"
repository = "https://github.com/quartiq/miniconf"
keywords = ["settings", "serde", "no_std", "json", "mqtt"]
categories = ["no-std", "config", "rust-patterns", "parsing"]
rust-version = "1.65.0"
rust-version = "1.65.0" # keep in sync with CI
resolver = "2"

[dependencies]
miniconf_derive = { path = "miniconf_derive" , version = "0.6" }
serde-json-core = { git = "https://github.com/rust-embedded-community/serde-json-core.git" }
serde = { version = "1.0.120", features = ["derive"], default-features = false }
log = "0.4"
heapless = { version = "0.7", features = ["serde"] }
miniconf_derive = { path = "miniconf_derive" , version = "0.6" }
itoa = "1.0.4"

serde-json-core = { git = "https://github.com/rust-embedded-community/serde-json-core.git" , optional = true}
log = {version = "0.4", optional = true}
heapless = { version = "0.7", features = ["serde"], optional=true }
jordens marked this conversation as resolved.
Show resolved Hide resolved
minimq = { version = "0.7", optional = true }
smlang = { version = "0.6", optional = true }
itoa = "1.0.4"

[features]
default = ["mqtt-client"]
mqtt-client = ["minimq", "smlang"]
default = ["mqtt"]
json = ["dep:serde-json-core", "dep:heapless"]
mqtt = ["dep:minimq", "dep:smlang", "dep:log", "json"]
mqtt-client = ["mqtt"] # backwards compat

[dev-dependencies]
machine = "0.3"
Expand All @@ -41,3 +43,8 @@ branch = "feature/0.7"

[[example]]
name = "mqtt"
required-features = ["mqtt"]

[[example]]
name = "readback"
required-features = ["json"]
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ client](MqttClient) and a Python reference implementation to ineract with it.

## Example
```rust
use miniconf::{heapless::String, Error, Miniconf, SerDe};
use miniconf::{Error, Miniconf, SerDe};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Copy, Clone, Default)]
Expand Down Expand Up @@ -97,7 +97,7 @@ let len = settings.get("/struct_", &mut buf)?;
assert_eq!(&buf[..len], br#"{"a":3,"b":3}"#);

// Iterating over and serializing all paths
for path in Settings::iter_paths::<3, String<32>>().unwrap() {
for path in Settings::iter_paths::<3, String>().unwrap() {
match settings.get(&path, &mut buf) {
Ok(len) => {
settings.set(&path, &buf[..len]).unwrap();
Expand All @@ -110,7 +110,7 @@ for path in Settings::iter_paths::<3, String<32>>().unwrap() {
}
}

# Ok::<(), miniconf::Error<miniconf::serde_json_core::de::Error>>(())
# Ok::<(), miniconf::Error<serde_json_core::de::Error>>(())
```

## MQTT
Expand Down Expand Up @@ -160,4 +160,7 @@ Deferred (non-atomic) access to inner elements of some types is not yet supporte
* Tuple structs (other than [Option], [Array])

## Features
* `mqtt-client` Enabled the MQTT client feature. See the example in [MqttClient].
* `mqtt` Enable the MQTT client feature. See the example in [MqttClient].
* `json` Enable the [SerDe] implementation for the [JsonCoreSlash] style.

Both features are enabled by default.
4 changes: 2 additions & 2 deletions examples/readback.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miniconf::{heapless::String, Miniconf, SerDe};
use miniconf::{Miniconf, SerDe};

#[derive(Debug, Default, Miniconf)]
struct AdditionalSettings {
Expand All @@ -23,7 +23,7 @@ fn main() {
};

// Maintains our state of iteration.
let mut settings_iter = Settings::iter_paths::<5, String<128>>().unwrap();
let mut settings_iter = Settings::iter_paths::<5, String>().unwrap();

// Just get one topic/value from the iterator
if let Some(topic) = settings_iter.next() {
Expand Down
6 changes: 3 additions & 3 deletions miniconf_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ categories = ["no-std", "config", "rust-patterns", "parsing"]
proc-macro = true

[dependencies]
syn = { version="1.0.58", features=["extra-traits"] }
quote = "1.0.8"
proc-macro2 = "1.0.24"
syn = { version = "2.0", features = ["extra-traits"] }
quote = "1.0"
proc-macro2 = "1.0"
45 changes: 0 additions & 45 deletions miniconf_derive/src/attributes.rs

This file was deleted.

22 changes: 14 additions & 8 deletions miniconf_derive/src/field.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use super::attributes::{AttributeParser, MiniconfAttribute};
use syn::{parse_quote, Generics};

pub struct StructField {
Expand All @@ -8,14 +7,21 @@ pub struct StructField {

impl StructField {
pub fn new(field: syn::Field) -> Self {
let attributes: Vec<MiniconfAttribute> = field
.attrs
.iter()
.filter(|attr| attr.path.is_ident("miniconf"))
.map(|attr| AttributeParser::new(attr.tokens.clone()).parse())
.collect();
let mut deferred = false;

let deferred = attributes.iter().any(|x| *x == MiniconfAttribute::Defer);
for attr in field.attrs.iter() {
if attr.path().is_ident("miniconf") {
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("defer") {
deferred = true;
Copy link
Member

@ryan-summers ryan-summers Jul 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing style, while some code overhead, was intended to make it easy to add new attributes while making it relatively maintainable. This is less code, but does it make it easier to easily add new attributes in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just another if, i.e. about five lines.
Same amount as in the old code (c.f. https://github.com/quartiq/miniconf/pull/150/files#diff-1857dc627a1f48fd67d28c8ed2d35e53994fe4b9d71ee181c034cc98a30bd163)

Ok(())
} else {
Err(meta.error(format!("unrecognized miniconf attribute {:?}", meta.path)))
}
})
.unwrap();
}
}

Self { deferred, field }
}
Expand Down
1 change: 0 additions & 1 deletion miniconf_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

mod attributes;
mod field;

use field::StructField;
Expand Down
4 changes: 2 additions & 2 deletions src/array.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Error, IterError, Metadata, Miniconf};
use crate::{Error, IterError, Metadata, Miniconf};
use core::{
fmt::Write,
ops::{Deref, DerefMut},
Expand Down Expand Up @@ -173,7 +173,7 @@ impl<T: Miniconf, const N: usize> Miniconf for Array<T, N> {
}
}

impl<T: crate::Serialize + crate::DeserializeOwned, const N: usize> Miniconf for [T; N] {
impl<T: serde::Serialize + serde::de::DeserializeOwned, const N: usize> Miniconf for [T; N] {
fn set_path<'a, 'b: 'a, P, D>(
&mut self,
path_parts: &mut P,
Expand Down
2 changes: 1 addition & 1 deletion src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{IterError, Metadata, SerDe};
use crate::{IterError, Metadata, SerDe};
use core::{fmt::Write, marker::PhantomData};

/// An iterator over the paths in a Miniconf namespace.
Expand Down
46 changes: 46 additions & 0 deletions src/json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::{Error, Miniconf, SerDe};
use serde_json_core::{de, ser};

/// Marker struct for the "JSON and `/`" [SerDe] specification.
///
/// Access items with `'/'` as path separator and JSON (from `serde-json-core`)
/// as serialization/deserialization payload format.
pub struct JsonCoreSlash;

impl<T> SerDe<JsonCoreSlash> for T
where
T: Miniconf,
{
const SEPARATOR: char = '/';
type DeError = de::Error;
type SerError = ser::Error;

fn set(&mut self, path: &str, data: &[u8]) -> Result<usize, Error<Self::DeError>> {
let mut de = de::Deserializer::new(data);
self.set_path(&mut path.split(Self::SEPARATOR).skip(1), &mut de)?;
de.end().map_err(Error::PostDeserialization)
}

fn get(&self, path: &str, data: &mut [u8]) -> Result<usize, Error<Self::SerError>> {
let mut ser = ser::Serializer::new(data);
self.get_path(&mut path.split(Self::SEPARATOR).skip(1), &mut ser)?;
Ok(ser.end())
}
}

// These allow unifying serde error information to make writing examples
// and tests easier. Doing this conversion is optional.
// #[cfg(any(test, doctest))]
impl From<Error<ser::Error>> for Error<de::Error> {
fn from(value: Error<ser::Error>) -> Self {
match value {
Error::BadIndex => Self::BadIndex,
Error::PathAbsent => Self::PathAbsent,
Error::PathNotFound => Self::PathNotFound,
Error::PathTooLong => Self::PathTooLong,
Error::PathTooShort => Self::PathTooShort,
Error::PostDeserialization(_) => Error::PostDeserialization(de::Error::CustomError),
Error::SerDe(_) => Self::SerDe(de::Error::CustomError),
}
}
}
Loading
Loading