diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f16c5d3..a8eedd9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -4,15 +4,27 @@ on:
push:
branches:
- master
+ - dev
- boilerplate
+ - idiomatic
+ - rc1
+ - rc2
+ - rc3
pull_request:
+permissions:
+ contents: read
+
+defaults:
+ run:
+ shell: bash
+
env:
CARGO_TERM_COLOR: always
jobs:
check:
- name: Test, Clippy, Fmt, Checkers
+ name: Stable checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -21,22 +33,19 @@ jobs:
with:
components: clippy
- - name: Install nightly rustfmt
- run: rustup toolchain install nightly --profile minimal --component rustfmt
+ - name: Install pinned nightly rustfmt
+ run: rustup toolchain install nightly-2026-08-08 --profile minimal --component rustfmt
- uses: Swatinem/rust-cache@v2
- - name: cargo test
- run: cargo test --locked
+ - name: cargo test (all targets)
+ run: cargo test --all-targets --locked
- name: cargo clippy
run: cargo clippy --all-targets --locked -- -D warnings
- - name: cargo build (test-doomgram example)
- run: cargo build --examples --features test-doomgram --locked
-
- name: cargo doc
- run: cargo doc --no-deps --locked
+ run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --locked
- name: rustfmt
run: ./scripts/fmt --check
@@ -50,6 +59,28 @@ jobs:
- name: DERIVE_LAYOUT checker
run: python3 scripts/check_derives.py
+ - name: cargo publish (dry run)
+ run: cargo publish --dry-run --locked
+
+ feature:
+ name: test-doomgram feature checks
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: dtolnay/rust-toolchain@stable
+
+ - uses: Swatinem/rust-cache@v2
+
+ - name: cargo test (test-doomgram)
+ run: cargo test --features test-doomgram --locked
+
+ - name: cargo build (examples with test-doomgram)
+ run: cargo build --examples --features test-doomgram --locked
+
+ - name: cargo doc (test-doomgram)
+ run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --features test-doomgram --locked
+
msrv:
name: MSRV (1.74)
runs-on: ubuntu-latest
@@ -61,6 +92,6 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: cargo check (library)
- # Full `cargo test` needs dev-deps (criterion → clap_lex 2024 edition),
- # which exceeds MSRV 1.74; the stable job runs the full test suite.
+ # Full tests need dev-deps (criterion -> clap_lex 2024 edition);
+ # stable runs the complete test suite; MSRV only checks the library.
run: cargo check --lib --locked
diff --git a/.vimrc b/.vimrc
index b7392f5..d34bf9e 100644
--- a/.vimrc
+++ b/.vimrc
@@ -1,6 +1,70 @@
+" Synesis C/C++ project .vimrc — aligned with .sis/.vscode/c_cxx/settings.json
+set nocompatible
+filetype indent plugin on
+syntax enable
set autoindent
-set expandtab
-set shiftwidth=4
-set softtabstop=4
-set tabstop=4
\ No newline at end of file
+set backspace=indent,eol,start
+set hlsearch
+set incsearch
+set number
+
+" files.insertFinalNewline
+set eol
+set fixeol
+
+" editor.renderWhitespace: all
+set list
+set listchars=tab:->,trail:-,extends:>,precedes:<,nbsp:+
+
+" editor.detectIndentation: false — global defaults (editor.tabSize: 2, insertSpaces: false)
+set tabstop=2
+set shiftwidth=2
+set softtabstop=2
+set noexpandtab
+set colorcolumn=76
+
+" colorcolumn draws a full-column tint in Vim (not a VS Code-style 1px line).
+" Keep it subtle via the ColorColumn highlight group; reapply after colorscheme changes.
+if has('termguicolors')
+ " set termguicolors
+endif
+
+function! s:ConfigureColorColumn() abort
+ highlight ColorColumn ctermbg=236 guibg=#2a2a2a cterm=NONE gui=NONE
+endfunction
+
+call s:ConfigureColorColumn()
+autocmd ColorScheme * call s:ConfigureColorColumn()
+
+" files.trimTrailingWhitespace
+autocmd BufWritePre * %s/\s\+$//e
+
+augroup sis_c_cxx
+ autocmd!
+
+ " [c] / [cpp]
+ autocmd FileType c,cpp setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,64,68,72,76
+
+ " [rust]
+ autocmd FileType rs setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=76
+
+ " [cmake]
+ autocmd FileType cmake setlocal noexpandtab tabstop=4 shiftwidth=4 softtabstop=4
+
+ " [shellscript]
+ autocmd FileType sh,bash,zsh setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2 colorcolumn=60,76
+
+ " [bat]
+ autocmd FileType bat,dosbatch setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76
+
+ " [json] / [markdown] / [yaml] / [ruby]
+ autocmd FileType json,markdown,yaml,ruby setlocal expandtab tabstop=2 shiftwidth=2 softtabstop=2
+
+ " [python]
+ autocmd FileType python setlocal expandtab tabstop=4 shiftwidth=4 softtabstop=4 colorcolumn=60,76
+
+ " [toml]
+ autocmd FileType toml setlocal noexpandtab tabstop=2 shiftwidth=2 softtabstop=2
+augroup END
+
diff --git a/CHANGES.md b/CHANGES.md
index e5a7218..86e7b37 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,4 +1,14 @@
-# Diagnosticism.Rust - CHANGES
+# Diagnosticism.Rust - Changes
+
+
+## 0.4.3 - 31st August 2026
+
+* added docs.rs metadata for the optional `test-doomgram` feature;
+* strengthened **ci.yml** with locked stable, feature, documentation, example, formatting, checker, package, and MSRV validation;
+* pinned **scripts/fmt** to nightly-2026-08-08 for reproducible formatting;
+* corrected public rustdoc width and warning issues;
+* aligned **NEWS.md**, **README.md**, and **EXAMPLES.md** release and example documentation;
+* updated the **LICENSE** copyright range through 2026;
## 0.4.2 - 10th July 2026
@@ -81,4 +91,3 @@ All history before this day is moot!
-
diff --git a/Cargo.lock b/Cargo.lock
index 964006f..f954069 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -221,7 +221,7 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "diagnosticism"
-version = "0.4.2"
+version = "0.4.3"
dependencies = [
"base-traits",
"criterion",
diff --git a/Cargo.toml b/Cargo.toml
index 6b17358..91c9413 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@ categories = [
"development-tools::profiling",
]
description = "Miscellaneous discrete and simple diagnostics facilities (for Rust)"
+documentation = "https://docs.rs/diagnosticism"
edition = "2021"
homepage = "https://github.com/synesissoftware/Diagnosticism.Rust"
keywords = [
@@ -26,7 +27,14 @@ name = "diagnosticism"
readme = "README.md"
repository = "https://github.com/synesissoftware/Diagnosticism.Rust"
rust-version = "1.74"
-version = "0.4.2"
+version = "0.4.3"
+
+# docs.rs builds the optional `rand`-backed example path.
+
+[package.metadata.docs.rs]
+features = [
+ "test-doomgram",
+]
# ##########################################################
diff --git a/EXAMPLES.md b/EXAMPLES.md
index 1ae8a18..d2b93ef 100644
--- a/EXAMPLES.md
+++ b/EXAMPLES.md
@@ -1,13 +1,11 @@
-# Diagnosticism.Rust Examples
-
-|Name|Source & Description|Summary|
-|---|---|---|
-|**debug_squeezer**|[examples/debug_squeezer.rs](/examples/debug_squeezer.rs)
[examples/debug_squeezer.md](/examples/debug_squeezer.md)|An example using **Diagnosticism.Rust**'s `DebugSqueezer` type to simplify the `Debug` form of a user-defined type.|
-|**doomgram**|[examples/doomgram.rs](/examples/doomgram.rs)
[examples/doomgram.md](/examples/doomgram.md)|An example using **Diagnosticism.Rust**'s `DoomGram` type to represent the performance of some time-consuming operations, including `to_strip()`, `to_mmm()`, and `to_nmmm()`.|
-|**ellipsis**|[examples/ellipsis.rs](/examples/ellipsis.rs)
[examples/ellipsis.md](/examples/ellipsis.md)|An example using **Diagnosticism.Rust**'s `Ellipsis` type to shorten the `Debug` form of a user-defined type.|
-|**password**|[examples/password.rs](/examples/password.rs)
[examples/password.md](/examples/password.md)|An example using **Diagnosticism.Rust**'s `Password` type to secure the `Debug` form of a user-defined type.|
+# Diagnosticism.Rust - Examples
+| Name | Source & Description | Summary |
+| ------------------ | ---------------------------------------------------------------------------------------------------------- | ------- |
+| **debug_squeezer** | [examples/debug_squeezer.rs](./examples/debug_squeezer.rs)
[examples/debug_squeezer.md](./examples/debug_squeezer.md) | An example using **Diagnosticism.Rust**'s `DebugSqueezer` type to simplify the `Debug` form of a user-defined type. |
+| **doomgram** | [examples/doomgram.rs](./examples/doomgram.rs)
[examples/doomgram.md](./examples/doomgram.md) | An example using **Diagnosticism.Rust**'s `DoomGram` type to represent the performance of some time-consuming operations, including `to_strip()`, `to_mmm()`, and `to_nmmm()`. |
+| **ellipsis** | [examples/ellipsis.rs](./examples/ellipsis.rs)
[examples/ellipsis.md](./examples/ellipsis.md) | An example using **Diagnosticism.Rust**'s `Ellipsis` type to shorten the `Debug` form of a user-defined type. |
+| **password** | [examples/password.rs](./examples/password.rs)
[examples/password.md](./examples/password.md) | An example using **Diagnosticism.Rust**'s `Password` type to secure the `Debug` form of a user-defined type. |
-
diff --git a/LICENSE b/LICENSE
index 54792f3..77ccc67 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
Diagnosticism.Rust - BSD 3-Clause License
-Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
+Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..aa67769
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,20 @@
+# Diagnosticism.Rust - News
+
+| Date | News Item |
+| ---------------- | -------------------------------------------------------------------------------------------------- |
+| 31st August 2026 | [Diagnosticism.Rust 0.4.3](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.4.3) released |
+| 10th July 2026 | [Diagnosticism.Rust 0.4.2](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.4.2) released |
+| 7th July 2026 | [Diagnosticism.Rust 0.4.1](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.4.1) released |
+| 30th June 2026 | [Diagnosticism.Rust 0.4.0](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.4.0) released |
+| 28th June 2026 | [Diagnosticism.Rust 0.3.2](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.3.2) released |
+| 28th June 2026 | [Diagnosticism.Rust 0.3.1](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.3.1) released |
+| 28th June 2026 | [Diagnosticism.Rust 0.3.0](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.3.0) released |
+| 27th June 2026 | [Diagnosticism.Rust 0.2.1](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.2.1) released |
+| 24th July 2025 | [Diagnosticism.Rust 0.2.0](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.2.0) released |
+| 29th March 2025 | [Diagnosticism.Rust 0.1.0](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.1.0) released |
+| 19th December 2024 | [Diagnosticism.Rust 0.0.2](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.0.2) released |
+| 13th September 2024 | [Diagnosticism.Rust 0.0.1](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.0.1) released |
+| 27th August 2024 | [Diagnosticism.Rust 0.0.0](https://github.com/synesissoftware/Diagnosticism.Rust/releases/tag/0.0.0) released |
+
+
+
diff --git a/README.md b/README.md
index b53785c..3e6c495 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ Other facilities (that are not directly related to `Debug`) will be added to the
Reference in **Cargo.toml** in the usual way:
```toml
-diagnosticism = { version = "0" }
+diagnosticism = { version = "0.4" }
```
@@ -84,7 +84,7 @@ The following function is re-exported at the crate root (and defined in the [`di
For example:
-```Rust
+```rust
use diagnosticism::nanoseconds_to_string;
assert_eq!( "123.4ms", nanoseconds_to_string(123_456_789, ""));
@@ -138,7 +138,7 @@ Examples are provided in the ```examples``` directory, along with a markdown des
The example program **doomgram** (in **examples** directory, built with feature `test-doomgram`), illustrates use of `DoomGram` to capture the order-of-magnitude histogram of a large number of small random delays, and to format min/mean/max duration summaries. The program source is:
-```Rust
+```rust
// examples/doomgram.rs : example program illustrating use of `DoomGram`
use diagnosticism::{
@@ -262,7 +262,7 @@ Naturally, in a live system one would not be employing the exploded `Debug` view
In the example program **ellipsis** (in **examples** directory), the following types are defined to illustrate the benefit of using `Ellipsis` to provide concise `Debug` output in terse (i.e. non-`#alternate()`) form:
-```Rust
+```rust
/// Large structure that provides the internals of `Thing`
#[derive(Clone)]
#[derive(Debug)]
@@ -358,4 +358,3 @@ Crates upon which **Diagnosticism.Rust** has development dependencies:
-
diff --git a/examples/debug_squeezer.md b/examples/debug_squeezer.md
index c0a4c60..39969e9 100644
--- a/examples/debug_squeezer.md
+++ b/examples/debug_squeezer.md
@@ -1,4 +1,4 @@
-# Diagnosticism.Rust Example - **debug_squeezer**
+# Diagnosticism.Rust - Example - **debug_squeezer**
## Summary
@@ -7,7 +7,7 @@ An example using **Diagnosticism.Rust**'s `DebugSqueezer` type to simplify the `
## Source
-```Rust
+```rust
// examples/debug_squeezer.rs : example program illustrating use of `DebugSqueezer`
#![allow(dead_code)]
@@ -237,4 +237,3 @@ it gives the output:
-
diff --git a/examples/doomgram.md b/examples/doomgram.md
index 0bdd824..03c4392 100644
--- a/examples/doomgram.md
+++ b/examples/doomgram.md
@@ -1,4 +1,4 @@
-# Diagnosticism.Rust Example - **doomgram**
+# Diagnosticism.Rust - Example - **doomgram**
## Summary
@@ -7,7 +7,7 @@ An example using **Diagnosticism.Rust**'s `DoomGram` type to represent the perfo
## Source
-```Rust
+```rust
// examples/doomgram.rs : example program illustrating use of `DoomGram`
use diagnosticism::{
@@ -135,4 +135,3 @@ The three formatted lines use complementary views of the same data:
-
diff --git a/examples/ellipsis.md b/examples/ellipsis.md
index 6189e0e..e559634 100644
--- a/examples/ellipsis.md
+++ b/examples/ellipsis.md
@@ -1,4 +1,4 @@
-# Diagnosticism.Rust Example - **ellipsis**
+# Diagnosticism.Rust - Example - **ellipsis**
## Summary
@@ -7,7 +7,7 @@ An example using **Diagnosticism.Rust**'s `Ellipsis` type to shorten the `Debug`
## Source
-```Rust
+```rust
// examples/ellipsis.rs : demonstrates use of `Ellipsis`
#![allow(dead_code)]
@@ -192,4 +192,3 @@ Verbose `Debug` form of `thing2`: Thing2 {
-
diff --git a/examples/password.md b/examples/password.md
index 4e53ec6..30f3f72 100644
--- a/examples/password.md
+++ b/examples/password.md
@@ -1,4 +1,4 @@
-# Diagnosticism.Rust Example - **password**
+# Diagnosticism.Rust - Example - **password**
## Summary
@@ -7,7 +7,7 @@ An example using **Diagnosticism.Rust**'s `Password` type to secure the `Debug`
## Source
-```Rust
+```rust
use diagnosticism::Password;
use std::fmt as std_fmt;
@@ -62,4 +62,3 @@ credentials: Credentials {
-
diff --git a/rustfmt.toml b/rustfmt.toml
index 858e1a8..af3938f 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,15 +1,17 @@
# rustfmt.toml for Diagnosticism.Rust
#
-# Requires nightly rustfmt with unstable features enabled, e.g.:
+# Requires pinned nightly rustfmt with unstable features enabled, e.g.:
#
# ./scripts/fmt
#
# Or:
#
-# RUSTFMT="$(rustup which --toolchain nightly rustfmt)" cargo fmt -- --unstable-features
+# cargo +nightly-2026-08-08 fmt -- --unstable-features
#
-# configured for cargo-fmt 1.96.0-nightly
+# The wrapper uses nightly-2026-08-08 by default.
+#
+# configured for cargo-fmt 1.99.0-nightly
# array_width=60 # deprecated
# attr_fn_like_width=70 # deprecated
diff --git a/scripts/fmt b/scripts/fmt
index 13731a1..0a06baf 100755
--- a/scripts/fmt
+++ b/scripts/fmt
@@ -1,10 +1,11 @@
#! /usr/bin/env bash
set -euo pipefail
-RUSTFMT="$(rustup which --toolchain nightly rustfmt 2>/dev/null || true)"
+RUSTFMT_TOOLCHAIN="${RUSTFMT_TOOLCHAIN:-nightly-2026-08-08}"
+RUSTFMT="$(rustup which --toolchain "${RUSTFMT_TOOLCHAIN}" rustfmt 2>/dev/null || true)"
if [[ -z "${RUSTFMT}" ]]; then
- echo "error: nightly rustfmt is required (see rustfmt.toml)" >&2
- echo " rustup component add rustfmt --toolchain nightly" >&2
+ echo "error: ${RUSTFMT_TOOLCHAIN} rustfmt is required (see rustfmt.toml)" >&2
+ echo " rustup toolchain install ${RUSTFMT_TOOLCHAIN} --component rustfmt" >&2
exit 1
fi
diff --git a/src/diagnostics/debug_squeezer.rs b/src/diagnostics/debug_squeezer.rs
index 90d997b..07e4543 100644
--- a/src/diagnostics/debug_squeezer.rs
+++ b/src/diagnostics/debug_squeezer.rs
@@ -3,18 +3,19 @@
use std::fmt as std_fmt;
-/// Structure to assist with restricting the length of [Debug] forms of
-/// fields within a given width.
+/// Structure to assist with restricting the length of
+/// [Debug] forms of fields within a given width.
///
-/// When dealing with complex data structures, the [Debug] form can be
-/// somewhat overwhelming, and unhelpful to debugging/tracing efforts. In
-/// such cases, [DebugSqueezer] can be used to limit the length of the
+/// When dealing with complex data structures, the [Debug]
+/// form can be somewhat overwhelming, and unhelpful to
+/// debugging/tracing efforts. In such cases,
+/// [DebugSqueezer] can be used to limit the length of the
/// output, as in the following example.
///
/// # Examples
///
/// ```
-/// // NOTE: this example way more complex than it needs because 1.88+ requires the documentation code to compile (and I don't yet know how to suppress that)
+/// // NOTE: this example is more complex than necessary because 1.88+ requires the documentation code to compile (and I don't yet know how to suppress that)
/// use diagnosticism::DebugSqueezer;
/// use std::collections::{ BTreeMap, HashMap };
///
diff --git a/src/diagnostics/time_format/nanoseconds_str.rs b/src/diagnostics/time_format/nanoseconds_str.rs
index 4dd6e72..cb6dc7b 100644
--- a/src/diagnostics/time_format/nanoseconds_str.rs
+++ b/src/diagnostics/time_format/nanoseconds_str.rs
@@ -18,8 +18,8 @@ const INLINE_CAP : usize = 15;
/// Compact storage for a formatted nanosecond duration string.
///
/// Obtain values from [`crate::nanoseconds_to_string`]. Most outputs fit in
-/// [`INLINE_CAP`] UTF-8 bytes and are stored inline without heap
-/// allocation. Longer results use a [`String`] variant.
+/// 15 UTF-8 bytes and are stored inline without heap allocation. Longer
+/// results use a [`String`] variant.
#[derive(Clone)]
#[derive(Eq)]
pub struct NanosecondsStr {