Skip to content

Commit 0fb4b84

Browse files
committed
add IpAddr type serailize to byte representation
1 parent 99c00e2 commit 0fb4b84

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

src/bipaddr.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
//! Byte IpAddr which helps with the deserialization.
2+
3+
use core::{
4+
borrow::{Borrow, BorrowMut},
5+
fmt, net,
6+
ops::{Deref, DerefMut},
7+
};
8+
9+
use serde::{
10+
de::{self, Visitor},
11+
Deserialize, Deserializer,
12+
};
13+
14+
#[cfg(all(feature = "alloc", not(feature = "std")))]
15+
use alloc::format;
16+
17+
/// IpAddr serialize to and deserialize from big-endian bytes representation.
18+
///
19+
/// Due to a limitation within `serde` and Rust, a `IpAddr::V4` and `IpAddr::V6` will
20+
/// serialize and deserialize as a list of individual byte elements. Serializing `IpAddr`
21+
/// requires serialize enum which this bencode/library does not support yet.
22+
///
23+
/// # Examples
24+
///
25+
/// ```rust
26+
/// use bt_bencode::ByteIpAddr;
27+
/// use core::net;
28+
///
29+
/// let v4_bytes = [1,2,3,4];
30+
/// let v6_bytes = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
31+
/// let v4 = net::IpAddr::from(v4_bytes);
32+
/// let v6 = net::IpAddr::from(v6_bytes);
33+
/// let bip4 = ByteIpAddr::from(v4);
34+
///
35+
///
36+
/// let encoded = bt_bencode::to_vec(&bip4)?;
37+
/// assert_eq!(encoded, b"4:\x01\x02\x03\x04");
38+
///
39+
/// let decoded: ByteIpAddr = bt_bencode::from_slice(&encoded)?;
40+
/// assert_eq!(decoded, v4.into());
41+
///
42+
/// let bip6 = ByteIpAddr::from(v6);
43+
///
44+
/// let encoded = bt_bencode::to_vec(&bip6)?;
45+
/// assert_eq!(encoded, b"16:\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10");
46+
///
47+
/// let decoded: ByteIpAddr = bt_bencode::from_slice(&encoded)?;
48+
/// assert_eq!(decoded, v6.into());
49+
///
50+
/// // test invalid bytes
51+
/// assert!(bt_bencode::from_slice::<ByteIpAddr>(b"5:\x01\x02\x03\x04\x05").is_err());
52+
///
53+
/// # Ok::<(), bt_bencode::Error>(())
54+
/// ```
55+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
56+
pub struct ByteIpAddr(net::IpAddr);
57+
58+
impl AsRef<net::IpAddr> for ByteIpAddr {
59+
fn as_ref(&self) -> &net::IpAddr {
60+
&self.0
61+
}
62+
}
63+
64+
impl AsMut<net::IpAddr> for ByteIpAddr {
65+
fn as_mut(&mut self) -> &mut net::IpAddr {
66+
&mut self.0
67+
}
68+
}
69+
70+
impl Borrow<net::IpAddr> for ByteIpAddr {
71+
fn borrow(&self) -> &net::IpAddr {
72+
&self.0
73+
}
74+
}
75+
76+
impl BorrowMut<net::IpAddr> for ByteIpAddr {
77+
fn borrow_mut(&mut self) -> &mut net::IpAddr {
78+
&mut self.0
79+
}
80+
}
81+
82+
impl fmt::Debug for ByteIpAddr {
83+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84+
fmt::Debug::fmt(&self.0, f)
85+
}
86+
}
87+
88+
impl Deref for ByteIpAddr {
89+
type Target = net::IpAddr;
90+
91+
fn deref(&self) -> &Self::Target {
92+
&self.0
93+
}
94+
}
95+
96+
impl DerefMut for ByteIpAddr {
97+
fn deref_mut(&mut self) -> &mut Self::Target {
98+
&mut self.0
99+
}
100+
}
101+
102+
impl<T> From<T> for ByteIpAddr
103+
where
104+
net::IpAddr: From<T>,
105+
{
106+
fn from(value: T) -> Self {
107+
Self(net::IpAddr::from(value))
108+
}
109+
}
110+
111+
impl serde::Serialize for ByteIpAddr {
112+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113+
where
114+
S: serde::Serializer,
115+
{
116+
match self.0 {
117+
net::IpAddr::V4(ip) => serializer.serialize_bytes(&ip.octets()),
118+
net::IpAddr::V6(ip) => serializer.serialize_bytes(&ip.octets()),
119+
}
120+
}
121+
}
122+
123+
struct IpAddrVisitor;
124+
125+
impl<'de> Visitor<'de> for IpAddrVisitor {
126+
type Value = ByteIpAddr;
127+
128+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
129+
formatter.write_str("byte string of length 4(ipv4) or 16(ipv6)")
130+
}
131+
132+
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
133+
where
134+
E: de::Error,
135+
{
136+
match v.len() {
137+
4 => Ok(ByteIpAddr(net::IpAddr::V4(net::Ipv4Addr::from([
138+
v[0], v[1], v[2], v[3],
139+
])))),
140+
16 => Ok(ByteIpAddr(net::IpAddr::V6(net::Ipv6Addr::from([
141+
v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10], v[11], v[12],
142+
v[13], v[14], v[15],
143+
])))),
144+
other => Err(de::Error::invalid_value(
145+
de::Unexpected::Str(&format!("get byte string {v:02x?} of length {other}")),
146+
&self,
147+
)),
148+
}
149+
}
150+
}
151+
152+
impl<'de> Deserialize<'de> for ByteIpAddr {
153+
fn deserialize<D>(deserializer: D) -> Result<ByteIpAddr, D::Error>
154+
where
155+
D: Deserializer<'de>,
156+
{
157+
deserializer.deserialize_byte_buf(IpAddrVisitor)
158+
}
159+
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ extern crate serde;
108108
mod bstring;
109109
mod de;
110110
mod error;
111+
mod bipaddr;
111112

112113
pub mod read;
113114
pub mod write;
@@ -122,6 +123,8 @@ pub use de::{from_slice, Deserializer};
122123
#[doc(inline)]
123124
pub use error::{Error, ErrorKind, Result};
124125
#[doc(inline)]
126+
pub use bipaddr::ByteIpAddr;
127+
#[doc(inline)]
125128
pub use value::{from_value, to_value, Value};
126129

127130
#[doc(inline)]

0 commit comments

Comments
 (0)