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

feat: ser/de for IpAddr type; schema for Ipv4Addr/Ipv6Addr/IpAddr types #309

Merged
merged 13 commits into from
Oct 8, 2024
26 changes: 26 additions & 0 deletions borsh/src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,30 @@ impl BorshDeserialize for std::net::SocketAddr {
}
}

#[cfg(feature = "std")]
impl BorshDeserialize for std::net::IpAddr {
#[inline]
fn deserialize_reader<R: Read> (reader: &mut R) -> Result<Self> {
let kind = u8::deserialize_reader(reader)?;
match kind {
0 => {
// Deserialize an Ipv4Addr and convert it to IpAddr::V4
let ipv4_addr = std::net::Ipv4Addr::deserialize_reader(reader)?;
Ok(std::net::IpAddr::V4(ipv4_addr))
},
1 => {
// Deserialize an Ipv6Addr and convert it to IpAddr::V6
let ipv6_addr = std::net::Ipv6Addr::deserialize_reader(reader)?;
Ok(std::net::IpAddr::V6(ipv6_addr))
},
value => Err(Error::new(
ErrorKind::InvalidData,
format!("Invalid IpAddr variant: {}", value),
)),
}
}
}

#[cfg(feature = "std")]
impl BorshDeserialize for std::net::SocketAddrV4 {
#[inline]
Expand Down Expand Up @@ -703,6 +727,8 @@ impl BorshDeserialize for std::net::Ipv6Addr {
}
}



impl<T, U> BorshDeserialize for Box<T>
where
U: Into<Box<T>> + Borrow<T>,
Expand Down
21 changes: 21 additions & 0 deletions borsh/src/ser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,27 @@ impl BorshSerialize for std::net::Ipv6Addr {
}
}

#[cfg(feature = "std")]
impl BorshSerialize for std::net::IpAddr {
#[inline]
fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
match self {
std::net::IpAddr::V4(ipv4) => {
// Serialize a byte to indicate it's IPv4
writer.write_all(&[0u8])?;
// Serialize the IPv4 address
writer.write_all(&ipv4.octets())?;
},
std::net::IpAddr::V6(ipv6) => {
// Serialize a byte to indicate it's IPv6
writer.write_all(&[1u8])?;
// Serialize the IPv6 address
writer.write_all(&ipv6.octets())?;
},
}
Ok(())
}
}
impl<T: BorshSerialize + ?Sized> BorshSerialize for Box<T> {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<()> {
self.as_ref().serialize(writer)
Expand Down
35 changes: 35 additions & 0 deletions borsh/tests/schema/test_ip_addr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::common_macro::schema_imports::*;

#[cfg(feature = "std")]
use std::net::IpAddr;

#[test]
fn ip_addr_schema() {
let actual_name = IpAddr::declaration();
let mut actual_defs = schema_map!();
IpAddr::add_definitions_recursively(&mut actual_defs);

assert_eq!("IpAddr", actual_name);
assert_eq!(
schema_map! {
"IpAddr" => Definition::Union {
variants: vec![
"IpAddr::V4".to_string(),
"IpAddr::V6".to_string()
],
},
"IpAddr::V4" => Definition::Tuple {
elements: vec!["u8".to_string(), "u8".to_string(), "u8".to_string(), "u8".to_string()],
},
"IpAddr::V6" => Definition::Tuple {
elements: vec![
"u16".to_string(), "u16".to_string(), "u16".to_string(), "u16".to_string(),
"u16".to_string(), "u16".to_string(), "u16".to_string(), "u16".to_string(),
],
},
"u8" => Definition::Primitive(1),
"u16" => Definition::Primitive(2),
},
actual_defs
);
}
13 changes: 7 additions & 6 deletions borsh/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod custom_reader {

/// this module doesn't contain runnable tests;
/// it's included into module tree to ensure derived code doesn't raise compilation
/// errors
/// errors
#[rustfmt::skip]
#[cfg(feature = "derive")]
mod compile_derives {
Expand All @@ -31,9 +31,9 @@ mod compile_derives {
/// These are full roundtrip `BorshSerialize`/`BorshDeserialize` tests
#[rustfmt::skip]
mod roundtrip {
mod test_strings;
mod test_strings;
#[cfg(feature = "ascii")]
mod test_ascii_strings;
mod test_ascii_strings;
mod test_arrays;
mod test_vecs;
mod test_tuple;
Expand All @@ -59,7 +59,7 @@ mod roundtrip {
mod test_generic_enums;
mod test_recursive_structs;
mod test_recursive_enums;
mod test_serde_with_third_party;
mod test_serde_with_third_party;
mod test_enum_discriminants;
#[cfg(feature = "bytes")]
mod test_ultimate_many_features_combined;
Expand All @@ -73,12 +73,13 @@ mod roundtrip {
#[rustfmt::skip]
mod schema {
#[cfg(feature = "ascii")]
mod test_ascii_strings;
mod test_strings;
mod test_ascii_strings;
mod test_strings;
mod test_arrays;
mod test_vecs;
mod test_tuple;
mod test_primitives;
mod test_ip_addr;
// mod test_nonzero_integers; // NOTE: there's nothing corresponding to `roundtrip::test_nonzero_integers`
mod test_range;
mod test_phantom_data;
Expand Down
1 change: 1 addition & 0 deletions fuzz/fuzz-run/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn main() {
std::net::SocketAddrV6,
std::net::Ipv4Addr,
std::net::Ipv6Addr,
std::net::IpAddr,
Box<[u8]>,
Option<u64>,
Option<String>,
Expand Down
Loading