Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ alloc = []
bumpalo = ["dep:bumpalo", "std"]
bytes = ["dep:bytes", "octseq/bytes"]
heapless = ["dep:heapless", "octseq/heapless"]
serde = ["dep:serde", "octseq/serde"]
serde = ["std", "dep:serde", "octseq/serde"]
smallvec = ["dep:smallvec", "octseq/smallvec"]
std = ["alloc", "dep:hashbrown", "bumpalo?/std", "bytes?/std", "octseq/std", "time/std"]
tracing = ["dep:log", "dep:tracing"]
Expand All @@ -73,7 +73,7 @@ net = ["bytes", "futures-util", "rand", "std", "tokio"]
resolv = ["net", "smallvec", "unstable-client-transport"]
resolv-sync = ["resolv", "tokio/rt"]
tsig = ["bytes", "ring", "smallvec"]
zonefile = ["bytes", "serde", "std"]
zonefile = ["bytes", "serde", "std", "bumpalo"] # new: ["std", "bumpalo", "dep:time"]

# Unstable features
unstable-new = []
Expand Down Expand Up @@ -147,7 +147,7 @@ required-features = ["net", "tokio-stream", "tracing-subscriber", "unstable-clie

[[example]]
name = "read-zone"
required-features = ["zonefile"]
required-features = ["zonefile", "unstable-new"]

[[example]]
name = "query-zone"
Expand Down
44 changes: 10 additions & 34 deletions examples/read-zone.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//! Reads a zone file.

use std::env;
use std::fs::File;
use std::process::exit;
use std::time::SystemTime;
use std::{env, io::BufReader};

use domain::zonefile::inplace::Entry;
use domain::zonefile::inplace::Zonefile;
use domain::new::zonefile::simple::ZonefileScanner;

fn main() {
let mut args = env::args();
Expand All @@ -21,40 +20,17 @@ fn main() {
for zone_file in zone_files {
print!("Processing {zone_file}: ");
let start = SystemTime::now();
let mut reader =
Zonefile::load(&mut File::open(&zone_file).unwrap()).unwrap();
println!(
"Data loaded ({:.03}s).",
start.elapsed().unwrap().as_secs_f32()
);
let file = BufReader::new(File::open(&zone_file).unwrap());
let mut scanner = ZonefileScanner::new(file, None);

let mut i = 0;
let mut last_entry = None;
loop {
match reader.next_entry() {
Ok(entry) if entry.is_some() => {
last_entry = entry;
}
Ok(_) => break, // EOF
Err(err) => {
eprintln!(
"\nAn error occurred while reading {zone_file}:"
);
eprintln!(" Error: {err}");
if let Some(entry) = &last_entry {
if let Entry::Record(record) = &entry {
eprintln!(
"\nThe last record read was:\n{record}."
);
} else {
eprintln!("\nThe last record read was:\n{last_entry:#?}.");
}
eprintln!("\nTry commenting out the line after that record with a leading ; (semi-colon) character.")
}
exit(1);
}
}
while let Some(entry) = scanner.scan().transpose() {
i += 1;
if let Err(err) = entry {
eprintln!("Could not parse {zone_file}: {err}");
exit(1);
}

if i % 100_000_000 == 0 {
println!(
"Processed {}M records ({:.03}s)",
Expand Down
63 changes: 63 additions & 0 deletions src/new/base/charstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use core::str::FromStr;

use crate::utils::dst::{UnsizedCopy, UnsizedCopyFrom};

#[cfg(feature = "zonefile")]
use crate::new::zonefile::scanner::{Scan, ScanError, Scanner};

use super::{
build::{BuildInMessage, NameCompressor},
parse::{ParseMessageBytes, SplitMessageBytes},
Expand Down Expand Up @@ -446,6 +449,42 @@ impl fmt::Display for CharStrParseError {
}
}

//--- Parsing from the zonefile format

#[cfg(feature = "zonefile")]
impl<'a> Scan<'a> for &'a CharStr {
/// Scan a character string.
///
/// This parses the `d-word` syntax from [the specification].
///
/// [the specification]: crate::new::zonefile#specification
fn scan(
scanner: &mut Scanner<'_>,
alloc: &'a bumpalo::Bump,
buffer: &mut std::vec::Vec<u8>,
) -> Result<Self, ScanError> {
let start = buffer.len();
match scanner.scan_token(buffer)? {
Some(token) if token.len() > 255 => {
buffer.truncate(start);
Err(ScanError::Custom("overlong character string"))
}

Some(token) => {
let bytes = alloc.alloc_slice_copy(token);
buffer.truncate(start);
// SAFETY: 'token' consists of up to 255 bytes.
Ok(unsafe { core::mem::transmute::<&[u8], Self>(bytes) })
}

None => {
buffer.truncate(start);
Err(ScanError::Incomplete)
}
}
}
}

//============ Tests =========================================================

#[cfg(test)]
Expand Down Expand Up @@ -473,4 +512,28 @@ mod test {
);
assert_eq!(buffer, &bytes[..6]);
}

#[cfg(feature = "zonefile")]
#[test]
fn scan() {
use crate::new::zonefile::scanner::{Scan, ScanError, Scanner};

let cases = [
(b"hello" as &[u8], Ok(b"hello" as &[u8])),
(b"\"hi\"and\"bye\"" as &[u8], Ok(b"hiandbye")),
(b"\"\"" as &[u8], Ok(b"")),
(b"" as &[u8], Err(ScanError::Incomplete)),
];

let alloc = bumpalo::Bump::new();
let mut buffer = std::vec::Vec::new();
for (input, expected) in cases {
let mut scanner = Scanner::new(input, None);
assert_eq!(
<&CharStr>::scan(&mut scanner, &alloc, &mut buffer)
.map(|c| &c.octets),
expected
);
}
}
}
Loading
Loading