pub mod framing;
pub mod header;
pub mod message;
pub mod name;
pub mod reader;
pub mod synth;
pub mod ttl;
pub mod writer;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("message too short: need at least 12 bytes, got {0}")]
MessageTooShort(usize),
#[error("expected QDCOUNT=1, got {0}")]
InvalidQuestionCount(u16),
#[error("compression pointer in question section is not allowed")]
CompressionPointerInQuestion,
#[error(
"unexpected end of buffer at offset {offset}: need {needed} bytes, {available} available"
)]
UnexpectedEof {
offset: usize,
needed: usize,
available: usize,
},
#[error("TCP length prefix is truncated: need 2 bytes, got {0}")]
TruncatedLengthPrefix(usize),
#[error("label too long: {0} bytes (maximum is 63)")]
LabelTooLong(usize),
#[error("name too long: {0} bytes (maximum is 255)")]
NameTooLong(usize),
#[error("name skip limit exceeded while following compression pointers")]
NameSkipLimitExceeded,
#[error("compression pointer target {target} is invalid (message length {msg_len})")]
InvalidPointerTarget {
target: u16,
msg_len: usize,
},
#[error("invalid domain name: empty label")]
EmptyLabel,
#[error("message too long: {0} bytes (maximum is 65535)")]
MessageTooLong(usize),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_variants_display() {
assert!(Error::MessageTooShort(4).to_string().contains('4'));
assert!(Error::InvalidQuestionCount(2).to_string().contains('2'));
assert!(!Error::CompressionPointerInQuestion.to_string().is_empty());
let eof = Error::UnexpectedEof {
offset: 10,
needed: 4,
available: 2,
};
let s = eof.to_string();
assert!(s.contains("10"), "offset should appear in message: {s}");
assert!(s.contains('4'), "needed should appear in message: {s}");
assert!(s.contains('2'), "available should appear in message: {s}");
assert!(Error::TruncatedLengthPrefix(1).to_string().contains('1'));
assert!(Error::MessageTooLong(70000).to_string().contains("70000"));
}
}