Skip to content

Commit 12ca765

Browse files
committed
add IpAddr type serailize to byte representation
1 parent 99c00e2 commit 12ca765

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

src/bipaddr.rs

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

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)