Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a new base module #474

Draft
wants to merge 87 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
b0bf491
Add module 'new_base'
bal-e Dec 6, 2024
ea600fd
[new_base] Add module 'name'
bal-e Dec 9, 2024
6fb0957
[new_base/name] Define labels
bal-e Dec 9, 2024
66c4d19
[new_base] Add module 'message'
bal-e Dec 10, 2024
48051b4
[new_base/name/label] Use 'zerocopy'
bal-e Dec 10, 2024
be78a8f
[new_base] Add module 'parse'
bal-e Dec 10, 2024
7a1a847
[new_base/name] Add module 'parsed'
bal-e Dec 10, 2024
ed95534
[new_base] Add module 'question'
bal-e Dec 10, 2024
37bc7d2
Add module 'record'
bal-e Dec 11, 2024
26653c3
[new_base] Add high-level parsing traits
bal-e Dec 11, 2024
e1c701f
[new_base/name] Add module 'reversed'
bal-e Dec 11, 2024
7ef218d
[new_base/name/reversed] Implement complex parsing
bal-e Dec 11, 2024
3c0b4cd
[new_base/name] Add some 'Debug' impls
bal-e Dec 11, 2024
4b8cc79
[new_base] Implement parsing for 'Question' and 'Record'
bal-e Dec 11, 2024
b56260c
[new_base/parse] Update with new question/record types
bal-e Dec 11, 2024
1622e58
[new_base/name] Fix bugs (thanks clippy)
bal-e Dec 12, 2024
f27f922
[new_base] Make 'record' a private module
bal-e Dec 12, 2024
dd123c1
Use 'zerocopy' 0.8.5 or newer
bal-e Dec 16, 2024
46b2e45
Add module 'new_rdata' with most RFC 1035 types
bal-e Dec 16, 2024
9e238ae
[new_base] Define 'CharStr'
bal-e Dec 16, 2024
bb63a1e
[new_rdata] Define 'Hinfo'
bal-e Dec 16, 2024
5ec06dc
[new_rdata/rfc1035] Implement (basic) 'Txt' records
bal-e Dec 25, 2024
6ad095e
[new_rdata/rfc1035] Add 'ParseFrom' impls where missing
bal-e Dec 25, 2024
90e15bb
[new_rdata/rfc1035] Don't use 'zerocopy' around names
bal-e Dec 25, 2024
c86a57e
[new_base/charstr] Impl 'Eq' and 'Debug'
bal-e Dec 25, 2024
a607c77
[new_base] Add module 'serial'
bal-e Dec 25, 2024
7731a35
[new_base] Add module 'build'
bal-e Dec 26, 2024
c27dd1f
[new_base/build] Add a 'Builder' for DNS messages
bal-e Dec 26, 2024
993eda7
[new_base/name/reversed] Impl building traits
bal-e Dec 26, 2024
d407492
[new_base/build] Add convenience impls for '[u8]'
bal-e Dec 26, 2024
55c7854
[new_base/question] Impl building traits
bal-e Dec 26, 2024
74e6783
[new_base/record] Support building and overhaul parsing
bal-e Dec 26, 2024
6772427
[new_base/charstr] Support building
bal-e Dec 26, 2024
59c33b2
[new_rdata/rfc1035] Impl building traits
bal-e Dec 26, 2024
2d84573
[build/builder] Improve unclear documentation
bal-e Dec 26, 2024
a8433c9
[new_rdata/rfc1035] gate 'Ipv4Addr' behind 'std'
bal-e Dec 27, 2024
86f14bb
[new_rdata/rfc1035] Gate more things under 'std'
bal-e Dec 27, 2024
0728275
[new_base/build/builder] Remove unnecessary explicit lifetime in impl
bal-e Dec 27, 2024
f73ca63
[new_rdata/rfc1035] Support 'Display' outside 'std'
bal-e Dec 28, 2024
1133b4c
[new_rdata] Inline 'rfc1035' and support 'rfc3596'
bal-e Dec 30, 2024
1a95ae8
[new_rdata] Rename submodules with more intuitive names
bal-e Dec 30, 2024
6bf26c5
[new_base] Set up basic EDNS support
bal-e Dec 30, 2024
aa0c590
[new_base/record] Add trait 'ParseRecordData'
bal-e Dec 30, 2024
d11f9e5
[new_base/parse] Make 'Split*' imply 'Parse*'
bal-e Dec 30, 2024
ff7d913
[new_base/record] Add a default for 'parse_record_data()'
bal-e Dec 30, 2024
ba260f0
[new_rdata/basic] Use more capitalization in record data type names
bal-e Dec 30, 2024
6d358a3
[new_rdata] Define enum 'RecordData'
bal-e Dec 30, 2024
bd08a47
[new_rdata/basic] Elide lifetime as per Clippy
bal-e Dec 30, 2024
54f131e
[new_rdata] Elide lifetimes as per clippy
bal-e Dec 31, 2024
6881f6a
Set up a 'domain-macros' crate
bal-e Jan 1, 2025
155fb5a
[new_base/parse] Define 'ParseBytesByRef' for deriving
bal-e Jan 1, 2025
cf170e6
[macros] Define 'ImplSkeleton' and prepare a basic derive
bal-e Jan 1, 2025
89ee797
Expand 'ParseBytesByRef' and largely finish its derive macro
bal-e Jan 2, 2025
baaa8d2
[macros] Add module 'repr' for checking for stable layouts
bal-e Jan 2, 2025
d4fc42f
[new_base/parse] Implement '*BytesByRef' for '[T; N]'
bal-e Jan 2, 2025
a1bfc4f
[macros] Add a derive macro for 'SplitBytesByRef'
bal-e Jan 2, 2025
2164b87
Use '{Parse,Split}BytesByRef' instead of 'zerocopy'
bal-e Jan 2, 2025
499e858
Rename '{Split,Parse}From' to '{Split,Parse}Bytes'
bal-e Jan 2, 2025
2d60092
[macros] Add derives for '{Split,Parse}Bytes'
bal-e Jan 2, 2025
7e0ef89
[macros] Factor out 'new_lifetime()'
bal-e Jan 2, 2025
b0f6b67
Use parsing trait derives across the 'new_*' codebase
bal-e Jan 2, 2025
4a5d343
Impl and use derives for 'AsBytes' and 'BuildBytes'
bal-e Jan 2, 2025
d1f94ba
[macros] Minor fixes as per clippy
bal-e Jan 2, 2025
c0368ea
[new_base/parse] Fix missing doc link
bal-e Jan 2, 2025
42d48e0
[macros] Fix no-fields output for 'ParseBytes'
bal-e Jan 2, 2025
90b531a
[new_base/serial] Support measuring unix time
bal-e Jan 2, 2025
f8fc525
[new_edns] Implement DNS cookie support
bal-e Jan 2, 2025
d445587
[macros] Factor out struct inspection and building
bal-e Jan 3, 2025
21dfd3d
[new_edns] Impl RFC 8914 "Extended DNS errors"
bal-e Jan 6, 2025
1659621
[new_edns] Impl parsing/building for 'EdnsOption'
bal-e Jan 6, 2025
7bb6d2c
[new_base] Add module 'wire' to replace 'zerocopy'
bal-e Jan 6, 2025
af13cf1
[new_base] Correct docs for build traits
bal-e Jan 6, 2025
8daf6b5
[macros] Avoid glob imports where possible
bal-e Jan 6, 2025
8bf87be
[macros/lib.rs] Remove the last 'syn' glob import
bal-e Jan 6, 2025
8afc305
[new_base/parse] Rework '{Parse,Split}FromMessage'
bal-e Jan 7, 2025
1037ba0
[new_base/name] Delete unused 'parsed.rs'
bal-e Jan 7, 2025
5faf44d
[new_base/wire] Define 'SizePrefixed'
bal-e Jan 7, 2025
a98d246
[new_rdata/edns] Implement iteration and formatting
bal-e Jan 7, 2025
3ea33ac
[new_base/build] Use 'BuildResult' to ensure 'commit()' is called
bal-e Jan 9, 2025
6caee28
[new_base/build] Define 'MessageBuilder'
bal-e Jan 9, 2025
95d0fe8
[new_base/message] Add 'as_bytes_mut()' and 'slice_to_mut()'
bal-e Jan 9, 2025
3f14cca
[new_base/name] Add 'UnparsedName'
bal-e Jan 13, 2025
2c9594e
[new_base/message] Impl 'as_array()' for 'SectionCounts'
bal-e Jan 13, 2025
a01a7f2
[new_base/build] Define 'RecordBuilder'
bal-e Jan 13, 2025
7ef9b5b
[new_base/name] Accept Clippy simplifications
bal-e Jan 13, 2025
60f7664
Merge branch 'main' into new-base
bal-e Jan 13, 2025
7540d58
Merge branch 'main' into new-base
bal-e Jan 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[workspace]
resolver = "2"
members = [".", "./macros"]

