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

Add serde::Serialize for AllRecordData. #343

Merged
merged 2 commits into from
Oct 2, 2024
Merged
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
23 changes: 7 additions & 16 deletions src/base/iana/exterr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,19 +160,10 @@ int_enum! {
/// ```
pub const EDE_PRIVATE_RANGE_BEGIN: u16 = 49152;

// Only implement `Display` for `ExtendedErrorCode`, as the `FromStr`
// bundled by the `int_enum_*` macros is not very useful.
impl core::fmt::Display for ExtendedErrorCode {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use core::fmt::Write;
match self.to_mnemonic() {
Some(m) => {
for ch in m {
f.write_char(*ch as char)?
}
Ok(())
}
None => write!(f, "EDE{}", self.to_int()),
}
}
}
int_enum_str_with_prefix!(
ExtendedErrorCode,
"EDE",
b"EDE",
u16,
"unknown error code"
);
13 changes: 13 additions & 0 deletions src/base/name/parsed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,19 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for ParsedName<Octs> {
}
}

//--- Serialize

#[cfg(feature = "serde")]
impl<Octs: AsRef<[u8]>> serde::Serialize for ParsedName<Octs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use std::string::ToString;
self.to_string().serialize(serializer)
}
}

//------------ ParsedNameIter -----------------------------------------------

/// An iterator over the labels in a parsed domain name.
Expand Down
16 changes: 16 additions & 0 deletions src/base/opt/algsig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,22 @@ impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Understood<N3uVariant, Octs> {
}
}

//--- Serialize

#[cfg(feature = "serde")]
impl<V, Octs: AsRef<[u8]>> serde::Serialize for Understood<V, Octs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
use serde::ser::SerializeSeq;
let mut list = serializer.serialize_seq(None)?;
for item in self.iter() {
list.serialize_element(&item)?;
}
list.end()
}
}

//--- Extended Opt and OptBuilder

