Compare commits
7
Commits
d365729b37
..
v1.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad6c32d0c6 | ||
|
|
17574a0d15 | ||
|
|
8aa2b1b9c0 | ||
|
|
6a043e2824 | ||
|
|
81033bb27c | ||
|
|
dfd5d240d2 | ||
|
|
78946578d1 |
+8
-2
@@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
-
|
||||
|
||||
## [1.1.0] - 2026-09-18
|
||||
|
||||
### Added
|
||||
|
||||
- TOML 1.1 support, on by default: date-times and times without seconds
|
||||
(`07:32`, `1979-05-27T07:32`, normalised to full seconds on output), the
|
||||
`\e` and `\xHH` escape sequences, and multi-line inline tables with
|
||||
@@ -35,8 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Changed
|
||||
|
||||
- The compliance suite is [toml-test](https://github.com/toml-lang/toml-test)
|
||||
v2.2.0, run in TOML 1.0 mode. The new corpus holds 205 valid and 474 invalid
|
||||
cases (v1.6.0 had 185 and 371), and it caught the two documents the parser
|
||||
v2.2.0, up from v1.6.0. Its TOML 1.0 corpus holds 205 valid and 474 invalid
|
||||
cases (185 and 371 before), and it caught the two documents the parser
|
||||
still accepted, fixed below.
|
||||
- The flattened struct layout the decoder consults is cached per struct type
|
||||
and shared with the encoder, which now resolves duplicate field keys with
|
||||
|
||||
+6
-4
@@ -53,9 +53,11 @@ just test
|
||||
7. Open a pull request against `development`.
|
||||
|
||||
Releases are cut by merging `development` into `main` and tagging `vX.Y.Z`. The
|
||||
release workflow runs the full gate set including the race detector and
|
||||
publishes the Gitea release with the matching `CHANGELOG.md` section as its
|
||||
notes.
|
||||
release workflow validates the tag, runs the static gates and the test suite
|
||||
with the coverage floor, and publishes the Gitea release with the matching
|
||||
`CHANGELOG.md` section as its notes. The race detector is not in that set: race
|
||||
never runs on a push path, and the local `just gates` raced the tree before the
|
||||
tag was cut.
|
||||
|
||||
## Code style
|
||||
|
||||
@@ -114,7 +116,7 @@ Workflows live in `.gitea/workflows/` and run on the project's own runners:
|
||||
|---|---|---|
|
||||
| Test | push or pull request to `development` | format check, vet, modernisation, build, the test suite with the coverage floor, the toml-test compliance suite |
|
||||
| Race | `workflow_dispatch`, by hand | the suite under the race detector, the same race gate the local `just gates` runs |
|
||||
| Release | a `v*` tag | the same gates plus the race detector, then the Gitea release created from the `CHANGELOG.md` section |
|
||||
| Release | a `v*` tag | tag validation, format, vet, modernisation, build and the test suite with the coverage floor, then the Gitea release created from the `CHANGELOG.md` section; no race detector |
|
||||
|
||||
The local equivalent is `just gates`, which is the same set plus the race
|
||||
detector.
|
||||
|
||||
+11
-4
@@ -7,6 +7,11 @@ package. The snippets assume:
|
||||
import "sourcedock.dev/petrbalvin/interpres"
|
||||
```
|
||||
|
||||
The parser accepts TOML 1.0 documents plus the TOML 1.1 extensions: date-times
|
||||
and times without seconds, the `\e` and `\xHH` escape sequences, and
|
||||
multi-line inline tables with comments and trailing commas. The encoder emits
|
||||
TOML 1.0, which is valid under both versions.
|
||||
|
||||
## Functions
|
||||
|
||||
### `func Parse(data []byte) (map[string]any, error)`
|
||||
@@ -139,8 +144,10 @@ offending key or index, for example `p: interpres: integer 300 overflows uint8`.
|
||||
Offset date-times decode into `time.Time` and keep their offset. The local
|
||||
variants decode into `LocalDateTime`, `LocalDate` and `LocalTime`, whose
|
||||
embedded `time.Time` is normalised to UTC (midnight UTC for a local date, the
|
||||
zero date for a local time). There is no implicit conversion between the offset
|
||||
and local kinds; assigning one to the other is an error.
|
||||
zero date for a local time). Every kind may omit the seconds as of TOML 1.1
|
||||
(`07:32`, `1979-05-27T07:32`); such a value carries a zero second, and the
|
||||
canonical rendering writes full seconds. There is no implicit conversion
|
||||
between the offset and local kinds; assigning one to the other is an error.
|
||||
|
||||
### Arrays of tables
|
||||
|
||||
@@ -362,8 +369,8 @@ out, err := interpres.NewEncoder().UseLiteralMultiline(80).Marshal(cfg)
|
||||
Single-line strings keep the basic form regardless of the threshold, and a
|
||||
threshold of `0` or less disables the option. A string the literal form cannot
|
||||
carry verbatim (an embedded run of three single quotes, a control character
|
||||
other than tab, or a carriage return outside a CRLF pair) also keeps the basic
|
||||
form, so the output always re-parses to the same value.
|
||||
other than tab or newline, or a carriage return outside a CRLF pair) also keeps
|
||||
the basic form, so the output always re-parses to the same value.
|
||||
|
||||
### Cancellation
|
||||
|
||||
|
||||
@@ -99,8 +99,8 @@ sequenceDiagram
|
||||
`Decode`, `DecodeContext`, `Marshal` and `MarshalContext` call allocates its
|
||||
own unexported worker, so a configured type is safe for concurrent use; the
|
||||
setter methods are not, and must finish before the value is shared.
|
||||
- The parser is allocated per `ParseContext` call; nothing is cached between
|
||||
documents.
|
||||
- The parser is allocated per `ParseContext` call; the parser itself caches
|
||||
nothing between documents.
|
||||
- The one piece of shared state is the struct-schema cache in `decode.go`: a
|
||||
`sync.Map` keyed by `reflect.Type`, holding the flattened field layout the
|
||||
decoder and the encoder both consult. A schema is immutable once published,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Benchmarking
|
||||
|
||||
How the performance numbers attached to this project are measured, so that a
|
||||
number in a changelog entry or a release note can be reproduced and trusted.
|
||||
|
||||
## The suite
|
||||
|
||||
The benchmarks live in `bench_test.go`, next to the code they measure:
|
||||
|
||||
| Benchmark | What it measures |
|
||||
|---|---|
|
||||
| `BenchmarkParse` | `Parse` over a representative configuration document |
|
||||
| `BenchmarkMarshal` | `Marshal` of the tree `Parse` produced from the same document |
|
||||
| `BenchmarkStrictDecode` | `Decode` into a struct under `DisallowUnknownFields` |
|
||||
| `BenchmarkParseLong` | `Parse` over a generated document with about 2000 array-of-tables entries |
|
||||
|
||||
## Running
|
||||
|
||||
```sh
|
||||
just bench
|
||||
```
|
||||
|
||||
The recipe runs the suite with `-benchmem -count=5`. Every benchmark uses
|
||||
`b.Loop`, so setup runs outside the timed region, and `ReportAllocs` records
|
||||
allocations per operation. The parse and marshal benchmarks set `SetBytes`, so
|
||||
their results read as input bytes per second.
|
||||
|
||||
## Method
|
||||
|
||||
- An idle machine only: a loaded box times whatever else is running, and the
|
||||
fastest sample can land on the wrong function.
|
||||
- An A/B comparison runs both variants inside one process, in one binary;
|
||||
separate processes of identical binaries differ by more than the effect
|
||||
being measured.
|
||||
- The five counts are compared through their medians, allocations and bytes
|
||||
per operation alongside the times. Differences within 1 to 2 percent are
|
||||
noise; only a difference beyond that is a result.
|
||||
- When timing is hopeless, the allocation and byte counts are the result.
|
||||
|
||||
## Reports
|
||||
|
||||
The repository stores no benchmark reports. A performance claim in
|
||||
`CHANGELOG.md` is measured with the method above on the change that makes it,
|
||||
and the number travels with the claim.
|
||||
+9
-6
@@ -77,7 +77,9 @@ just bench
|
||||
```
|
||||
|
||||
Benchmark on an idle machine, and compare only runs made in one process against
|
||||
each other. The recipe sweeps `./...` five times with `-benchmem`.
|
||||
each other. The recipe sweeps `./...` five times with `-benchmem`. The binding
|
||||
measurement method, and what counts as a result, is in
|
||||
[docs/BENCHMARKING.md](BENCHMARKING.md).
|
||||
|
||||
## Debugging the build
|
||||
|
||||
@@ -97,12 +99,13 @@ pipeline.
|
||||
|---|---|---|
|
||||
| `test.yml` | push or pull request to `development` | format check, vet, modernisation, build, the test suite with the 80 percent coverage floor, then the toml-test compliance suite |
|
||||
| `race.yml` | `workflow_dispatch`, by hand | the suite under the race detector; the same race gate `just gates` runs locally |
|
||||
| `release.yml` | a `v*` tag | the same gates plus the race detector, then the Gitea release from the CHANGELOG section |
|
||||
| `release.yml` | a `v*` tag | tag validation, then format, vet, modernisation, build and the test suite with the coverage floor, then the Gitea release from the CHANGELOG section. No race detector: race never runs on a push path, and the local `just gates` raced the tree before the tag was cut |
|
||||
|
||||
## Releases
|
||||
|
||||
Releases are cut by merging `development` into `main` and tagging `vX.Y.Z`. The
|
||||
tag drives the release workflow: it validates the tag, runs the full gate set
|
||||
including the race detector, extracts the matching `## [X.Y.Z]` section from
|
||||
`CHANGELOG.md`, and publishes the release with that section as its body. A
|
||||
library ships no binaries, so the release carries the notes and nothing else.
|
||||
tag drives the release workflow: it validates the tag, runs the static gates
|
||||
and the test suite with the coverage floor, extracts the matching `## [X.Y.Z]`
|
||||
section from `CHANGELOG.md`, and publishes the release with that section as its
|
||||
body. A library ships no binaries, so the release carries the notes and nothing
|
||||
else.
|
||||
|
||||
Reference in New Issue
Block a user