11a0216d1Sopenharmony_ci//! io-lifetimes provides two different options for library authors 21a0216d1Sopenharmony_ci//! writing APIs which accept untyped I/O resources. 31a0216d1Sopenharmony_ci//! 41a0216d1Sopenharmony_ci//! The following uses the POSIX-ish `Fd` types; similar considerations 51a0216d1Sopenharmony_ci//! apply to the Windows and portable types. 61a0216d1Sopenharmony_ci 71a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 81a0216d1Sopenharmony_ciuse io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; 91a0216d1Sopenharmony_ci 101a0216d1Sopenharmony_ci/// The simplest way to accept a borrowed I/O resource is to simply use a 111a0216d1Sopenharmony_ci/// `BorrwedFd` as an argument. This doesn't require the function to have any 121a0216d1Sopenharmony_ci/// type parameters. It also works in FFI signatures, as `BorrowedFd` and (on 131a0216d1Sopenharmony_ci/// Rust >= 1.63) `Option<BorrowedFd>` are guaranteed to have the same layout 141a0216d1Sopenharmony_ci/// as `RawFd`. 151a0216d1Sopenharmony_ci/// 161a0216d1Sopenharmony_ci/// Callers with an `AsFd`-implementing type would call `.as_fd()` and pass 171a0216d1Sopenharmony_ci/// the result. 181a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 191a0216d1Sopenharmony_cifn use_fd_a(fd: BorrowedFd<'_>) { 201a0216d1Sopenharmony_ci let _ = fd; 211a0216d1Sopenharmony_ci} 221a0216d1Sopenharmony_ci 231a0216d1Sopenharmony_ci/// Another way to do this is to use an `AsFd` type parameter. This is more 241a0216d1Sopenharmony_ci/// verbose at the function definition site, and entails monomorphization, but 251a0216d1Sopenharmony_ci/// it has the advantage of allowing users to pass in any type implementing 261a0216d1Sopenharmony_ci/// `AsFd` directly, without having to call `.as_fd()` themselves. 271a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 281a0216d1Sopenharmony_cifn use_fd_b<Fd: AsFd>(fd: Fd) { 291a0216d1Sopenharmony_ci let _ = fd.as_fd(); 301a0216d1Sopenharmony_ci} 311a0216d1Sopenharmony_ci 321a0216d1Sopenharmony_ci/// Another way to do this is to use an `impl AsFd` parameter. 331a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 341a0216d1Sopenharmony_cifn use_fd_c(fd: impl AsFd) { 351a0216d1Sopenharmony_ci let _ = fd.as_fd(); 361a0216d1Sopenharmony_ci} 371a0216d1Sopenharmony_ci 381a0216d1Sopenharmony_ci/// The simplest way to accept a consumed I/O resource is to simply use an 391a0216d1Sopenharmony_ci/// `OwnedFd` as an argument. Similar to `use_fd_a`, this doesn't require the 401a0216d1Sopenharmony_ci/// function to have any type parameters, and also works in FFI signatures. 411a0216d1Sopenharmony_ci/// 421a0216d1Sopenharmony_ci/// Callers with an `IntoFd`-implementing type would call `.into_fd()` and pass 431a0216d1Sopenharmony_ci/// the result. 441a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 451a0216d1Sopenharmony_cifn consume_fd_a(fd: OwnedFd) { 461a0216d1Sopenharmony_ci let _ = fd; 471a0216d1Sopenharmony_ci} 481a0216d1Sopenharmony_ci 491a0216d1Sopenharmony_ci/// Another way to do this is to use an `IntoFd` type parameter. Similar to 501a0216d1Sopenharmony_ci/// `use_fd_b`, this is more verbose here and entails monomorphization, but it 511a0216d1Sopenharmony_ci/// has the advantage of allowing users to pass in any type implementing 521a0216d1Sopenharmony_ci/// `IntoFd` directly. 531a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 541a0216d1Sopenharmony_cifn consume_fd_b<Fd: Into<OwnedFd>>(fd: Fd) { 551a0216d1Sopenharmony_ci let _: OwnedFd = fd.into(); 561a0216d1Sopenharmony_ci} 571a0216d1Sopenharmony_ci 581a0216d1Sopenharmony_ci/// Another way to do this is to use an `impl IntoFd` parameter. 591a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 601a0216d1Sopenharmony_cifn consume_fd_c(fd: impl Into<OwnedFd>) { 611a0216d1Sopenharmony_ci let _: OwnedFd = fd.into(); 621a0216d1Sopenharmony_ci} 631a0216d1Sopenharmony_ci 641a0216d1Sopenharmony_ci/// Now let's see how the APIs look for users. 651a0216d1Sopenharmony_ci#[cfg(all(feature = "close", not(windows)))] 661a0216d1Sopenharmony_cifn main() { 671a0216d1Sopenharmony_ci let f = std::fs::File::open("Cargo.toml").unwrap(); 681a0216d1Sopenharmony_ci 691a0216d1Sopenharmony_ci // The simple option requires an `.as_fd()` at the callsite. 701a0216d1Sopenharmony_ci use_fd_a(f.as_fd()); 711a0216d1Sopenharmony_ci 721a0216d1Sopenharmony_ci // Another option can take a reference to any owning type directly. 731a0216d1Sopenharmony_ci use_fd_b(&f); 741a0216d1Sopenharmony_ci 751a0216d1Sopenharmony_ci // Of course, users can still pass in `BorrowedFd` values if they want to. 761a0216d1Sopenharmony_ci use_fd_b(f.as_fd()); 771a0216d1Sopenharmony_ci 781a0216d1Sopenharmony_ci // The other option is `impl AsFd`. 791a0216d1Sopenharmony_ci use_fd_c(&f); 801a0216d1Sopenharmony_ci 811a0216d1Sopenharmony_ci // Users can still pass in `BorrowedFd` values if they want to here too. 821a0216d1Sopenharmony_ci use_fd_c(f.as_fd()); 831a0216d1Sopenharmony_ci 841a0216d1Sopenharmony_ci let a = std::fs::File::open("Cargo.toml").unwrap(); 851a0216d1Sopenharmony_ci let b = std::fs::File::open("Cargo.toml").unwrap(); 861a0216d1Sopenharmony_ci let c = std::fs::File::open("Cargo.toml").unwrap(); 871a0216d1Sopenharmony_ci 881a0216d1Sopenharmony_ci // The simple option requires an `.into()` at the callsite. 891a0216d1Sopenharmony_ci consume_fd_a(a.into()); 901a0216d1Sopenharmony_ci 911a0216d1Sopenharmony_ci // Another option can take any `Into<OwnedFd>` type directly. 921a0216d1Sopenharmony_ci consume_fd_b(b); 931a0216d1Sopenharmony_ci 941a0216d1Sopenharmony_ci // The other option can take any `Into<OwnedFd>` type directly. 951a0216d1Sopenharmony_ci consume_fd_c(c); 961a0216d1Sopenharmony_ci} 971a0216d1Sopenharmony_ci 981a0216d1Sopenharmony_ci#[cfg(windows)] 991a0216d1Sopenharmony_cifn main() { 1001a0216d1Sopenharmony_ci println!("This example uses non-Windows APIs."); 1011a0216d1Sopenharmony_ci} 1021a0216d1Sopenharmony_ci 1031a0216d1Sopenharmony_ci#[cfg(all(not(feature = "close"), not(windows)))] 1041a0216d1Sopenharmony_cifn main() { 1051a0216d1Sopenharmony_ci println!("This example requires the \"close\" feature."); 1061a0216d1Sopenharmony_ci} 107