1//! Portability abstractions over `Owned*` and `Borrowed*`. 2//! 3//! On Unix, "everything is a file descriptor". On Windows, file/pipe/process 4//! handles are distinct from socket descriptors. This file provides a minimal 5//! layer of portability over this difference. 6 7use crate::views::{FilelikeView, FilelikeViewType, SocketlikeView, SocketlikeViewType}; 8#[cfg(any(unix, target_os = "wasi"))] 9use crate::{AsFd, BorrowedFd, OwnedFd}; 10#[cfg(windows)] 11use crate::{AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, OwnedHandle, OwnedSocket}; 12 13/// A reference to a filelike object. 14/// 15/// This is a portability abstraction over Unix-like [`BorrowedFd`] and 16/// Windows' `BorrowedHandle`. 17#[cfg(any(unix, target_os = "wasi"))] 18pub type BorrowedFilelike<'filelike> = BorrowedFd<'filelike>; 19 20/// A reference to a filelike object. 21/// 22/// This is a portability abstraction over Unix-like `BorrowedFd` and 23/// Windows' [`BorrowedHandle`]. 24#[cfg(windows)] 25pub type BorrowedFilelike<'filelike> = BorrowedHandle<'filelike>; 26 27/// A reference to a socketlike object. 28/// 29/// This is a portability abstraction over Unix-like [`BorrowedFd`] and 30/// Windows' `BorrowedSocket`. 31#[cfg(any(unix, target_os = "wasi"))] 32pub type BorrowedSocketlike<'socketlike> = BorrowedFd<'socketlike>; 33 34/// A reference to a socketlike object. 35/// 36/// This is a portability abstraction over Unix-like `BorrowedFd` and 37/// Windows' [`BorrowedSocket`]. 38#[cfg(windows)] 39pub type BorrowedSocketlike<'socketlike> = BorrowedSocket<'socketlike>; 40 41/// An owned filelike object. 42/// 43/// This is a portability abstraction over Unix-like [`OwnedFd`] and 44/// Windows' `OwnedHandle`. 45#[cfg(any(unix, target_os = "wasi"))] 46pub type OwnedFilelike = OwnedFd; 47 48/// An owned filelike object. 49/// 50/// This is a portability abstraction over Unix-like `OwnedFd` and 51/// Windows' [`OwnedHandle`]. 52#[cfg(windows)] 53pub type OwnedFilelike = OwnedHandle; 54 55/// An owned socketlike object. 56/// 57/// This is a portability abstraction over Unix-like [`OwnedFd`] and 58/// Windows' `OwnedSocket`. 59#[cfg(any(unix, target_os = "wasi"))] 60pub type OwnedSocketlike = OwnedFd; 61 62/// An owned socketlike object. 63/// 64/// This is a portability abstraction over Unix-like `OwnedFd` and 65/// Windows' [`OwnedSocket`]. 66#[cfg(windows)] 67pub type OwnedSocketlike = OwnedSocket; 68 69/// A portable trait to borrow a reference from an underlying filelike object. 70/// 71/// This is a portability abstraction over Unix-like [`AsFd`] and Windows' 72/// `AsHandle`. It also provides the `as_filelike_view` convenience function 73/// providing typed views. 74#[cfg(any(unix, target_os = "wasi"))] 75pub trait AsFilelike: AsFd { 76 /// Borrows the reference. 77 /// 78 /// # Example 79 /// 80 /// ```rust,no_run 81 /// use std::fs::File; 82 /// # use std::io; 83 /// use io_lifetimes::{AsFilelike, BorrowedFilelike}; 84 /// 85 /// let mut f = File::open("foo.txt")?; 86 /// let borrowed_filelike: BorrowedFilelike<'_> = f.as_filelike(); 87 /// # Ok::<(), io::Error>(()) 88 /// ``` 89 fn as_filelike(&self) -> BorrowedFilelike<'_>; 90 91 /// Return a borrowing view of a resource which dereferences to a `&Target`. 92 /// 93 /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases, 94 /// such as [`File`], `Read` and `Write` are implemented for `&Target` in 95 /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on 96 /// the resuting view, like this: 97 /// 98 /// ```rust,ignore 99 /// let v = f.as_filelike_view::<std::fs::File>(); 100 /// (&*v).read(&mut buf).unwrap(); 101 /// ``` 102 /// 103 /// [`File`]: std::fs::File 104 /// [`Read`]: std::io::Read 105 /// [`Write`]: std::io::Write 106 fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>; 107} 108 109#[cfg(any(unix, target_os = "wasi"))] 110impl<T: AsFd> AsFilelike for T { 111 #[inline] 112 fn as_filelike(&self) -> BorrowedFilelike<'_> { 113 self.as_fd() 114 } 115 116 #[inline] 117 fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> { 118 FilelikeView::new(self) 119 } 120} 121 122/// A portable trait to borrow a reference from an underlying filelike object. 123/// 124/// This is a portability abstraction over Unix-like `AsFd` and Windows' 125/// [`AsHandle`]. It also provides the `as_filelike_view` convenience function 126/// providing typed views. 127#[cfg(windows)] 128pub trait AsFilelike: AsHandle { 129 /// Borrows the reference. 130 /// 131 /// # Example 132 /// 133 /// ```rust,no_run 134 /// use std::fs::File; 135 /// # use std::io; 136 /// use io_lifetimes::{AsFilelike, BorrowedFilelike}; 137 /// 138 /// let mut f = File::open("foo.txt")?; 139 /// let borrowed_filelike: BorrowedFilelike<'_> = f.as_filelike(); 140 /// # Ok::<(), io::Error>(()) 141 /// ``` 142 fn as_filelike(&self) -> BorrowedFilelike<'_>; 143 144 /// Return a borrowing view of a resource which dereferences to a `&Target`. 145 /// 146 /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases, 147 /// such as [`File`], `Read` and `Write` are implemented for `&Target` in 148 /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on 149 /// the resuting view, like this: 150 /// 151 /// ```rust,ignore 152 /// let v = f.as_filelike_view::<std::fs::File>(); 153 /// (&*v).read(&mut buf).unwrap(); 154 /// ``` 155 /// 156 /// [`File`]: std::fs::File 157 /// [`Read`]: std::io::Read 158 /// [`Write`]: std::io::Write 159 fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>; 160} 161 162#[cfg(windows)] 163impl<T: AsHandle> AsFilelike for T { 164 #[inline] 165 fn as_filelike(&self) -> BorrowedFilelike<'_> { 166 self.as_handle() 167 } 168 169 #[inline] 170 fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> { 171 FilelikeView::new(self) 172 } 173} 174 175/// A portable trait to borrow a reference from an underlying socketlike 176/// object. 177/// 178/// This is a portability abstraction over Unix-like [`AsFd`] and Windows' 179/// `AsSocket`. It also provides the `as_socketlike_view` convenience 180/// function providing typed views. 181#[cfg(any(unix, target_os = "wasi"))] 182pub trait AsSocketlike: AsFd { 183 /// Borrows the reference. 184 fn as_socketlike(&self) -> BorrowedSocketlike<'_>; 185 186 /// Return a borrowing view of a resource which dereferences to a `&Target`. 187 /// 188 /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases, 189 /// such as [`TcpStream`], `Read` and `Write` are implemented for `&Target` in 190 /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on 191 /// the resuting view, like this: 192 /// 193 /// ```rust,ignore 194 /// let v = s.as_socketlike_view::<std::net::TcpStream>(); 195 /// (&*v).read(&mut buf).unwrap(); 196 /// ``` 197 /// 198 /// [`TcpStream`]: std::net::TcpStream 199 /// [`Read`]: std::io::Read 200 /// [`Write`]: std::io::Write 201 fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>; 202} 203 204#[cfg(any(unix, target_os = "wasi"))] 205impl<T: AsFd> AsSocketlike for T { 206 #[inline] 207 fn as_socketlike(&self) -> BorrowedSocketlike<'_> { 208 self.as_fd() 209 } 210 211 #[inline] 212 fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> { 213 SocketlikeView::new(self) 214 } 215} 216 217/// A portable trait to borrow a reference from an underlying socketlike 218/// object. 219/// 220/// This is a portability abstraction over Unix-like `AsFd` and Windows' 221/// [`AsSocket`]. It also provides the `as_socketlike_view` convenience 222/// function providing typed views. 223#[cfg(windows)] 224pub trait AsSocketlike: AsSocket { 225 /// Borrows the reference. 226 fn as_socketlike(&self) -> BorrowedSocketlike; 227 228 /// Return a borrowing view of a resource which dereferences to a `&Target`. 229 /// 230 /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases, 231 /// such as [`TcpStream`], `Read` and `Write` are implemented for `&Target` in 232 /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on 233 /// the resuting view, like this: 234 /// 235 /// ```rust,ignore 236 /// let v = s.as_socketlike_view::<std::net::TcpStream>(); 237 /// (&*v).read(&mut buf).unwrap(); 238 /// ``` 239 /// 240 /// [`TcpStream`]: std::net::TcpStream 241 fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>; 242} 243 244#[cfg(windows)] 245impl<T: AsSocket> AsSocketlike for T { 246 #[inline] 247 fn as_socketlike(&self) -> BorrowedSocketlike<'_> { 248 self.as_socket() 249 } 250 251 #[inline] 252 fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> { 253 SocketlikeView::new(self) 254 } 255} 256 257/// A portable trait to express the ability to consume an object and acquire 258/// ownership of its filelike object. 259/// 260/// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and Windows' 261/// `Into<OwnedHandle>`. 262#[cfg(any(unix, target_os = "wasi"))] 263pub trait IntoFilelike: Into<OwnedFd> { 264 /// Consumes this object, returning the underlying filelike object. 265 /// 266 /// # Example 267 /// 268 /// ```rust,no_run 269 /// use std::fs::File; 270 /// # use std::io; 271 /// use io_lifetimes::{IntoFilelike, OwnedFilelike}; 272 /// 273 /// let f = File::open("foo.txt")?; 274 /// let owned_filelike: OwnedFilelike = f.into_filelike(); 275 /// # Ok::<(), io::Error>(()) 276 /// ``` 277 fn into_filelike(self) -> OwnedFilelike; 278} 279 280#[cfg(any(unix, target_os = "wasi"))] 281impl<T: Into<OwnedFd>> IntoFilelike for T { 282 #[inline] 283 fn into_filelike(self) -> OwnedFilelike { 284 self.into() 285 } 286} 287 288/// A portable trait to express the ability to consume an object and acquire 289/// ownership of its filelike object. 290/// 291/// This is a portability abstraction over Unix-like `Into<OwnedFd>` and Windows' 292/// [`Into<OwnedHandle>`]. 293#[cfg(windows)] 294pub trait IntoFilelike: Into<OwnedHandle> { 295 /// Consumes this object, returning the underlying filelike object. 296 fn into_filelike(self) -> OwnedFilelike; 297} 298 299#[cfg(windows)] 300impl<T: Into<OwnedHandle>> IntoFilelike for T { 301 #[inline] 302 fn into_filelike(self) -> OwnedFilelike { 303 self.into() 304 } 305} 306 307/// A portable trait to express the ability to consume an object and acquire 308/// ownership of its socketlike object. 309/// 310/// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and Windows' 311/// `Into<OwnedSocket>`. 312#[cfg(any(unix, target_os = "wasi"))] 313pub trait IntoSocketlike: Into<OwnedFd> { 314 /// Consumes this object, returning the underlying socketlike object. 315 fn into_socketlike(self) -> OwnedSocketlike; 316} 317 318#[cfg(any(unix, target_os = "wasi"))] 319impl<T: Into<OwnedFd>> IntoSocketlike for T { 320 #[inline] 321 fn into_socketlike(self) -> OwnedSocketlike { 322 self.into() 323 } 324} 325 326/// A portable trait to express the ability to consume an object and acquire 327/// ownership of its socketlike object. 328/// 329/// This is a portability abstraction over Unix-like `Into<OwnedFd>` and Windows' 330/// [`Into<OwnedSocket>`]. 331#[cfg(windows)] 332pub trait IntoSocketlike: Into<OwnedSocket> { 333 /// Consumes this object, returning the underlying socketlike object. 334 /// 335 /// # Example 336 /// 337 /// ```rust,no_run 338 /// use std::fs::File; 339 /// # use std::io; 340 /// use io_lifetimes::{IntoFilelike, OwnedFilelike}; 341 /// 342 /// let f = File::open("foo.txt")?; 343 /// let owned_filelike: OwnedFilelike = f.into_filelike(); 344 /// # Ok::<(), io::Error>(()) 345 /// ``` 346 fn into_socketlike(self) -> OwnedSocketlike; 347} 348 349#[cfg(windows)] 350impl<T: Into<OwnedSocket>> IntoSocketlike for T { 351 #[inline] 352 fn into_socketlike(self) -> OwnedSocketlike { 353 self.into() 354 } 355} 356 357/// A portable trait to express the ability to construct an object from a 358/// filelike object. 359/// 360/// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and Windows' 361/// `From<OwnedHandle>`. It also provides the `from_into_filelike` convenience 362/// function providing simplified from+into conversions. 363#[cfg(any(unix, target_os = "wasi"))] 364pub trait FromFilelike: From<OwnedFd> { 365 /// Constructs a new instance of `Self` from the given filelike object. 366 /// 367 /// # Example 368 /// 369 /// ```rust,no_run 370 /// use std::fs::File; 371 /// # use std::io; 372 /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike}; 373 /// 374 /// let f = File::open("foo.txt")?; 375 /// let owned_filelike: OwnedFilelike = f.into_filelike(); 376 /// let f = File::from_filelike(owned_filelike); 377 /// # Ok::<(), io::Error>(()) 378 /// ``` 379 fn from_filelike(owned: OwnedFilelike) -> Self; 380 381 /// Constructs a new instance of `Self` from the given filelike object 382 /// converted from `into_owned`. 383 /// 384 /// # Example 385 /// 386 /// ```rust,no_run 387 /// use std::fs::File; 388 /// # use std::io; 389 /// use io_lifetimes::{FromFilelike, IntoFilelike}; 390 /// 391 /// let f = File::open("foo.txt")?; 392 /// let f = File::from_into_filelike(f); 393 /// # Ok::<(), io::Error>(()) 394 /// ``` 395 fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self; 396} 397 398#[cfg(any(unix, target_os = "wasi"))] 399impl<T: From<OwnedFd>> FromFilelike for T { 400 #[inline] 401 fn from_filelike(owned: OwnedFilelike) -> Self { 402 Self::from(owned) 403 } 404 405 #[inline] 406 fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self { 407 Self::from_filelike(owned.into_filelike()) 408 } 409} 410 411/// A portable trait to express the ability to construct an object from a 412/// filelike object. 413/// 414/// This is a portability abstraction over Unix-like `From<OwnedFd>` and Windows' 415/// [`From<OwnedHandle>`]. It also provides the `from_into_filelike` convenience 416/// function providing simplified from+into conversions. 417#[cfg(windows)] 418pub trait FromFilelike: From<OwnedHandle> { 419 /// Constructs a new instance of `Self` from the given filelike object. 420 /// 421 /// # Example 422 /// 423 /// ```rust,no_run 424 /// use std::fs::File; 425 /// # use std::io; 426 /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike}; 427 /// 428 /// let f = File::open("foo.txt")?; 429 /// let owned_filelike: OwnedFilelike = f.into_filelike(); 430 /// let f = File::from_filelike(owned_filelike); 431 /// # Ok::<(), io::Error>(()) 432 /// ``` 433 fn from_filelike(owned: OwnedFilelike) -> Self; 434 435 /// Constructs a new instance of `Self` from the given filelike object 436 /// converted from `into_owned`. 437 /// 438 /// # Example 439 /// 440 /// ```rust,no_run 441 /// use std::fs::File; 442 /// # use std::io; 443 /// use io_lifetimes::{FromFilelike, IntoFilelike}; 444 /// 445 /// let f = File::open("foo.txt")?; 446 /// let f = File::from_into_filelike(f); 447 /// # Ok::<(), io::Error>(()) 448 /// ``` 449 fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self; 450} 451 452#[cfg(windows)] 453impl<T: From<OwnedHandle>> FromFilelike for T { 454 #[inline] 455 fn from_filelike(owned: OwnedFilelike) -> Self { 456 Self::from(owned) 457 } 458 459 #[inline] 460 fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self { 461 Self::from_filelike(owned.into_filelike()) 462 } 463} 464 465/// A portable trait to express the ability to construct an object from a 466/// socketlike object. 467/// 468/// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and Windows' 469/// `From<OwnedSocketFrom<OwnedSocket> It also provides the `from_into_socketlike` convenience 470/// function providing simplified from+into conversions. 471#[cfg(any(unix, target_os = "wasi"))] 472pub trait FromSocketlike: From<OwnedFd> { 473 /// Constructs a new instance of `Self` from the given socketlike object. 474 fn from_socketlike(owned: OwnedSocketlike) -> Self; 475 476 /// Constructs a new instance of `Self` from the given socketlike object 477 /// converted from `into_owned`. 478 fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self; 479} 480 481#[cfg(any(unix, target_os = "wasi"))] 482impl<T: From<OwnedFd>> FromSocketlike for T { 483 #[inline] 484 fn from_socketlike(owned: OwnedSocketlike) -> Self { 485 Self::from(owned) 486 } 487 488 #[inline] 489 fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self { 490 Self::from_socketlike(owned.into_socketlike()) 491 } 492} 493 494/// A portable trait to express the ability to construct an object from a 495/// socketlike object. 496/// 497/// This is a portability abstraction over Unix-like `From<OwnedFd>` and Windows' 498/// [`From<OwnedSocket>`]. It also provides the `from_into_socketlike` convenience 499/// function providing simplified from+into conversions. 500#[cfg(windows)] 501pub trait FromSocketlike: From<OwnedSocket> { 502 /// Constructs a new instance of `Self` from the given socketlike object. 503 fn from_socketlike(owned: OwnedSocketlike) -> Self; 504 505 /// Constructs a new instance of `Self` from the given socketlike object 506 /// converted from `into_owned`. 507 fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self; 508} 509 510#[cfg(windows)] 511impl<T: From<OwnedSocket>> FromSocketlike for T { 512 #[inline] 513 fn from_socketlike(owned: OwnedSocketlike) -> Self { 514 Self::from(owned) 515 } 516 517 #[inline] 518 fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self { 519 Self::from_socketlike(owned.into_socketlike()) 520 } 521} 522