use std::fmt;
use bytes::BufMut;
use ::bits::charstr::CharStr;
use ::bits::compose::{Compose, Compress, Compressor};
use ::bits::parse::{Parse, ParseAll, ParseAllError, Parser, ShortBuf};
use ::bits::rdata::RtypeRecordData;
use ::iana::{Nsec3HashAlg, Rtype};
use ::master::scan::{CharSource, Scan, Scanner, ScanError, SyntaxError};
use ::utils::base32;
use super::rfc4034::{RtypeBitmap, RtypeBitmapError};
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Nsec3 {
hash_algorithm: Nsec3HashAlg,
flags: u8,
iterations: u16,
salt: CharStr,
next_owner: CharStr,
types: RtypeBitmap,
}
impl Nsec3 {
pub fn new(
hash_algorithm: Nsec3HashAlg,
flags: u8,
iterations: u16,
salt: CharStr,
next_owner: CharStr,
types: RtypeBitmap
) -> Self {
Nsec3 { hash_algorithm, flags, iterations, salt, next_owner, types }
}
pub fn hash_algorithm(&self) -> Nsec3HashAlg {
self.hash_algorithm
}
pub fn flags(&self) -> u8 {
self.flags
}
pub fn opt_out(&self) -> bool {
self.flags & 0x01 != 0
}
pub fn iterations(&self) -> u16 {
self.iterations
}
pub fn salt(&self) -> &CharStr {
&self.salt
}
pub fn next_owner(&self) -> &CharStr {
&self.next_owner
}
pub fn types(&self) -> &RtypeBitmap {
&self.types
}
}
impl ParseAll for Nsec3 {
type Err = ParseNsec3Error;
fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
if len < 6 {
return Err(ShortBuf.into())
}
let start = parser.pos();
let hash_algorithm = Nsec3HashAlg::parse(parser)?;
let flags = u8::parse(parser)?;
let iterations = u16:: parse(parser)?;
let salt = CharStr::parse(parser)?;
let next_owner = CharStr::parse(parser)?;
let len = if parser.pos() > start + len {
return Err(ShortBuf.into())
}
else {
len - (parser.pos() - start)
};
let types = RtypeBitmap::parse_all(parser, len)?;
Ok(Self::new(
hash_algorithm, flags, iterations, salt, next_owner, types
))
}
}
impl Compose for Nsec3 {
fn compose_len(&self) -> usize {
4 + self.salt.compose_len() + self.next_owner.compose_len() +
self.types.compose_len()
}
fn compose<B: BufMut>(&self, buf: &mut B) {
self.hash_algorithm.compose(buf);
self.flags.compose(buf);
self.iterations.compose(buf);
self.salt.compose(buf);
self.next_owner.compose(buf);
self.types.compose(buf);
}
}
impl Compress for Nsec3 {
fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
buf.compose(self)
}
}
impl Scan for Nsec3 {
fn scan<C: CharSource>(
scanner: &mut Scanner<C>
) -> Result<Self, ScanError> {
Ok(Self::new(
Nsec3HashAlg::scan(scanner)?,
u8::scan(scanner)?,
u16::scan(scanner)?,
scan_salt(scanner)?,
scan_hash(scanner)?,
RtypeBitmap::scan(scanner)?
))
}
}
fn scan_salt<C: CharSource>(
scanner: &mut Scanner<C>
) -> Result<CharStr, ScanError> {
if let Ok(()) = scanner.skip_literal("-") {
Ok(CharStr::empty())
}
else {
CharStr::scan_hex(scanner)
}
}
fn scan_hash<C: CharSource>(
scanner: &mut Scanner<C>
) -> Result<CharStr, ScanError> {
scanner.scan_base32hex_phrase(|bytes| {
CharStr::from_bytes(bytes).map_err(SyntaxError::content)
})
}
impl fmt::Display for Nsec3 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {} {} ", self.hash_algorithm, self.flags,
self.iterations)?;
self.salt.display_hex(f)?;
base32::display_hex(&self.next_owner, f)?;
write!(f, " {}", self.types)
}
}
impl RtypeRecordData for Nsec3 {
const RTYPE: Rtype = Rtype::Nsec3;
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Nsec3param {
hash_algorithm: Nsec3HashAlg,
flags: u8,
iterations: u16,
salt: CharStr,
}
impl Nsec3param {
pub fn new(
hash_algorithm: Nsec3HashAlg,
flags: u8,
iterations: u16,
salt: CharStr
) -> Self {
Nsec3param { hash_algorithm, flags, iterations, salt }
}
pub fn hash_algorithm(&self) -> Nsec3HashAlg {
self.hash_algorithm
}
pub fn flags(&self) -> u8 {
self.flags
}
pub fn iterations(&self) -> u16 {
self.iterations
}
pub fn salt(&self) -> &CharStr {
&self.salt
}
}
impl Parse for Nsec3param {
type Err = ShortBuf;
fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
Ok(Self::new(
Nsec3HashAlg::parse(parser)?,
u8::parse(parser)?,
u16::parse(parser)?,
CharStr::parse(parser)?,
))
}
fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
parser.advance(4)?;
CharStr::skip(parser)
}
}
impl ParseAll for Nsec3param {
type Err = ParseAllError;
fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
if len < 5 {
return Err(ParseAllError::ShortField)
}
Ok(Self::new(
Nsec3HashAlg::parse(parser)?,
u8::parse(parser)?,
u16::parse(parser)?,
CharStr::parse_all(parser, len - 4)?,
))
}
}
impl Compose for Nsec3param {
fn compose_len(&self) -> usize {
4 + self.salt.compose_len()
}
fn compose<B: BufMut>(&self, buf: &mut B) {
self.hash_algorithm.compose(buf);
self.flags.compose(buf);
self.iterations.compose(buf);
self.salt.compose(buf);
}
}
impl Compress for Nsec3param {
fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
buf.compose(self)
}
}
impl Scan for Nsec3param {
fn scan<C: CharSource>(
scanner: &mut Scanner<C>
) -> Result<Self, ScanError> {
Ok(Self::new(
Nsec3HashAlg::scan(scanner)?,
u8::scan(scanner)?,
u16::scan(scanner)?,
scan_salt(scanner)?
))
}
}
impl fmt::Display for Nsec3param {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {} {} ", self.hash_algorithm, self.flags,
self.iterations)?;
self.salt.display_hex(f)
}
}
impl RtypeRecordData for Nsec3param {
const RTYPE: Rtype = Rtype::Nsec3param;
}
#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
pub enum ParseNsec3Error {
#[fail(display="short field")]
ShortField,
#[fail(display="invalid record type bitmap")]
BadRtypeBitmap,
}
impl From<ShortBuf> for ParseNsec3Error {
fn from(_: ShortBuf) -> Self {
ParseNsec3Error::ShortField
}
}
impl From<RtypeBitmapError> for ParseNsec3Error {
fn from(err: RtypeBitmapError) -> Self {
match err {
RtypeBitmapError::ShortBuf => ParseNsec3Error::ShortField,
RtypeBitmapError::BadRtypeBitmap => ParseNsec3Error::BadRtypeBitmap
}
}
}
pub mod parsed {
pub use super::{Nsec3, Nsec3param};
}