@@ -104,6 +104,31 @@ impl SocketAddrAny {
104104 Self { storage, len }
105105 }
106106
107+ /// Creates a socket address from reading from `ptr`, which points at `len`
108+ /// initialized bytes.
109+ ///
110+ /// # Panics
111+ ///
112+ /// if `len` is smaller than the sockaddr header or larger than
113+ /// `SocketAddrStorage`.
114+ ///
115+ /// # Safety
116+ ///
117+ /// * `ptr` must be a pointer to memory containing a valid socket address.
118+ /// * `len` bytes must be initialized.
119+ pub unsafe fn read ( ptr : * const SocketAddrStorage , len : SocketAddrLen ) -> Self {
120+ assert ! ( len as usize >= size_of:: <read_sockaddr:: sockaddr_header>( ) ) ;
121+ assert ! ( len as usize <= size_of:: <SocketAddrStorage >( ) ) ;
122+ let mut storage = MaybeUninit :: < SocketAddrStorage > :: uninit ( ) ;
123+ core:: ptr:: copy_nonoverlapping (
124+ ptr. cast :: < u8 > ( ) ,
125+ storage. as_mut_ptr ( ) . cast :: < u8 > ( ) ,
126+ len as usize ,
127+ ) ;
128+ let len = NonZeroU32 :: new_unchecked ( len) ;
129+ Self { storage, len }
130+ }
131+
107132 /// Gets the initialized part of the storage as bytes.
108133 #[ inline]
109134 fn bytes ( & self ) -> & [ u8 ] {
@@ -304,3 +329,18 @@ impl TryFrom<SocketAddrAny> for SocketAddrUnix {
304329 read_sockaddr:: read_sockaddr_unix ( & value)
305330 }
306331}
332+
333+ #[ cfg( test) ]
334+ mod tests {
335+ use super :: * ;
336+
337+ #[ test]
338+ fn any_read ( ) {
339+ let localhost = std:: net:: Ipv6Addr :: LOCALHOST ;
340+ let addr = SocketAddrAny :: from ( SocketAddrV6 :: new ( localhost, 7 , 8 , 9 ) ) ;
341+ unsafe {
342+ let same = SocketAddrAny :: read ( addr. as_ptr ( ) , addr. addr_len ( ) ) ;
343+ assert_eq ! ( addr, same) ;
344+ }
345+ }
346+ }
0 commit comments