**Note:** after version [0.3.3 (2021-07-05)](#markdown-header-033-2021-07-05), the [nonymous](https://crates.io/crates/nonymous) and [bore](https://crates.io/crates/bore) crates are versioned separately.
# bore ?.?.? (????-??-??)
- increased **minimum Rust version** from 1.46 to **1.72**
- new option `--trace` to use iterative resolution rather than recursive resolution
- new option `--tcp` to send queries over TCP rather than UDP
- OpenBSD: fixed pledge(2) panic when `--host` and `--show-resolvers` are used together
- unknown OPCODE and RCODE values now show as `OPCODE?x` and `RCODE?x` rather than `<x>`
# nonymous 0.6.0 (2025-10-22)
- all error types now unconditionally implement [core::error::Error](https://doc.rust-lang.org/1.81.0/core/error/trait.Error.html)
- new `rdata` module for strongly typed RDATA with both views and owned types
- supported record types include `A`, `Aaaa`, `Ns`, `Cname`, and `Ptr`
- **breaking change:** most existing RDATA-related types have been renamed; here’s a guide
- `nonymous::view::rdata::Caa` → `nonymous::rdata::view::Caa<InClass>`
- `nonymous::view::rdata::CaaTag` → `nonymous::rdata::view::CaaTag<InClass>`
- `nonymous::view::rdata::CaaValue` → `nonymous::rdata::view::CaaValue<InClass>`
- `nonymous::view::rdata::CompressibleName` has been split; see below
- → `nonymous::rdata::view::Cname<C: GenericClass>`
- → `nonymous::rdata::view::Ns<C: GenericClass>`
- → `nonymous::rdata::view::Ptr<C: GenericClass>`
- `nonymous::view::rdata::InAddress` → `nonymous::rdata::view::A<InClass>`
- `nonymous::view::rdata::InAaaa` → `nonymous::rdata::view::Aaaa<InClass>`
- `nonymous::view::rdata::Malformed` → `nonymous::rdata::view::Malformed<C: GenericClass>`
- `nonymous::view::rdata::Mx` → `nonymous::rdata::view::Mx<InClass>`
- `nonymous::view::rdata::Rdata` → `nonymous::rdata::view::Rdata`
- `nonymous::view::rdata::RdataError` → `nonymous::rdata::view::error::RdataError`
- `nonymous::view::rdata::Soa` → `nonymous::rdata::view::Soa<C: GenericClass>`
- `nonymous::view::rdata::SoaError` → `nonymous::rdata::view::error::SoaError`
- `nonymous::view::rdata::Txt` → `nonymous::rdata::view::Txt<InClass>`
- `nonymous::view::rdata::Unknown` → `nonymous::rdata::view::Unknown<C: GenericClass>`
- `core`
- **breaking change:** the macros `opcode`, `rcode`, `r#type`, and `class` have been removed
- use the associated constants on `Opcode`, `Rcode`, `Type`, and `Class` instead
- **breaking change:** the `NamedConstants` and `NamedRcodes` types have been removed
- these were only necessary for the macros above, and should have been `#[doc(hidden)]`
- **breaking change:** the globals `OPCODE`, `RCODE`, `TYPE`, and `CLASS` have been removed
- these were only necessary for the macros above, and should have been `#[doc(hidden)]`
- `Opcode`, `Rcode`, `Type`, and `Class` now have associated constants that can be used in patterns
- `Rcode::from_basic_extended` can now be called in const contexts
- `Type::new` and `Type::value` can now be called in const contexts
- `Class::new` and `Class::value` can now be called in const contexts
- `Ttl::new` and `Ttl::value` can now be called in const contexts
- `Serial::new` and `Serial::value` can now be called in const contexts
- `emit`
- **breaking change:** removed `MessageError::Name`, `CopyQuestion`, and `BuildQuestion` variants
- `Name` was unused, while `CopyQuestion` and `BuildQuestion` have been merged into `Question`
- new method `MessageBuilder::record_with_name` adds a record with the given `Name`, `Type`, and `Class`
- `view`
- **breaking change:** `Record::try_rdata` has been removed
- use `Record::rdata`, `rdata_as_view`, or `rdata_as_owned` instead
- **breaking change:** `Rdata::CompressibleName` and the `CompressibleName` view have been removed
- use `Rdata::Ns`/`Ns`, `Rdata::Cname`/`Cname`, or `Rdata::Ptr`/`Ptr` instead
- **breaking change:** all RDATA views in `rdata` are now generic over a CLASS
- **breaking change:** all items in `rdata` have moved to `crate::rdata::view`
- **breaking change:** `rdata::InAddress` has been renamed to `crate::rdata::view::A`
- **breaking change:** `rdata::InAaaa` has been renamed to `crate::rdata::view::Aaaa`
- **breaking change:** `rdata::RdataError0` has been removed
- this was an internal implementation detail, and should not have been `pub`
- new trait `ViewToOwned<Owned>` for converting views to one or more owned representations
- new method `Record::rdata_as_view` to get the record’s RDATA as a view type
- new method `Record::rdata_as_owned` to get the record’s RDATA as an owned type
- new method `Name::parent` to get a `Name` view with the name’s first label removed
- new method `Name::truncate` to get a `Name` view with only the last *x* non-null labels
- new method `Name::subdomain_distance` to compute how deep a subdomain is relative to another name
- new method `Unknown::as_bytes` to get the raw bytes of the RDATA as originally decoded
- `Name::labels_with_null` results can now be returned from the same function that created the `Name` view
- this used to fail with `error[E0515]: cannot return value referencing temporary value` or `error[E0515]: cannot return value referencing local variable`, because the lifetime was erroneously bound to that of `&self`
- `Name::labels_not_null` results can now be returned from the same function that created the `Name` view
- this used to fail with `error[E0515]: cannot return value referencing temporary value` or `error[E0515]: cannot return value referencing local variable`, because the lifetime was erroneously bound to that of `&self`
- `name`
- **breaking change:** `NameBuf::view` now returns `NameView<'this>` instead of `&'this NameView<'this>`
- **breaking change:** `NameBuf::labels_with_null` now returns `Labels<'this>` instead of `&'this NameView<'this>`
- this makes the return type consistent with `Name::labels_with_null`
- **breaking change:** `NameBuf::labels_not_null` now returns `Labels<'this>` instead of `&'this NameView<'this>`
- this makes the return type consistent with `Name::labels_not_null`
- **breaking change:** `NameBufError` has been renamed to `OwnedNameError`
- this module is now usable even when both `std` and `alloc` features are disabled
- new types `NameBufMax` and `NameBufN<const N: usize>` for owned names backed by [`ArrayVec`](https://docs.rs/arrayvec/0.7.6/arrayvec/struct.ArrayVec.html)
- new method `NameBuf::parent` to get a `Name` view with the name’s first label removed
- new method `NameBuf::truncate` to get a `Name` view with only the last *x* non-null labels
- new method `NameBuf::subdomain_distance` to compute how deep a subdomain is relative to another name
- `server`
- performance of `response` is now measured with a microbenchmark
# nonymous 0.5.1 (2025-10-20)
- fixed build errors with `--features alloc` but without `--features std`
- CI commit checks now include running nonymous crate tests under `--features alloc`
- CI commit checks now include running all tests under `--features bench`
# nonymous 0.5.0 (2025-10-13)
- increased **minimum Rust version** from 1.72 to **1.81**
- new type `NameBuf` representing an owned name, for use in data structures keyed on names
- `core`
- `Type` now implements `Copy` + `Eq` + `Hash` + `Ord` + `PartialOrd`
- `emit::MessageBuilder`
- new method `question_with_name` adds a question with the given `Name`, `Type`, and `Class`
- `view`
- **breaking change:** `Labels::new` is no longer public
- use `Name::labels_with_null` or `Name::labels_not_null` instead
- **breaking change:** `Questions::new` is no longer public
- use `Message::qd` instead
- **breaking change:** `Records::new` is no longer public
- use `Message::an` or `Message::ns` or `Message::ar` instead
- `view::Name`
- **breaking change:** the `root` method has been renamed to `is_root`
- **breaking change:** the `labels` method has been renamed to `labels_with_null`
- new method `labels_not_null` iterates through the name’s labels, excluding the null label
- new method `is_subdomain_of` checks if the name is a subdomain of (or equal) to another name
- now implements `PartialEq` with `Name`, `[u8]`, `&[u8]`, `[u8; N]`, `&[u8; N]`, `str`, `&str`, `String`, `&String`
- now implements `Ord` + `PartialOrd` + `Eq` with `Name`
- now implements `Hash`
- `view::Label`
- **breaking change:** all `PartialEq` impls now resolve pointers
- **breaking change:** the `null` method has been renamed to `is_null`
- **breaking change:** the `literal` method has been removed in favour of `value`
- new method `value` gets the label’s contents after resolving pointers
- now implements `PartialEq` with `Label`, `&[u8]`, `&[u8; N]`, `str`, `&str`, `String`, `&String`
- now implements `Ord` + `PartialOrd` + `Eq` with `Label`
- now implements `Hash`
- `view::rdata::InAddress`
- new method `to_ipv4_addr` converts the RDATA to an Ipv4Addr
- new method `to_ip_addr` converts the RDATA to an IpAddr
- now implements `Into<Ipv4Addr>` and `Into<IpAddr>`
- `view::rdata::InAaaa`
- new method `to_ipv6_addr` converts the RDATA to an Ipv6Addr
- new method `to_ip_addr` converts the RDATA to an IpAddr
- now implements `Into<Ipv6Addr>` and `Into<IpAddr>`
# nonymous 0.4.0 (2025-10-11)
- increased **minimum Rust version** from 1.46 to **1.72**
- **`view` and `fmt` (formerly `zone`) are now fuzzed and guaranteed to be panic-free**
- new `{opcode,rcode,type,class}` macros to get values by name at compile time
- new `server::response` helper function to start building a response to the given query
- new `MAX_SUPPORTED_EDNS_VERSION` constant representing supported EDNS version (0)
- `view::Extension` returns `UnimplementedVersion` error when VERSION exceeds this value
- new example `dynrdns` that dynamically generates responses to reverse DNS queries
- `core`
- new `core::{Opcode,Rcode}` types representing OPCODE and (extended) RCODE
- new `core::Serial` type representing SOA SERIAL with serial number arithmetic (RFC 1982)
- numeric types in `core` are now returned directly by view methods (see breaking changes)
- `emit`
- **improved runtime performance by over 10x** when using `ArrayVec`
- new `emit::MessageBuilder::{opcode,rcode}` methods to set OPCODE and (extended) RCODE
- new `emit::MessageBuilder::copy_question` methods to copy the given `view::Question`
- new `emit::ExtensionBuilder::{udp,version,do}` methods to set UDP payload size, VERSION, and DO flag
- new `emit::Sink::new` method to create a sink without an explicit limit
- new `emit::Sink::capacity_limit` function to calculate the limit imposed by the given buffer
- new `emit::Sink::response_limit` function to calculate the limit for a buffer, protocol, and query
- `emit::MessageBuilder::extension` now implies `MessageBuilder::into_ar` if needed
- builder docs now clearly categorise state machine methods as down/step/up transitions
- added ArrayVec-based versions of builder benches
- squelched new warning about unused attribute on macro invocation
- squelched new warning about renamed private_intra_doc_links lint
- `view`
- new `view::Message::udp_limit` method returning the requestor’s UDP payload size
- `View::view` now accepts values of any `RangeBounds<usize>` type, such as `..`
- `view::Label` now implements `PartialEq` with `[u8]` and `[u8; N]`
- `view::Label::literal` now returns lifetime of source (`'s`) rather than lifetime of `&self`
- `Plain` and `Pretty` formatters now implement `Debug`, not just `Display`
- `OPCODE`
- added “DSO”, number 6
- fixed incorrect numbering of “Notify” and “Update” as 3 and 4 (now 4 and 5)
- `RCODE`
- added “DSOTYPENI”, number 11
- added “BADCOOKIE”, number 23
- fixed incorrect naming of 6 as “BADTYPE” (now “BADTIME”)
## Breaking changes
- **note: there are a great deal of breaking changes, but we have tried to list as many as possible below**
- `emit::Buffer` has been migrated from [arrayvec](https://crates.io/crates/arrayvec) 0.5 to 0.7
- to migrate, replace the following
- `ArrayVec::<[u8; N]>` → `ArrayVec::<u8, N>`
- `<A: Array<Item = u8>> ArrayVec::<A>` → `<const N: usize> ArrayVec::<u8, N>`
- `const` has been merged into `core` and reworked to...
- rename `Names::{name,number}` to `NamedConstants::to_{name,number}` for clarity
- give `RCODE` explicit support for the context-sensitive value 16 (BADVERS or BADSIG)
- use `RCODE::to_name_opt` or `RCODE::to_name_tsig` instead of `to_name`
- `emit` has been reworked to...
- borrow rather than own its output buffers
- `Builder` and its concrete types are now marked `#[must_use]`
- to migrate, declare the buffer separately, then pass it with `&mut` to `Sink` and the builder chain
- ensure that questions and records contain exactly one QNAME and NAME respectively
- `NameError` has two new variants, `Question` and `Record`
- to migrate `NameBuilder` usage in question QNAME, replace `.finish()?.finish(...)?` with `.finish_question(...)?`
- to migrate `NameBuilder` usage in record NAME, replace `.finish()?.try_into_data()?` with `.try_into_rdata()?`
- to migrate `NameBuilder` usage in record RDATA, replace `.finish()?` with `.return_to_rdata()?`
- ensure that extended RCODE values are correctly split between message header and EDNS OPT RR
- `MessageBuilder::finish` returns `ExtensionRequired` error with non-zero extended part but no EDNS OPT RR
- to migrate, replace `.finish()` with `.finish()?`
- use the consistent term “step” for state machine states
- `message::QuestionSection` was renamed to `QuestionStep`
- `message::RecordSection` was renamed to `RecordStep`
- `view` has been reworked to...
- include the EDNS version (if any) in errors for malformed messages
- `MessageError` is now a struct wrapping the old enum, which is now `MessageErrorKind`
- use the new `core::{Opcode,Rcode,Serial}` types for OPCODE, (extended) RCODE, and SOA SERIAL
- `Header::opcode` now returns `core::Opcode`
- `Message::rcode` now returns `core::Rcode`
- `Soa::serial` now returns `core::Serial`
- use the `core::Ttl` type more consistently
- `Record::ttl` now returns `core::Ttl`
- `Soa::{refresh,retry,expire,minimum}` now return `core::Ttl`
- remove the `Type` and `Class` views in favour of `core::{Type,Class}`
- `Question::qtype` and `Record::r#type` now return `core::Type`
- `Question::qclass` and `Record::class` now return `core::Class`
- make it easier to distinguish the null label from other labels
- `Label::literal` now returns `None` for the null label
- `zone` has been renamed to `fmt`
# [bore 0.4.1](https://codeberg.org/shuppy/nonymous/src/tag/bore-0.4.1/bore) (2021-11-28)
- fixed bug where positional argument `@<host>` was ignored
# [bore 0.4.0](https://codeberg.org/shuppy/nonymous/src/tag/bore-0.4.0/bore) (2021-11-28)
- new positional argument `@<host>` as a shorthand for `--host <host>`
- positional arguments can now be given in any order, including `<type>` before `<name>`
- added hint to improve error message when `-x` (`--reverse`) given without name
## Breaking changes
- positional argument `<name>`
- now requires at least one dot or colon, e.g. use `mx.` to query the top-level domain “mx”
- now requires leading `@` to be escaped, e.g. use `\@.example` to query the name `@.example`
## Project changes
- CI migrated from Bitbucket Pipelines to Bamboo ([bamboo.daz.cat](https://bamboo.daz.cat))
- [commit checks](https://bamboo.daz.cat/browse/NO-COMM) now include OpenBSD (x64) and Windows (x64 + x86) in addition to Linux x64 (MSRV + nightly)
- [test coverage](https://bamboo.daz.cat/browse/NO-TCOV) is now being calculated again, with cargo-tarpaulin 0.18.0 instead of 0.9.3
# [0.3.3](https://codeberg.org/shuppy/nonymous/src/tag/0.3.3) (2021-07-05)
## bore
- Windows: use ENABLE_VIRTUAL_TERMINAL_PROCESSING to ensure that `--color` works natively
- Unix: fixed a bug where SIGPIPE might cause a visible panic (especially on macOS)
- OpenBSD: fixed pledge(2) promises for `--show-resolvers` (was broken in 0.3.0)
- added scripts to check for regressions on non-CI platforms (Windows + macOS + OpenBSD)
# [0.3.2](https://codeberg.org/shuppy/nonymous/src/tag/0.3.2) (2021-07-05)
## bore
- OpenBSD: fixed pledge(2) promises for `--decode` (regression in 0.3.1)
# [0.3.1](https://codeberg.org/shuppy/nonymous/src/tag/0.3.1) (2021-07-05)
## bore
- fixed bug where failure to gather default resolvers would break `--decode`
- this is necessary for a useful installCheckPhase in the Nix derivation
- note that failure otherwise remains fatal unless `--host` is given
# [0.3.0](https://codeberg.org/shuppy/nonymous/src/tag/0.3.0) (2021-07-04)
- nonymous-scoop was removed (0.0.2 was the last version)
- please install [bore](https://crates.io/crates/bore) instead
- nonymous + bore: increased minimum Rust version from 1.39 to 1.46
- nonymous + bore: the “strict” package feature has been removed in favour of `#[cfg(ci_)]`
- use `RUSTFLAGS='--cfg ci'` instead of `--feature strict` to build these crates with `#[deny(warnings)]`
- nonymous + bore: `Label` now displays symbols other than `-_;` and space in the more compact `\;` format
## Conformance
- nonymous + bore: IPv6 addresses are now displayed in canonical format ([RFC 5952](https://datatracker.ietf.org/doc/html/rfc5952))
- nonymous + bore: `NameBuilder::labels` and <host> argument now parse names in zone format (supporting escapes)
## nonymous
- removed all hard dependencies on `alloc` and `std` outside of tests
- `Record::{rdata, try_rdata}` now return non-exhaustive enum instead of `Box<dyn>`
- `Type` and `Class` name/value maps are now backed by compile-time sorted arrays
- all tests except one now run in `#![no_std]` without `alloc` (but not benches)
- all `alloc`/`std`-dependent features in dependencies are now disabled or feature-gated
- CI runs a new test (nonono) that will fail to compile given any future regressions
- fixed broken links in rustdoc for `view` iterator types and some `MessageBuilder` methods
## bore
- new option `--show-resolvers` lists resolver hosts and ports that would be used
- new option `--reverse` (`-x`) makes a reverse DNS query (in-addr.arpa. or ip6.arpa.)
- new option `--color` highlights output to draw your attention to important parts
- new option `--man` views detailed docs compiled into the binary
- crate now uses [pledge(2)](https://man.openbsd.org/OpenBSD-6.3/pledge.2) + [unveil(2)](https://man.openbsd.org/OpenBSD-6.4/unveil.2) for security on OpenBSD
- crate now gathers system resolvers with GetAdaptersAddresses on Windows
- crate now gathers system resolvers with dns_configuration_copy on macOS
- crate now uses [eyre](https://crates.io/crates/eyre) for error reporting (was [failure](https://crates.io/crates/failure))
- crate now correctly reports nested errors with full source chains (causes)
- crate now has meaningful error messages on every fallible code path
- crate can no longer be consumed as a library (was a hack for nonymous-scoop)
## Breaking changes
- **note: there are a great deal of breaking changes, but we have tried to list as many as possible below**
- error handling has been reworked
- all error types now implement std::error::Error where available (was [failure](https://crates.io/crates/failure)::Error)
- note: without the “std” feature, `view::rdata::RdataError` discards original error for now
- all error messages have been rewritten and improved with the help of [displaydoc](https://crates.io/crates/displaydoc)
- `emit::BoundsError` is now an enum with three tuple variants (was unit struct)
- `emit::NameError` new variants: DecimalEscapeRange, DecimalEscapeSyntax, UnfinishedEscape, UnfinishedLabel
- `emit` has been reworked and simplified to a new panic-free API with fallible packet writing
- `Sink` now replaces `RootBuilder` and `RootBuildee` as the top of the builder hierarchy
- eliminated the distinction between `Buildee` (no `Sink`) and `Builder` (buildee plus sink)
- `Sink::new` has been split into `TryFrom::from` (no limit) and `Sink::with_limit` (limit: u16)
- `Sink` growth is now fallible with a new `GrowError` type (previously panicking)
- `Sink` creation is now fallible with a new `SinkError` type (previously panicking)
- `NewBuilder::new` is now fallible in the same way as `Sink` creation
- `view`: zone-like view formatting has been moved to `crate::zone`
- to migrate, wrap view objects in a `Plain`, then `Display` as usual
- `NameBuilder::labels` now requires trailing dot and rejects lone dot (bore is unaffected)
- `NameBuilder::labels` now takes a `&[u8]` rather than a `&str`
- for the old behaviour, pass `str` arguments through `str::as_bytes`
# [0.0.2](https://codeberg.org/shuppy/nonymous/src/tag/0.0.2) (2021-01-03)
## Breaking changes
- scoop(1) ([nonymous-scoop](https://crates.io/crates/nonymous-scoop)) was renamed to bore(1) ([bore](https://crates.io/crates/bore))
- you can still install nonymous-scoop if you want scoop(1), but this version will be the last
- nonymous: increased minimum Rust version from 1.37 to 1.39
- nonymous: `crate::emit` was rewritten from scratch (pull request #2)
- for an example of how to migrate, see bore/src/main.rs
- API is now zero-copy, `#![no_std]` compatible, and harder to misuse
- you can pass a packet size limit to `Sink`, for UDP and similar use cases
- nonymous: `crate::NeverError` was removed (but it was only used by the old `crate::emit`)
- nonymous: `crate::emit::{Type, TypeError}` were moved to `crate::core::{Type, TypeFromStrError}`
- nonymous: `crate::emit::{Class, ClassError}` were moved to `crate::core::{Class, ClassFromStrError}`
- nonymous: `crate::emit::{Ttl, TtlError}` were moved to `crate::core::{Ttl, TtlFromStrError}`
- nonymous: `NameBuilder::label` (moved from `Name::parent`) now takes a `&[u8]` rather than a `&str`
- for the old behaviour, pass `str` arguments through `str::as_bytes`
## Issues
- fixed bug where RecordError::Bounds display message is incomplete (issue #1)
- added code coverage checks, currently disabled by default due to [a CI problem] (issue #2)
- fixed bug where `nonymous::emit::Name` doesn’t accept arbitrary binary labels (issue #3)
[a CI problem]: https://twitter.com/dazabani/status/1201527372740096000
## bore
- new options: `--encode` + `--decode` + `--dump` + `--load`
- crate is now built against Rust 1.39.0 on CI (was nightly-2019-09-13)
- crate now uses the stable Tokio 0.2 API (was 0.2.0-alpha.4)
# [0.0.1](https://codeberg.org/shuppy/nonymous/src/tag/0.0.1) (2019-09-29)
## Breaking changes
- `nonymous::emit::Record::new` is now fallible, failing when the given `rdata` is too long
- `nonymous::view::ExtensionError` removes the unused `Bounds` variant
- `nonymous::view::Len` was removed
- for the old behaviour, replace `Len::len` calls with `View::len` calls
- `nonymous::view::Record::rdata` is now infallible, returning `Malformed` as a last resort
- for the old behaviour, rename `Record::rdata` calls to `Record::try_rdata`
- `nonymous::view::Record::rdata_offset` was removed
- for the old behaviour, replace calls with `Record::rdata_range(x).start`
- `nonymous::view::View` adds a required `fn len`
## nonymous
- crate is now `#![forbid(unsafe_code)]`
- `crate::view` error types now have meaningful error messages
- crate moves [assert_matches] from `[dependencies]` to `[dev-dependencies]`
- crate cleans up unwrap calls outside of tests and benches
- crate cleans up FIXME sites for `as {integer}` casts
## nonymous-scoop
- crate is now `#![forbid(unsafe_code)]`
- scoop(1) now uses `Display` to report fatal errors and their causes
- crate moves [assert_matches] from `[dependencies]` to `[dev-dependencies]`
- crate bumps tokio to 0.2.0-alpha.4 explicitly
- crate cleans up unwrap calls outside of tests and benches
[assert_matches]: https://crates.io/crates/assert_matches
# [0.0.0](https://codeberg.org/shuppy/nonymous/src/tag/0.0.0) (2019-09-16)
## nonymous
- initial release with view and emit modules
## nonymous-scoop
- initial release with resolv.conf(5) support