'Label' was accidentally including the length octet in its display
output. Now, an explicit 'contents()' method has been added which does
not include the length octet, and it is used for the display impl.
In the future, an 'UnsizedClone' trait might be a better fit (with
blanket impls for things like 'Box'), but some 'Clone' impls will
probably always be necessary.
'SecureRandom' is only implemented by ring's 'SystemRandom' type, which
is thread-safe. However, this property was lost when the trait object
was used. Re-introducing these bounds makes 'KeyPair' thread-safe.
- Automatically determine the MSRV.
- Rebuild 'main' every week to catch environmental changes.
- Run Clippy in a dedicated job to be more parallel.
- Only run it on Ubuntu.
- Introduce caching of '~/.cargo' and '/target'.
- Only save it on 'main', but restore it in all other jobs.
- Preserve OpenSSL-excluding behavior for Windows.
This language feature is deprecated, but the lint for it is not
enabled by default. Enabling the lint and fixing all occurrences also
resolves some new Clippy lints. This does not affect the API or
behaviour of the code in any way.
'domain::new' is an umbrella project for rewriting large parts of 'domain'.
The goal is to take advantage of new advancements (often in the Rust language
itself) in order to improve the ergonomics and the efficiency of the API.
This set of commits added 'new::base', 'new::rdata', and 'new::edns'. These
provide a simple and efficient _mid-level_ API for basic DNS work. They are
based on the existing 'base', 'rdata', and 'base::opt' modules, but provide a
different API in many places.
'new::base::wire' is a stand-alone module for efficient (de)serialization for
arbitrary byte formats. It pairs with 'utils::dst', which provides important
utility functions for dynamically sized types in Rust. 'domain-macros' adds
derive macros for the traits from these modules.
The added modules will continue to be enhanced. There is still functionality
waiting to be added (e.g. operations on domain names) that were not critical
but are important for replicating the complete functionality of the existing
'base' module. Likewise, support for more record data types will be added.
In the future, more modules will be ported over to 'new', and eventually 'new'
will replace the existing APIs altogether. 'new::base' will be the foundation
for those modules, and is already usable as-is for lower-level DNS work.
Full commit history:
* Add module 'new_base'
* [new_base] Add module 'name'
* [new_base/name] Define labels
* [new_base] Add module 'message'
* [new_base/name/label] Use 'zerocopy'
* [new_base] Add module 'parse'
* [new_base/name] Add module 'parsed'
* [new_base] Add module 'question'
* Add module 'record'
* [new_base] Add high-level parsing traits
* [new_base/name] Add module 'reversed'
* [new_base/name/reversed] Implement complex parsing
* [new_base/name] Add some 'Debug' impls
* [new_base] Implement parsing for 'Question' and 'Record'
* [new_base/parse] Update with new question/record types
* [new_base/name] Fix bugs (thanks clippy)
* [new_base] Make 'record' a private module
* Use 'zerocopy' 0.8.5 or newer
It implements 'Hash' for the provided integer types.
* Add module 'new_rdata' with most RFC 1035 types
* [new_base] Define 'CharStr'
* [new_rdata] Define 'Hinfo'
* [new_rdata/rfc1035] Implement (basic) 'Txt' records
* [new_rdata/rfc1035] Add 'ParseFrom' impls where missing
* [new_rdata/rfc1035] Don't use 'zerocopy' around names
* [new_base/charstr] Impl 'Eq' and 'Debug'
* [new_base] Add module 'serial'
* [new_base] Add module 'build'
* [new_base/build] Add a 'Builder' for DNS messages
* [new_base/name/reversed] Impl building traits
* [new_base/build] Add convenience impls for '[u8]'
* [new_base/question] Impl building traits
* [new_base/record] Support building and overhaul parsing
* [new_base/charstr] Support building
* [new_rdata/rfc1035] Impl building traits
* [build/builder] Improve unclear documentation
* [new_rdata/rfc1035] gate 'Ipv4Addr' behind 'std'
* [new_rdata/rfc1035] Gate more things under 'std'
* [new_base/build/builder] Remove unnecessary explicit lifetime in impl
* [new_rdata/rfc1035] Support 'Display' outside 'std'
* [new_rdata] Inline 'rfc1035' and support 'rfc3596'
* [new_rdata] Rename submodules with more intuitive names
* [new_base] Set up basic EDNS support
Instead of 'new_base::opt', EDNS is now granted its own top-level
module. This matches up well with 'crate::tsig'.
* [new_base/record] Add trait 'ParseRecordData'
* [new_base/parse] Make 'Split*' imply 'Parse*'
* [new_base/record] Add a default for 'parse_record_data()'
* [new_rdata/basic] Use more capitalization in record data type names
* [new_rdata] Define enum 'RecordData'
* [new_rdata/basic] Elide lifetime as per Clippy
* [new_rdata] Elide lifetimes as per clippy
* Set up a 'domain-macros' crate
'domain-macros' will provide:
- 'derive' macros for DNS-specific (zero-copy) serialization
- 'derive' macros for building and parsing specialized DNS messages
- 'derive' macros for composing clients and servers
The first use case will replace 'zerocopy'.
* [new_base/parse] Define 'ParseBytesByRef' for deriving
* [macros] Define 'ImplSkeleton' and prepare a basic derive
* Expand 'ParseBytesByRef' and largely finish its derive macro
* [macros] Add module 'repr' for checking for stable layouts
* [new_base/parse] Implement '*BytesByRef' for '[T; N]'
* [macros] Add a derive macro for 'SplitBytesByRef'
'ParseBytesByRef' now requires all implementing types to be unaligned.
Otherwise, padding bytes wouldn't be accounted for properly, e.g. in
// Has alignment of largest field: 8 bytes
#[repr(C)]
pub struct Foo {
a: u8,
// 7 bytes of padding here
b: u64,
}
The 'derive' can't tell how much padding to use, so it would parse a
'[u8; 9]' as a valid instance of 'Foo'. Every 'repr(C)' would have to
use 'repr(packed)' too.
* Use '{Parse,Split}BytesByRef' instead of 'zerocopy'
* Rename '{Split,Parse}From' to '{Split,Parse}Bytes'
* [macros] Add derives for '{Split,Parse}Bytes'
* [macros] Factor out 'new_lifetime()'
* Use parsing trait derives across the 'new_*' codebase
* Impl and use derives for 'AsBytes' and 'BuildBytes'
* [macros] Minor fixes as per clippy
* [new_base/parse] Fix missing doc link
* [macros] Fix no-fields output for 'ParseBytes'
* [new_base/serial] Support measuring unix time
* [new_edns] Implement DNS cookie support
* [macros] Factor out struct inspection and building
* [new_edns] Impl RFC 8914 "Extended DNS errors"
* [new_edns] Impl parsing/building for 'EdnsOption'
* [new_base] Add module 'wire' to replace 'zerocopy'
This ended up collecting a lot of small changes as I tried to get
things to compile.
- All the bytes parsing/building traits have been moved to 'wire'.
- The 'wire::ints' module replaces 'U16' and 'U32' from 'zerocopy'.
- '{Parse,Split}BytesByRef' now support parsing from '&mut'.
- Every derive macro is documented under a re-export in 'wire'.
The remaining contents of 'new_base::{build, parse}' might get moved
into a shared 'message' module at some point. We'll see.
* [new_base] Correct docs for build traits
* [macros] Avoid glob imports where possible
* [macros/lib.rs] Remove the last 'syn' glob import
* [new_base/parse] Rework '{Parse,Split}FromMessage'
Instead of passing the input selection as a range for parsing, the
whole message is cut (using 'Message::slice_to()') and only the start
is indicated. This ensures that we never cross the end of the range.
It also implicitly dictates that compressed names are not allowed to
reference future locations in messages.
In addition, both the parsing traits now use offsets into the message
_contents_ rather than the whole message. They can avoid 'as_bytes()'
everywhere and have better guarantees of success. It also ensures the
message header can never be selected for parsing.
* [new_base/name] Delete unused 'parsed.rs'
* [new_base/wire] Define 'SizePrefixed'
* [new_rdata/edns] Implement iteration and formatting
* [new_base/build] Use 'BuildResult' to ensure 'commit()' is called
This has already caught a missing commit (for 'Question').
* [new_base/build] Define 'MessageBuilder'
* [new_base/message] Add 'as_bytes_mut()' and 'slice_to_mut()'
* [new_base/name] Add 'UnparsedName'
* [new_base/message] Impl 'as_array()' for 'SectionCounts'
* [new_base/build] Define 'RecordBuilder'
* [new_base/name] Accept Clippy simplifications
* [new_base/build/record] Track record data size
* [new_base/parse] Remove 'ParseMessage' etc.
These interfaces need to be redesigned to be more specific to important
use cases.
* [new_base/build] Document 'BuildCommitted' thoroughly
* [new_base/build/builder] Rewrite with a lot of documentation
* [new_base/build] Add module documentation
* [new_base/parse] Add a bit of module documentation
* [new_base/parse] Add missing doc links
* [new_base/wire/ints] Make 'set()' non-const
* [new_base/wire/parse] Fix documentation typo
See: <https://github.com/NLnetLabs/domain/pull/474#discussion_r1925023434>
* [new_edns/cookie] Rename 'CookieRequest' to 'ClientCookie'
Also fixes typo in field name 'reversed' ('reserved') of 'Cookie'.
See: <https://github.com/NLnetLabs/domain/pull/474#discussion_r1925050929>
See: <https://github.com/NLnetLabs/domain/pull/474#discussion_r1925115123>
* [new_base/parse] Refactor '{Parse,Split}FromMessage'
- The traits have been renamed to '{Parse,Split}MessageBytes' for
consistency with '{Parse,Split}Bytes'.
- The traits now consume 'message.contents' instead of the whole
'message', allowing them to be used in more contexts (e.g. the
upcoming overhauled builder types).
* [new_base/build] Overhaul message building
- 'BuilderContext' now tracks the last question / record in a message,
allowing its building to be recovered in the future (WIP).
- 'MessageBuilder' inlines the 'Builder' and just stores a mutable
reference to a 'Message' for simplicity.
- 'Builder' no longer gives access to the message header, and uses
'&UnsafeCell<[u8]>' to represent the message contents.
* [new_base/build/message] Add resumption methods
* [new_base/build] Test 'MessageBuilder' and fix some bugs
* [new_base/build] Track section counts while building
* [new_base/wire/parse] Fix miscount of doc test
* [new_base/wire/parse] Support parsing into arrays
* [new_base/build] Accept clippy suggestions
* [new_rdata] Use 'core::net::Ipv4Addr'
* [new_rdata] Document format in 'Txt'
See: <https://github.com/NLnetLabs/domain/pull/474#discussion_r1925085085>
* [new_base/name] Add 'LabelBuf' and support building on 'Label'
* [new_base/name] Add mutable access from 'RevNameBuf'
* [new_base] Simply parse impls using 'split_*()'
I have taken care to preserve explicit parse impls for wrapper types
like 'SizePrefixed', and a few cases where performance could matter.
* [new_base/name] Define the standard 'Name' type
* [new_base/name] Add deconstruction methods for 'UnparsedName'
* Remove accidental trailing whitespace
* [new_base] Import various fixes from 'new-net-server'
* [new_edns] Remove debug 'println'
* [new_base] Add some basic unit tests
* [new_rdata/basic] Refactor into submodules
* [new_rdata] Impl equality for 'RecordData'
* [new_rdata] Add 'map_name(s)_by_ref()'
* [new_base/wire] Make 'SizePrefixed' generic over size type
Some DNSSEC types use single-byte prefixed data, for which I'd still
like to make use of 'SizePrefixed' to avoid boilerplate.
* [new_rdata] Implement stubs of DNSSEC record types
* [src/new_base/size_prefixed] Fix clippy lint
* [new_rdata/dnssec] Export helper types
* [new_rdata] Avoid '{BuildInto,ParseFrom}Message' where possible
* [new_rdata] Incorporate DNSSEC record types
* [new_base/name/absolute] Add 'NameBuf'
This will be used for zonefile parsing.
* [new_base] Add 'bumpalo' and impl 'clone_to_bump()'
'bumpalo' is useful for allocating unsized data types like record data.
It is currently used in the 'new-zonefile' branch as a buffer space for
records to be parsed into. 'clone_to_bump()' is necessary in order to
deep-copy record data into a new bump allocator.
* [utils] Add 'UnsizedClone' and 'CloneFrom'
These are important for improving DST ergonomics; they make it much
easier to copy around unsized types, which 'domain' now has many of.
* Define and use a derive macro for 'UnsizedClone'
* [utils] Define 'clone_to_bump()' for integrating with 'bumpalo'
* Replace most 'clone_to_bump()'s via 'UnsizedClone'
* Fix broken doc links
* [new_base/name/absolute] Impl 'Ord' for 'Name'
* [new_base/message] Impl 'UnsizedClone' for 'Message'
* [new_base/name] Introduce 'CanonicalName'
'CanonicalName' introduces important operations for DNSSEC. It is
only implemented by 'Name' (not 'RevName') because 'RevName' cannot
implement it efficiently (users should prefer 'RecordData<&Name>').
* Implement DNSSEC canonical ordering and building
* [new_base/record] Fix broken doc link
* [new_base] Add module 'compat'
* [new_rdata/edns] Add 'Opt::EMPTY'
* [new_base/build] Make 'MessageBuilder::finish()' return a mutable ref
* [new_base/build] Add 'must_use' in a few vital places
This helps prevent users from accidentally forgetting to commit the
components of the message they're building.
* [new_base/compat] Remove hard-to-port re-exports
* [new_edns] Add 'EdnsRecord::clone_to_bump()'
* [new_base/message] Make 'HeaderFlags' setters modify in place
* [new_base/build] Fix broken doc test
* [new_base/name] impl 'FromStr' for '*Buf' types
* [new_base/wire] Clarify bits of doc test
* [new_base/wire] Polish internal code
- Added some documentation and reasoning for the primitive types (U16
etc.) provided in this module.
- Added documentation about the bounds on 'S' for 'SizePrefixed'.
- Improved the safety message for 'SizePrefixed'.
* [new_base] Rephrase 'byte string' -> 'byte sequence'
- Along the way, the documentation for the parsing traits has been
improved significantly.
* [new_base/message] Rename 'slice_to()' to 'truncate()'
* [new_base/message] Rename methods in 'HeaderFlags'
* [utils] Simplify 'UnsizedClone' usage
* [new_base/message] Fix wording of 'additional' in 'SectionCounts'
* [new_base/serial] Use a custom method instead of 'Add'
Also updates it to disallow negative additions, as per the RFC.
* [new_base/name/label] Allow wildcard labels in 'FromStr'
* [new_base] Add more build/parse impls for 'std' wrappers
* [new_rdata] Store 'A' and 'Aaaa' inline in 'RecordData'
* [new_rdata] Expose 'dnssec::TypeBitmaps' publicly
* [new_rdata/ipv6] Use 'core::net' instead of 'std::net'
* [new_base/question] Adjust docs for 'QType' constants
* [new_base] Add 'missing_doc' lints
* [new_base/message] Thoroughly document 'HeaderFlags'
* [new_base/name/unparsed] Allow 'UnparsedName' to be parsed from byte sequences
* [new_base/record] Add 'Record::map_name()'
* [new_base/record] Remove 'UnparsedRecord'
It's left over from experiments with high-level message parsing.
* [new_base/record] Split 'ParseRecordDataBytes' from 'ParseRecordData'
This makes it possible to use 'RecordData::parse_record_data_bytes()'
with name types that don't support decompression.
* [new_rdata] Add 'BoxedRecordData'
'BoxedRecordData' fills a missing bit of functionality, for long-term
storage of record data. 'RecordData' itself wasn't suitable for this
because of its lifetime parameter.
* [src/utils] impl 'CloneFrom' for 'Rc' and 'Arc'
Unlike 'Box', these types can't be constructed from a 'Layout'. We
have to convince them to allocate in the right layout, which is hard
because we then need a compile-time known alignment. I've added an
alignment type to 'UnsizedClone' for this.
* [new_base/question] Remove 'UnparsedQuestion'
* [new_rdata/basic/a] Document thoroughly
* [utils/mod.rs] Import derive macro for 'UnsizedClone'
* [new_rdata/basic/mx] Freshen up and document thoroughly
* [new_rdata/basic/ns] Freshen up and document thoroughly
* [new_rdata/basic/ptr] Freshen up and document thoroughly
* [new_rdata/basic/ns] Adjust docs to specify authority
* [new_rdata/basic/soa] Freshen up and document thoroughly
* [utils::UnsizedClone] Fix doc test
* [utils] Refactor 'UnsizedClone' -> 'dst::UnsizedCopy'
* Refactor '{Parse,Split}BytesByRef' to '{Parse,Split}BytesZC'
- '*_by_ref()' methods have been renamed to '_zc()'.
- '*_by_mut()' methods are no longer offered; these will be offered
through a separate trait, that will also support 'Box'.
- A new bound on 'UnsizedCopy' has been added, which provides
'ptr_with_address()' (now 'ptr_with_addr()').
* [new_base/parse/wire] Add 'ParseBytesInPlace'
* [new_rdata/basic/txt] Clean up and document thoroughly
- Also introduces 'CharStrBuf' to simplify the building of 'Txt's.
* [new_rdata/basic/cname] Clean up and document thoroughly
* [new_rdata/basic/txt] Remove 'parse_boxed_bytes()'
This functionality is already provided by
'ParseBytesZC::parse_bytes_in()', with exactly the same signature.
* [new_rdata] Remove 'Wks'
The existing 'base' module doesn't support it either.
* [new_rdata/basic/hinfo] Clean up and document thoroughly
* [new_base] Minor bugfixes (mainly documentation)
* [new_base] Update doc tests to match new APIs
* [new_rdata/ipv6] Clean up and document thoroughly
* [new_base/wire/size_prefixed] Fix incorrect formatting
* [new_base/wire/build] Add 'BuildBytes::built_bytes_size()'
This will make it much easier to allocate buffers for building into.
It is still preferable to over-allocate by a small amount rather than
to get the exact size.
Note that using 'built_bytes_size()' to reserve space in a 'Vec' is
almost certainly more efficient than incrementally appending to it, as
heap allocations are going to be more expensive than traversing any
object to calculate its serialization size.
* [new_rdata/edns] Clean up and document thoroughly
- 'Opt' will now validate the option structure during parsing, acting
like '[UnparsedEdnsOption]'.
- Introduced 'UnparsedEdnsOption', similar to 'UnparsedRecordData'.
'Opt::options()' will return 'UnparsedEdnsOption' for every option
it could not parse properly.
- Renamed 'UnknownOption' to 'UnknownOptionData' to distinguish how it
works from 'UnparsedEdnsOption'.
* Tweak some documentation
* [new_*] Prefer 'alloc' over 'std'
* [new_edns] Add conversion between 'Record' and 'EdnsRecord'
* [new_base/parse] Add a high-level example
* [new_base] Add 'MessageItem' and a mid-level parsing API
'Message's are semantically equivalent to sequences of 'MessageItem's,
and this is the basis for the mid-level API. Next up: building.
* [new_base] Expand top-level documentation
* [new_base] Overhaul the building API
The mid-level building API has been completely rewritten. It is much
simpler now, but no longer supports in-place modification or resumption
for the last message item.
'BuildIntoMessage' was renamed to 'BuildInMessage', and its signature
was completely changed to remove 'Builder'. It is now quite similar to
'SplitMessageBytes'. A slightly more involved truncation strategy is
used, where the name compressor is left to reset by the caller.
* [new_base/build] Update doc test
* [new_base] Implement name compresion
- Most file changes were to correct the parameter name for the name
compressor in 'impl BuildInMessage::build_in_message()'.
- While the compressor seems to work correctly in basic cases, more
thorough testing is necessary.
- It would be valuable to benchmark name compression between new-base
and the existing base, e.g. in the construction of AXFR messages.
* [new_base/name/compressor] Use case-insensitive hashing
* Move 'new_*' to a dedicated 'new' module
This also adds an 'unstable-new' feature flag to gate these modules.
* [new] Account for new Clippy lints
Remove incorrect logic for determining the apex from signing functions, instead require the apex name to be passed in. This fixes issues such as signing wrongly identifying an out-of-zone name (such as a glue that sorts earlier than the zone) as the apex instead of the zone itself.
* stelline: document and refactor
* stelline: further refactoring
* stelline: use Debug in some errors to see quotes around the string
* stelline: document the syntax a bit in the readme
* stelline refactor WIP
* centralize logging settings
* stelline: fix up more wrong matching behaviour
All tests pass again!
* enabling logging module only when tracing-subscriber is enabled
* stelline: fix some code blocks being run as doctests
* stelline: reword based on feedback
* stelline: fix some clippy lints
The client cache depends on the moka crate. Make the client cache optional to allow the use of the client transports without depending on moka.
---------
Co-authored-by: Terts Diepraam <terts.diepraam@gmail.com>
- Extend the inplace zone parser to detect violations of the RFC 1035 section 5.2 requirement that a zonefile consist of exactly one class, enabled by default, and extend its error reporting to say what the wrong and expected classes were (and also use this contextual error support for other errors where applicable).
- Remove the default IN last class and allow the last class to be set if needed, as RFC 1035 doesn't define a default class.
The MSRV is being bumped so that `domain` can access newer language features. In particular:
- `<[u8]>::utf8_chunks()` (1.79) is very useful for processing byte strings that will _mostly_ contain valid UTF-8 text.
- `core::net` (1.77) allows us to remove our polyfills of `Ipv4Addr` etc., used when the `std` feature is disabled.
- `async fn` and return-position `impl Trait` in traits (1.75) allow us to define traits using `async fn`, avoiding the overhead of `Box<dyn Future>` for un-nameable future types.
- `Option::is_some_and()` (1.70) simplifies a very common pattern when inspecting optional values.
The MSRV bump policy is also being updated; it sets a maximum MSRV (relative to the latest stable Rust version) and documents the conditions under which a bump will occur.
This PR does this by enabling Tokio Tracing to emit logs if no tracing
subscriber is initialized (via the tracing/log feature).
Also fixes guards around costly logging to actually emits log events if no
tracing subscriber is initialized by using the enabled check of the log crate
instead of the enabled check of the tracing crate.
See: https://docs.rs/tracing/0.1.41/tracing/#emitting-log-records