Reusable serde adapters and utilities for Rust.
Qubit Serde collects small serde adapters that are useful across Rust libraries. It currently provides duration formats used by configuration and retry-style libraries, and is intended to grow with other focused serde utility modules.
- Focused adapters: provide small, reusable
#[serde(with = "...")]modules. - Shared conversion semantics: reuse
qubit-datatypeconversion rules for supported scalar formats. - Configuration friendly: support human-readable duration strings where useful.
- Easy reuse: make adapters available through a consistent
qubit_serde::serde::*path.
duration_millisserializesstd::time::Durationas a whole millisecondu64.- Deserialization accepts a non-negative
u64millisecond count. - Duration-to-millisecond conversion uses explicit
qubit-datatypemillisecond options.
duration_with_unitserializes durations as strings such as500ms.- Deserialization accepts strings with
ns,us,µs,μs,ms,s,m,h, ord. - Bare integer input is accepted as milliseconds for lenient configuration parsing.
- Duration-to-string conversion uses explicit
qubit-datatypemillisecond options. - Invalid units, invalid numbers, fractional values, and overflows are rejected.
Add this to your Cargo.toml:
[dependencies]
qubit-serde = "0.2"use std::time::Duration;
use serde::{
Deserialize,
Serialize,
};
#[derive(Debug, Serialize, Deserialize)]
struct Config {
#[serde(with = "qubit_serde::serde::duration_with_unit")]
timeout: Duration,
}
let config: Config = serde_json::from_str(r#"{"timeout":"5s"}"#)
.expect("duration with unit should parse");
assert_eq!(config.timeout, Duration::from_secs(5));
let json = serde_json::to_string(&config).expect("config should serialize");
assert_eq!(json, r#"{"timeout":"5000ms"}"#);use std::time::Duration;
use serde::{
Deserialize,
Serialize,
};
#[derive(Debug, Serialize, Deserialize)]
struct RetryState {
#[serde(with = "qubit_serde::serde::duration_millis")]
elapsed: Duration,
}
let state: RetryState = serde_json::from_str(r#"{"elapsed":250}"#)
.expect("millisecond duration should parse");
assert_eq!(state.elapsed, Duration::from_millis(250));serde::duration_millis- duration as whole milliseconds.serde::duration_with_unit- duration as strings with supported time units.
This project maintains tests for serialization, deserialization, accepted formats, invalid inputs, and overflow cases.
# Run all tests
cargo test
# Run with coverage report
./coverage.sh
# Generate text format report
./coverage.sh text
# Run CI checks (format, clippy, test, coverage, audit)
./ci-check.shSee COVERAGE.md for detailed coverage statistics.
Runtime dependencies:
qubit-datatypefor shared duration conversion semantics.serdefor serialization and deserialization integration.serde_jsonfor scalar value handling in lenient duration deserialization.
Copyright (c) 2025 - 2026. Haixing Hu, Qubit Co. Ltd. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
See LICENSE for the full license text.
Contributions are welcome! Please feel free to submit a Pull Request.
- Follow the Rust API guidelines.
- Keep adapters small, documented, and aligned with shared conversion semantics.
- Add tests for success paths, invalid input, and boundary conditions.
- Run
./ci-check.shbefore submitting PRs.
Haixing Hu - Qubit Co. Ltd.
More Rust libraries from Qubit are published under the qubit-ltd organization on GitHub.
Repository: https://github.com/qubit-ltd/rs-serde