Skip to content

Commit 06826b1

Browse files
authored
Rollup merge of rust-lang#100640 - reitermarkus:socket-display-buffer, r=thomcc
Use `DisplayBuffer` for socket addresses. Continuation of rust-lang#100625 for socket addresses. Renames `net::addr` to `net::addr::socket`, `net::ip` to `net::addr::ip` and `net::ip::display_buffer::IpDisplayBuffer` to `net::addr::display_buffer::DisplayBuffer`.
2 parents e95b813 + c8cc821 commit 06826b1

File tree

6 files changed

+103
-48
lines changed

6 files changed

+103
-48
lines changed

library/std/src/net/ip/display_buffer.rs library/std/src/net/display_buffer.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use crate::mem::MaybeUninit;
33
use crate::str;
44

55
/// Used for slow path in `Display` implementations when alignment is required.
6-
pub struct IpDisplayBuffer<const SIZE: usize> {
6+
pub struct DisplayBuffer<const SIZE: usize> {
77
buf: [MaybeUninit<u8>; SIZE],
88
len: usize,
99
}
1010

11-
impl<const SIZE: usize> IpDisplayBuffer<SIZE> {
11+
impl<const SIZE: usize> DisplayBuffer<SIZE> {
1212
#[inline]
1313
pub const fn new() -> Self {
1414
Self { buf: MaybeUninit::uninit_array(), len: 0 }
@@ -25,7 +25,7 @@ impl<const SIZE: usize> IpDisplayBuffer<SIZE> {
2525
}
2626
}
2727

28-
impl<const SIZE: usize> fmt::Write for IpDisplayBuffer<SIZE> {
28+
impl<const SIZE: usize> fmt::Write for DisplayBuffer<SIZE> {
2929
fn write_str(&mut self, s: &str) -> fmt::Result {
3030
let bytes = s.as_bytes();
3131

library/std/src/net/ip.rs library/std/src/net/ip_addr.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::mem::transmute;
88
use crate::sys::net::netc as c;
99
use crate::sys_common::{FromInner, IntoInner};
1010

11-
mod display_buffer;
12-
use display_buffer::IpDisplayBuffer;
11+
use super::display_buffer::DisplayBuffer;
1312

1413
/// An IP address, either IPv4 or IPv6.
1514
///
@@ -997,7 +996,7 @@ impl fmt::Display for Ipv4Addr {
997996
} else {
998997
const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
999998

1000-
let mut buf = IpDisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
999+
let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
10011000
// Buffer is long enough for the longest possible IPv4 address, so this should never fail.
10021001
write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
10031002

@@ -1844,7 +1843,7 @@ impl fmt::Display for Ipv6Addr {
18441843
} else {
18451844
const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
18461845

1847-
let mut buf = IpDisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
1846+
let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
18481847
// Buffer is long enough for the longest possible IPv6 address, so this should never fail.
18491848
write!(buf, "{}", self).unwrap();
18501849

File renamed without changes.

library/std/src/net/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,22 @@
2424
use crate::io::{self, ErrorKind};
2525

2626
#[stable(feature = "rust1", since = "1.0.0")]
27-
pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
28-
#[stable(feature = "rust1", since = "1.0.0")]
29-
pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
27+
pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
3028
#[stable(feature = "rust1", since = "1.0.0")]
3129
pub use self::parser::AddrParseError;
30+
#[stable(feature = "rust1", since = "1.0.0")]
31+
pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
3232
#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
3333
pub use self::tcp::IntoIncoming;
3434
#[stable(feature = "rust1", since = "1.0.0")]
3535
pub use self::tcp::{Incoming, TcpListener, TcpStream};
3636
#[stable(feature = "rust1", since = "1.0.0")]
3737
pub use self::udp::UdpSocket;
3838

39-
mod addr;
40-
mod ip;
39+
mod display_buffer;
40+
mod ip_addr;
4141
mod parser;
42+
mod socket_addr;
4243
mod tcp;
4344
#[cfg(test)]
4445
pub(crate) mod test;

library/std/src/net/addr.rs library/std/src/net/socket_addr.rs

+22-36
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
mod tests;
33

44
use crate::cmp::Ordering;
5-
use crate::fmt;
5+
use crate::fmt::{self, Write};
66
use crate::hash;
7-
use crate::io::{self, Write};
7+
use crate::io;
88
use crate::iter;
99
use crate::mem;
1010
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
@@ -15,6 +15,8 @@ use crate::sys_common::net::LookupHost;
1515
use crate::sys_common::{FromInner, IntoInner};
1616
use crate::vec;
1717

18+
use super::display_buffer::DisplayBuffer;
19+
1820
/// An internet socket address, either IPv4 or IPv6.
1921
///
2022
/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
@@ -616,25 +618,18 @@ impl fmt::Debug for SocketAddr {
616618
#[stable(feature = "rust1", since = "1.0.0")]
617619
impl fmt::Display for SocketAddrV4 {
618620
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619-
// Fast path: if there's no alignment stuff, write to the output buffer
620-
// directly
621+
// If there are no alignment requirements, write the socket address directly to `f`.
622+
// Otherwise, write it to a local buffer and then use `f.pad`.
621623
if f.precision().is_none() && f.width().is_none() {
622624
write!(f, "{}:{}", self.ip(), self.port())
623625
} else {
624-
const IPV4_SOCKET_BUF_LEN: usize = (3 * 4) // the segments
625-
+ 3 // the separators
626-
+ 1 + 5; // the port
627-
let mut buf = [0; IPV4_SOCKET_BUF_LEN];
628-
let mut buf_slice = &mut buf[..];
629-
630-
// Unwrap is fine because writing to a sufficiently-sized
631-
// buffer is infallible
632-
write!(buf_slice, "{}:{}", self.ip(), self.port()).unwrap();
633-
let len = IPV4_SOCKET_BUF_LEN - buf_slice.len();
634-
635-
// This unsafe is OK because we know what is being written to the buffer
636-
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
637-
f.pad(buf)
626+
const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
627+
628+
let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
629+
// Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
630+
write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
631+
632+
f.pad(buf.as_str())
638633
}
639634
}
640635
}
@@ -649,35 +644,26 @@ impl fmt::Debug for SocketAddrV4 {
649644
#[stable(feature = "rust1", since = "1.0.0")]
650645
impl fmt::Display for SocketAddrV6 {
651646
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652-
// Fast path: if there's no alignment stuff, write to the output
653-
// buffer directly
647+
// If there are no alignment requirements, write the socket address directly to `f`.
648+
// Otherwise, write it to a local buffer and then use `f.pad`.
654649
if f.precision().is_none() && f.width().is_none() {
655650
match self.scope_id() {
656651
0 => write!(f, "[{}]:{}", self.ip(), self.port()),
657652
scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
658653
}
659654
} else {
660-
const IPV6_SOCKET_BUF_LEN: usize = (4 * 8) // The address
661-
+ 7 // The colon separators
662-
+ 2 // The brackets
663-
+ 1 + 10 // The scope id
664-
+ 1 + 5; // The port
665-
666-
let mut buf = [0; IPV6_SOCKET_BUF_LEN];
667-
let mut buf_slice = &mut buf[..];
655+
const LONGEST_IPV6_SOCKET_ADDR: &str =
656+
"[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
668657

658+
let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
669659
match self.scope_id() {
670-
0 => write!(buf_slice, "[{}]:{}", self.ip(), self.port()),
671-
scope_id => write!(buf_slice, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
660+
0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
661+
scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
672662
}
673-
// Unwrap is fine because writing to a sufficiently-sized
674-
// buffer is infallible
663+
// Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
675664
.unwrap();
676-
let len = IPV6_SOCKET_BUF_LEN - buf_slice.len();
677665

678-
// This unsafe is OK because we know what is being written to the buffer
679-
let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
680-
f.pad(buf)
666+
f.pad(buf.as_str())
681667
}
682668
}
683669
}

library/std/src/net/addr/tests.rs library/std/src/net/socket_addr/tests.rs

+69
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,75 @@ fn to_socket_addr_string() {
5151
// s has been moved into the tsa call
5252
}
5353

54+
#[test]
55+
fn ipv4_socket_addr_to_string() {
56+
// Shortest possible IPv4 length.
57+
assert_eq!(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0).to_string(), "0.0.0.0:0");
58+
59+
// Longest possible IPv4 length.
60+
assert_eq!(
61+
SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), u16::MAX).to_string(),
62+
"255.255.255.255:65535"
63+
);
64+
65+
// Test padding.
66+
assert_eq!(
67+
&format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
68+
"1.1.1.1:53 "
69+
);
70+
assert_eq!(
71+
&format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
72+
" 1.1.1.1:53"
73+
);
74+
}
75+
76+
#[test]
77+
fn ipv6_socket_addr_to_string() {
78+
// IPv4-mapped address.
79+
assert_eq!(
80+
SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280), 8080, 0, 0)
81+
.to_string(),
82+
"[::ffff:192.0.2.128]:8080"
83+
);
84+
85+
// IPv4-compatible address.
86+
assert_eq!(
87+
SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(),
88+
"[::192.0.2.128]:8080"
89+
);
90+
91+
// IPv6 address with no zero segments.
92+
assert_eq!(
93+
SocketAddrV6::new(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15), 80, 0, 0).to_string(),
94+
"[8:9:a:b:c:d:e:f]:80"
95+
);
96+
97+
// Shortest possible IPv6 length.
98+
assert_eq!(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0).to_string(), "[::]:0");
99+
100+
// Longest possible IPv6 length.
101+
assert_eq!(
102+
SocketAddrV6::new(
103+
Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888),
104+
u16::MAX,
105+
u32::MAX,
106+
u32::MAX,
107+
)
108+
.to_string(),
109+
"[1111:2222:3333:4444:5555:6666:7777:8888%4294967295]:65535"
110+
);
111+
112+
// Test padding.
113+
assert_eq!(
114+
&format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
115+
"[1:2:3:4:5:6:7:8]:9 "
116+
);
117+
assert_eq!(
118+
&format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
119+
" [1:2:3:4:5:6:7:8]:9"
120+
);
121+
}
122+
54123
#[test]
55124
fn bind_udp_socket_bad() {
56125
// rust-lang/rust#53957: This is a regression test for a parsing problem

0 commit comments

Comments
 (0)