impl<Octs: Octets> Opt<Octs> {
Expand Down
1 change: 1 addition & 0 deletions src/base/opt/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use octseq::parse::Parser;
/// furthest away from the root to which the requesting resolver already has
/// all necessary records.
#[derive(Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[repr(transparent)]
pub struct Chain<Name: ?Sized> {
/// The start name AKA ‘closest trust point.’
Expand Down
21 changes: 21 additions & 0 deletions src/base/opt/cookie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use super::{Opt, OptData, ComposeOptData, ParseOptData};
/// cookie to be included in a response.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "rand", derive(Default))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Cookie {
/// The client cookie.
client: ClientCookie,
Expand Down Expand Up @@ -281,6 +282,16 @@ impl<'a, Target: Composer> OptBuilder<'a, Target> {
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct ClientCookie([u8; 8]);

#[cfg(feature = "serde")]
impl serde::Serialize for ClientCookie {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
use octseq::serde::SerializeOctets;
self.0.serialize_octets(serializer)
}
}

impl ClientCookie {
/// Creates a new client cookie from the given octets.
#[must_use]
Expand Down Expand Up @@ -399,6 +410,16 @@ impl fmt::Display for ClientCookie {
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ServerCookie(Array<32>);

#[cfg(feature = "serde")]
impl serde::Serialize for ServerCookie {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
use octseq::serde::SerializeOctets;
self.0.serialize_octets(serializer)
}
}

impl ServerCookie {
/// Creates a new server cookie from the given octets.
///
Expand Down
1 change: 1 addition & 0 deletions src/base/opt/expire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use octseq::parse::Parser;
///
/// See [RFC 7314](https://tools.ietf.org/html/rfc7314) for details.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Expire(Option<u32>);

impl Expire {
Expand Down
23 changes: 23 additions & 0 deletions src/base/opt/exterr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,39 @@ use core::convert::Infallible;
/// standardized [`ExtendedErrorCode`] for machines and an optional UTF-8
/// error text for humans.
#[derive(Clone)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize),
serde(bound(
serialize = "Octs: AsRef<[u8]>"
))
)]
pub struct ExtendedError<Octs> {
/// The extended error code.
code: ExtendedErrorCode,

/// Optional human-readable error information.
///
/// See `text` for the interpretation of the result.
#[cfg_attr(feature = "serde", serde(serialize_with = "lossy_text"))]
text: Option<Result<Str<Octs>, Octs>>,
}

#[cfg(feature = "serde")]
fn lossy_text<S, Octs: AsRef<[u8]>>(
text: &Option<Result<Str<Octs>, Octs>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match text {
Some(Ok(text)) => serializer.serialize_str(text),
Some(Err(text)) => serializer.serialize_str(&std::string::String::from_utf8_lossy(text.as_ref())),
None => serializer.serialize_none(),
}
}

impl ExtendedError<()> {
/// The option code for this option.
pub(super) const CODE: OptionCode = OptionCode::EXTENDED_ERROR;
Expand Down
2 changes: 2 additions & 0 deletions src/base/opt/keepalive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use octseq::parse::Parser;
/// its response, including a 16-bit value that provides the idle time in
/// units of 100 milliseconds.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct TcpKeepalive(Option<IdleTimeout>);

impl TcpKeepalive {
Expand Down Expand Up @@ -147,6 +148,7 @@ impl<'a, Target: Composer> OptBuilder<'a, Target> {
/// type provides means to conver the value into its raw `u16` value or into
/// a [`Duration`] value.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct IdleTimeout(u16);

impl IdleTimeout {
Expand Down
18 changes: 18 additions & 0 deletions src/base/opt/keytag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,24 @@ impl<'a, Target: Composer> OptBuilder<'a, Target> {
}
}

//--- Serialize

#[cfg(feature = "serde")]
impl<Octs: AsRef<[u8]>> serde::Serialize for KeyTag<Octs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
use serde::ser::SerializeSeq;

let mut list = serializer.serialize_seq(None)?;

for i in self.as_ref().iter() {
list.serialize_element(i)?;
}

list.end()
}
}

//------------ KeyTagIter ----------------------------------------------------

Expand Down
10 changes: 10 additions & 0 deletions src/base/opt/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ macro_rules! opt_types {
//------------ AllOptData --------------------------------------------

#[derive(Clone)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize),
serde(bound(
serialize = "
Octs: AsRef<[u8]> + octseq::serde::SerializeOctets,
Name: serde::Serialize,
",
))
)]
#[non_exhaustive]
pub enum AllOptData<Octs, Name> {
$( $(
Expand Down
30 changes: 30 additions & 0 deletions src/base/opt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,26 @@ pub struct Opt<Octs: ?Sized> {
octets: Octs,
}

#[cfg(feature = "serde")]
impl<O: AsRef<[u8]>> serde::Serialize for Opt<O> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq;
let mut list = serializer.serialize_seq(None)?;

for rec in self.for_slice_ref().iter::<AllOptData<_, _>>() {
let Ok(rec) = rec else {
continue;
};
list.serialize_element(&rec)?;
}

list.end()
}
}

impl Opt<()> {
/// The rtype of this record data type.
pub(crate) const RTYPE: Rtype = Rtype::OPT;
Expand Down Expand Up @@ -866,11 +886,21 @@ pub trait ComposeOptData: OptData {
///
/// This type accepts any option type via its option code and raw data.
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct UnknownOptData<Octs> {
/// The option code for the option.
code: OptionCode,

/// The raw option data.
#[cfg_attr(
feature = "serde",
serde(
serialize_with = "crate::utils::base16::serde::serialize",
bound(
serialize = "Octs: AsRef<[u8]> + octseq::serde::SerializeOctets",
)
)
)]
data: Octs,
}

Expand Down
9 changes: 9 additions & 0 deletions src/base/opt/nsid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ impl Nsid<()> {
/// The option code for this option.
pub(super) const CODE: OptionCode = OptionCode::NSID;
}

#[cfg(feature = "serde")]
impl<Octs: octseq::serde::SerializeOctets> serde::Serialize for Nsid<Octs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
self.octets.serialize_octets(serializer)
}
}

impl<Octs> Nsid<Octs> {
/// Creates a value from the ocets of the name server identifier.
Expand Down
12 changes: 12 additions & 0 deletions src/base/opt/padding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,15 @@ impl<'a, Target: Composer> OptBuilder<'a, Target> {
}
}


//--- Serialize

#[cfg(feature = "serde")]
impl<Octs: AsRef<[u8]>> serde::Serialize for Padding<Octs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer {
use octseq::serde::SerializeOctets;
self.octets.as_ref().serialize_octets(serializer)
}
}
1 change: 1 addition & 0 deletions src/base/opt/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use octseq::parse::Parser;
/// The option is defined in [RFC 7871](https://tools.ietf.org/html/rfc7871)
/// which also includes some guidance on its use.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ClientSubnet {
/// The source prefix length.
source_prefix_len: u8,
Expand Down
11 changes: 11 additions & 0 deletions src/rdata/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,17 @@ macro_rules! rdata_types {
/// This enum collects the record data types for all currently
/// implemented record types.
#[derive(Clone)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize),
serde(bound(
serialize = "
O: AsRef<[u8]> + octseq::serde::SerializeOctets,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@partim I copied this from elsewhere, but isn't AsRef<[u8]> always enough because we can do octs.as_ref().serialize_octets(serializer)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. It’s possible that SerializeOctets was doing more things in an earlier iteration. Or I was just not thinking straight.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, but then you have to do your own Serialize impl, no? This way we can just derive it?

N: serde::Serialize,
",
)),
serde(rename_all = "UPPERCASE")
)]
#[non_exhaustive]
pub enum AllRecordData<O, N> {
$( $( $(
Expand Down