[package]
name = "domain"
version = "0.10.3"
Expand All @@ -16,11 +20,9 @@ readme = "README.md"
keywords = ["DNS", "domain"]
license = "BSD-3-Clause"

[lib]
name = "domain"
path = "src/lib.rs"

[dependencies]
domain-macros = { path = "./macros", version = "0.10.3" }

arbitrary = { version = "1.4.1", optional = true, features = ["derive"] }
octseq = { version = "0.5.2", default-features = false }
time = { version = "0.3.1", default-features = false }
Expand Down Expand Up @@ -48,6 +50,12 @@ tokio-stream = { version = "0.1.1", optional = true }
tracing = { version = "0.1.40", optional = true }
tracing-subscriber = { version = "0.3.18", optional = true, features = ["env-filter"] }

# 'zerocopy' provides simple derives for converting types to and from byte
# representations, along with network-endian integer primitives. These are
# used to define simple elements of DNS messages and their serialization.
zerocopy = "0.8.5"
zerocopy-derive = "0.8.5"

[features]
default = ["std", "rand"]

Expand Down
28 changes: 28 additions & 0 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "domain-macros"

# Copied from 'domain'.
version = "0.10.3"
rust-version = "1.68.2"
edition = "2021"

authors = ["NLnet Labs <[email protected]>"]
description = "Procedural macros for the `domain` crate."
documentation = "https://docs.rs/domain-macros"
homepage = "https://github.com/nlnetlabs/domain/"
repository = "https://github.com/nlnetlabs/domain/"
keywords = ["DNS", "domain"]
license = "BSD-3-Clause"

