pub use std::net::Ipv6Addr;
use std::{fmt, net::AddrParseError, ops::Deref, str};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
error::ProtoResult,
rr::{RData, RecordData, RecordType},
serialize::binary::{BinDecodable, BinDecoder, BinEncodable, BinEncoder},
};
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct AAAA(pub Ipv6Addr);
impl AAAA {
#[allow(clippy::too_many_arguments)]
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Self {
Self(Ipv6Addr::new(a, b, c, d, e, f, g, h))
}
}
impl RecordData for AAAA {
fn try_from_rdata(data: RData) -> Result<Self, crate::rr::RData> {
match data {
RData::AAAA(ipv4) => Ok(ipv4),
_ => Err(data),
}
}
fn try_borrow(data: &RData) -> Option<&Self> {
match data {
RData::AAAA(ipv6) => Some(ipv6),
_ => None,
}
}
fn record_type(&self) -> RecordType {
RecordType::A
}
fn into_rdata(self) -> RData {
RData::AAAA(self)
}
}
impl BinEncodable for AAAA {
fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
let segments = self.segments();
encoder.emit_u16(segments[0])?;
encoder.emit_u16(segments[1])?;
encoder.emit_u16(segments[2])?;
encoder.emit_u16(segments[3])?;
encoder.emit_u16(segments[4])?;
encoder.emit_u16(segments[5])?;
encoder.emit_u16(segments[6])?;
encoder.emit_u16(segments[7])?;
Ok(())
}
}
impl<'r> BinDecodable<'r> for AAAA {
fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
let a: u16 = decoder.read_u16()?.unverified();
let b: u16 = decoder.read_u16()?.unverified();
let c: u16 = decoder.read_u16()?.unverified();
let d: u16 = decoder.read_u16()?.unverified();
let e: u16 = decoder.read_u16()?.unverified();
let f: u16 = decoder.read_u16()?.unverified();
let g: u16 = decoder.read_u16()?.unverified();
let h: u16 = decoder.read_u16()?.unverified();
Ok(Ipv6Addr::new(a, b, c, d, e, f, g, h).into())
}
}
#[allow(clippy::many_single_char_names)]
#[deprecated(note = "use the BinDecodable::read method instead")]
pub fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<AAAA> {
<AAAA as BinDecodable>::read(decoder)
}
#[deprecated(note = "use the BinEncodable::emit method instead")]
pub fn emit(encoder: &mut BinEncoder<'_>, address: &Ipv6Addr) -> ProtoResult<()> {
BinEncodable::emit(&AAAA::from(*address), encoder)
}
impl From<Ipv6Addr> for AAAA {
fn from(aaaa: Ipv6Addr) -> Self {
Self(aaaa)
}
}
impl From<AAAA> for Ipv6Addr {
fn from(aaaa: AAAA) -> Self {
aaaa.0
}
}
impl Deref for AAAA {
type Target = Ipv6Addr;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for AAAA {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.0)
}
}
impl str::FromStr for AAAA {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<Self, AddrParseError> {
Ipv6Addr::from_str(s).map(From::from)
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
use crate::serialize::binary::bin_tests::{test_emit_data_set, test_read_data_set};
fn get_data() -> Vec<(AAAA, Vec<u8>)> {
vec![
(
AAAA::from_str("::").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
), (
AAAA::from_str("1::").unwrap(),
vec![0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
),
(
AAAA::from_str("0:1::").unwrap(),
vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
),
(
AAAA::from_str("0:0:1::").unwrap(),
vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
),
(
AAAA::from_str("0:0:0:1::").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
),
(
AAAA::from_str("::1:0:0:0").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
),
(
AAAA::from_str("::1:0:0").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
),
(
AAAA::from_str("::1:0").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
),
(
AAAA::from_str("::1").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
),
(
AAAA::from_str("::127.0.0.1").unwrap(),
vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1],
),
(
AAAA::from_str("FF00::192.168.64.32").unwrap(),
vec![255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 64, 32],
),
]
}
#[test]
fn test_read() {
test_read_data_set(get_data(), |mut d| AAAA::read(&mut d));
}
#[test]
fn test_emit() {
test_emit_data_set(get_data(), |e, d| d.emit(e));
}
}