[lib]
proc-macro = true

[dependencies.proc-macro2]
version = "1.0"

[dependencies.syn]
version = "2.0"
features = ["visit"]

[dependencies.quote]
version = "1.0"
159 changes: 159 additions & 0 deletions macros/src/data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//! Working with structs, enums, and unions.

use std::ops::Deref;

use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{spanned::Spanned, *};
bal-e marked this conversation as resolved.
Show resolved Hide resolved

//----------- Struct ---------------------------------------------------------

/// A defined 'struct'.
pub struct Struct {
/// The identifier for this 'struct'.
ident: Ident,

/// The fields in this 'struct'.
fields: Fields,
}

impl Struct {
/// Construct a [`Struct`] for a 'Self'.
pub fn new_as_self(fields: &Fields) -> Self {
Self {
ident: <Token![Self]>::default().into(),
fields: fields.clone(),
}
}

/// Whether this 'struct' has no fields.
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}

/// The number of fields in this 'struct'.
pub fn num_fields(&self) -> usize {
self.fields.len()
}

/// The fields of this 'struct'.
pub fn fields(&self) -> impl Iterator<Item = &Field> + '_ {
self.fields.iter()
}

/// The sized fields of this 'struct'.
pub fn sized_fields(&self) -> impl Iterator<Item = &Field> + '_ {
self.fields().take(self.num_fields() - 1)
}

/// The unsized field of this 'struct'.
pub fn unsized_field(&self) -> Option<&Field> {
self.fields.iter().next_back()
}

/// The names of the fields of this 'struct'.
pub fn members(&self) -> impl Iterator<Item = Member> + '_ {
self.fields
.iter()
.enumerate()
.map(|(i, f)| make_member(i, f))
}

/// The names of the sized fields of this 'struct'.
pub fn sized_members(&self) -> impl Iterator<Item = Member> + '_ {
self.members().take(self.num_fields() - 1)
}

/// The name of the last field of this 'struct'.
pub fn unsized_member(&self) -> Option<Member> {
self.fields
.iter()
.next_back()
.map(|f| make_member(self.num_fields() - 1, f))
}

/// Construct a builder for this 'struct'.
pub fn builder<F: Fn(Member) -> Ident>(
&self,
f: F,
) -> StructBuilder<'_, F> {
StructBuilder {
target: self,
var_fn: f,
}
}
}

/// Construct a [`Member`] from a field and index.
fn make_member(index: usize, field: &Field) -> Member {
match &field.ident {
Some(ident) => Member::Named(ident.clone()),
None => Member::Unnamed(Index {
index: index as u32,
span: field.ty.span(),
}),
}
}

//----------- StructBuilder --------------------------------------------------

/// A means of constructing a 'struct'.
pub struct StructBuilder<'a, F: Fn(Member) -> Ident> {
/// The 'struct' being constructed.
target: &'a Struct,

/// A map from field names to constructing variables.
var_fn: F,
}

impl<F: Fn(Member) -> Ident> StructBuilder<'_, F> {
/// The initializing variables for this 'struct'.
pub fn init_vars(&self) -> impl Iterator<Item = Ident> + '_ {
self.members().map(&self.var_fn)
}

/// The names of the sized fields of this 'struct'.
pub fn sized_init_vars(&self) -> impl Iterator<Item = Ident> + '_ {
self.sized_members().map(&self.var_fn)
}

/// The name of the last field of this 'struct'.
pub fn unsized_init_var(&self) -> Option<Ident> {
self.unsized_member().map(&self.var_fn)
}
}

impl<F: Fn(Member) -> Ident> Deref for StructBuilder<'_, F> {
type Target = Struct;

fn deref(&self) -> &Self::Target {
self.target
}
}

impl<F: Fn(Member) -> Ident> ToTokens for StructBuilder<'_, F> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = &self.ident;
match self.fields {
Fields::Named(_) => {
let members = self.members();
let init_vars = self.init_vars();
quote! {
#ident { #(#members: #init_vars),* }
}
}

Fields::Unnamed(_) => {
let init_vars = self.init_vars();
quote! {
#ident ( #(#init_vars),* )
}
}

Fields::Unit => {
quote! { #ident }
}
}
.to_tokens(tokens);
}
}
Loading
Loading