summaryrefslogtreecommitdiffstats
path: root/vendor/io-lifetimes/examples
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/io-lifetimes/examples')
-rw-r--r--vendor/io-lifetimes/examples/easy-conversions.rs30
-rw-r--r--vendor/io-lifetimes/examples/flexible-apis.rs108
-rw-r--r--vendor/io-lifetimes/examples/hello.rs129
-rw-r--r--vendor/io-lifetimes/examples/owning-wrapper.rs147
-rw-r--r--vendor/io-lifetimes/examples/portable-views.rs28
5 files changed, 442 insertions, 0 deletions
diff --git a/vendor/io-lifetimes/examples/easy-conversions.rs b/vendor/io-lifetimes/examples/easy-conversions.rs
new file mode 100644
index 000000000..87481c12f
--- /dev/null
+++ b/vendor/io-lifetimes/examples/easy-conversions.rs
@@ -0,0 +1,30 @@
+//! io-lifetimes provides safe, portable, and convenient conversions from types
+//! implementing `IntoFilelike` and `FromSocketlike` to types implementing
+//! `FromFilelike` and `IntoSocketlike`, respectively.
+
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+use io_lifetimes::FromFilelike;
+use std::fs::File;
+use std::io::{self, Read};
+use std::process::{Command, Stdio};
+
+fn main() -> io::Result<()> {
+ let mut child = Command::new("cargo")
+ .arg("--help")
+ .stdout(Stdio::piped())
+ .spawn()
+ .expect("failed to execute child");
+
+ // Convert from `ChildStderr` into `File` without any platform-specific
+ // code or `unsafe`!
+ let mut file = File::from_into_filelike(child.stdout.take().unwrap());
+
+ // Well, this example is not actually that cool, because `File` doesn't let
+ // you do anything that you couldn't already do with `ChildStderr` etc., but
+ // it's useful outside of standard library types.
+ let mut buffer = String::new();
+ file.read_to_string(&mut buffer)?;
+
+ Ok(())
+}
diff --git a/vendor/io-lifetimes/examples/flexible-apis.rs b/vendor/io-lifetimes/examples/flexible-apis.rs
new file mode 100644
index 000000000..8eb19a287
--- /dev/null
+++ b/vendor/io-lifetimes/examples/flexible-apis.rs
@@ -0,0 +1,108 @@
+//! io-lifetimes provides two different options for library authors
+//! writing APIs which accept untyped I/O resources.
+//!
+//! The following uses the POSIX-ish `Fd` types; similar considerations
+//! apply to the Windows and portable types.
+
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+#[cfg(all(feature = "close", not(windows)))]
+use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd};
+
+/// The simplest way to accept a borrowed I/O resource is to simply use a
+/// `BorrwedFd` as an argument. This doesn't require the function to have any
+/// type parameters. It also works in FFI signatures, as `BorrowedFd` and (on
+/// Rust nightly) `Option<BorrowedFd>` are guaranteed to have the same layout
+/// as `RawFd`.
+///
+/// Callers with an `AsFd`-implementing type would call `.as_fd()` and pass
+/// the result.
+#[cfg(all(feature = "close", not(windows)))]
+fn use_fd_a(fd: BorrowedFd<'_>) {
+ let _ = fd;
+}
+
+/// Another way to do this is to use an `AsFd` type parameter. This is more
+/// verbose at the function definition site, and entails monomorphization, but
+/// it has the advantage of allowing users to pass in any type implementing
+/// `AsFd` directly, without having to call `.as_fd()` themselves.
+#[cfg(all(feature = "close", not(windows)))]
+fn use_fd_b<Fd: AsFd>(fd: Fd) {
+ let _ = fd.as_fd();
+}
+
+/// Another way to do this is to use an `impl AsFd` parameter.
+#[cfg(all(feature = "close", not(windows)))]
+fn use_fd_c(fd: impl AsFd) {
+ let _ = fd.as_fd();
+}
+
+/// The simplest way to accept a consumed I/O resource is to simply use an
+/// `OwnedFd` as an argument. Similar to `use_fd_a`, this doesn't require the
+/// function to have any type parameters, and also works in FFI signatures.
+///
+/// Callers with an `IntoFd`-implementing type would call `.into_fd()` and pass
+/// the result.
+#[cfg(all(feature = "close", not(windows)))]
+fn consume_fd_a(fd: OwnedFd) {
+ let _ = fd;
+}
+
+/// Another way to do this is to use an `IntoFd` type parameter. Similar to
+/// `use_fd_b`, this is more verbose here and entails monomorphization, but it
+/// has the advantage of allowing users to pass in any type implementing
+/// `IntoFd` directly.
+#[cfg(all(feature = "close", not(windows)))]
+fn consume_fd_b<Fd: IntoFd>(fd: Fd) {
+ let _ = fd.into_fd();
+}
+
+/// Another way to do this is to use an `impl IntoFd` parameter.
+#[cfg(all(feature = "close", not(windows)))]
+fn consume_fd_c(fd: impl IntoFd) {
+ let _ = fd.into_fd();
+}
+
+/// Now let's see how the APIs look for users.
+#[cfg(all(feature = "close", not(windows)))]
+fn main() {
+ let f = std::fs::File::open("Cargo.toml").unwrap();
+
+ // The simple option requires an `.as_fd()` at the callsite.
+ use_fd_a(f.as_fd());
+
+ // Another option can take a reference to any owning type directly.
+ use_fd_b(&f);
+
+ // Of course, users can still pass in `BorrowedFd` values if they want to.
+ use_fd_b(f.as_fd());
+
+ // The other option is `impl AsFd`.
+ use_fd_c(&f);
+
+ // Users can still pass in `BorrowedFd` values if they want to here too.
+ use_fd_c(f.as_fd());
+
+ let a = std::fs::File::open("Cargo.toml").unwrap();
+ let b = std::fs::File::open("Cargo.toml").unwrap();
+ let c = std::fs::File::open("Cargo.toml").unwrap();
+
+ // The simple option requires an `.into_fd()` at the callsite.
+ consume_fd_a(a.into_fd());
+
+ // Another option can take any `IntoFd` type directly.
+ consume_fd_b(b);
+
+ // The other option can take any `IntoFd` type directly.
+ consume_fd_c(c);
+}
+
+#[cfg(windows)]
+fn main() {
+ println!("This example uses non-Windows APIs.");
+}
+
+#[cfg(all(not(feature = "close"), not(windows)))]
+fn main() {
+ println!("This example requires the \"close\" feature.");
+}
diff --git a/vendor/io-lifetimes/examples/hello.rs b/vendor/io-lifetimes/examples/hello.rs
new file mode 100644
index 000000000..4f6b1a4ed
--- /dev/null
+++ b/vendor/io-lifetimes/examples/hello.rs
@@ -0,0 +1,129 @@
+//! A simple testcase that prints a few messages to the console, demonstrating
+//! the io-lifetimes API.
+
+#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+#[cfg(feature = "close")]
+use io_lifetimes::example_ffi::*;
+#[cfg(feature = "close")]
+use std::{
+ fs::File,
+ io::{self, Write},
+};
+
+#[cfg(all(unix, feature = "close"))]
+use io_lifetimes::{AsFd, FromFd, OwnedFd};
+
+#[cfg(windows)]
+use io_lifetimes::{AsHandle, FromHandle, OwnedHandle};
+#[cfg(windows)]
+use std::{convert::TryInto, os::windows::io::RawHandle, ptr::null_mut};
+
+#[cfg(all(rustc_attrs, unix, feature = "close"))]
+fn main() -> io::Result<()> {
+ let fd = unsafe {
+ // Open a file, which returns an `Option<OwnedFd>`, which we can
+ // maybe convert into an `OwnedFile`.
+ let fd: OwnedFd = open("/dev/stdout\0".as_ptr() as *const _, O_WRONLY | O_CLOEXEC)
+ .ok_or_else(io::Error::last_os_error)?;
+
+ // Borrow the fd to write to it.
+ let result = write(fd.as_fd(), "hello, world\n".as_ptr() as *const _, 13);
+ match result {
+ -1 => return Err(io::Error::last_os_error()),
+ 13 => (),
+ _ => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
+ }
+
+ fd
+ };
+
+ // Convert into a `File`. No `unsafe` here!
+ let mut file = File::from_fd(fd);
+ writeln!(&mut file, "greetings, y'all")?;
+
+ // We can borrow a `BorrowedFd` from a `File`.
+ unsafe {
+ let result = write(file.as_fd(), "sup?\n".as_ptr() as *const _, 5);
+ match result {
+ -1 => return Err(io::Error::last_os_error()),
+ 5 => (),
+ _ => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
+ }
+ }
+
+ // `OwnedFd` closes the fd in its `Drop` implementation.
+
+ Ok(())
+}
+
+/// The Windows analog of the above.
+#[cfg(all(windows, feature = "close"))]
+fn main() -> io::Result<()> {
+ let handle = unsafe {
+ // Open a file, which returns an `HandleOrInvalid`, which we can fallibly
+ // convert into an `OwnedFile`.
+ let handle: OwnedHandle = CreateFileW(
+ ['C' as u16, 'O' as _, 'N' as _, 0].as_ptr(),
+ FILE_GENERIC_WRITE,
+ 0,
+ null_mut(),
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ null_mut() as RawHandle as HANDLE,
+ )
+ .try_into()
+ .map_err(|_err| io::Error::last_os_error())?;
+
+ // Borrow the handle to write to it.
+ let mut number_of_bytes_written = 0;
+ let result = WriteFile(
+ handle.as_handle(),
+ "hello, world\n".as_ptr() as *const _,
+ 13,
+ &mut number_of_bytes_written,
+ null_mut(),
+ );
+ match (result, number_of_bytes_written) {
+ (0, _) => return Err(io::Error::last_os_error()),
+ (_, 13) => (),
+ (_, _) => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
+ }
+
+ handle
+ };
+
+ // Convert into a `File`. No `unsafe` here!
+ let mut file = File::from_handle(handle);
+ writeln!(&mut file, "greetings, y'all")?;
+
+ // We can borrow a `BorrowedHandle` from a `File`.
+ unsafe {
+ let mut number_of_bytes_written = 0;
+ let result = WriteFile(
+ file.as_handle(),
+ "sup?\n".as_ptr() as *const _,
+ 5,
+ &mut number_of_bytes_written,
+ null_mut(),
+ );
+ match (result, number_of_bytes_written) {
+ (0, _) => return Err(io::Error::last_os_error()),
+ (_, 5) => (),
+ (_, _) => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
+ }
+ }
+
+ // `OwnedHandle` closes the handle in its `Drop` implementation.
+
+ Ok(())
+}
+
+#[cfg(all(
+ not(all(rustc_attrs, unix, feature = "close")),
+ not(all(windows, feature = "close"))
+))]
+fn main() {
+ println!("On Unix, this example requires Rust nightly (for `rustc_attrs`) and the \"close\" feature.");
+}
diff --git a/vendor/io-lifetimes/examples/owning-wrapper.rs b/vendor/io-lifetimes/examples/owning-wrapper.rs
new file mode 100644
index 000000000..74a05b2f4
--- /dev/null
+++ b/vendor/io-lifetimes/examples/owning-wrapper.rs
@@ -0,0 +1,147 @@
+//! A simple example implementing the main traits for a type.
+
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+use io_lifetimes::OwnedFilelike;
+#[cfg(not(windows))]
+use io_lifetimes::{AsFd, BorrowedFd, FromFd, IntoFd, OwnedFd};
+#[cfg(windows)]
+use io_lifetimes::{AsHandle, BorrowedHandle, FromHandle, IntoHandle, OwnedHandle};
+
+/// A wrapper around a file descriptor.
+///
+/// Implementing `AsFd`, `IntoFd`, and `FromFd` for a type that wraps an
+/// `Owned*` is straightforward. `Owned*` types also automatically close the
+/// handle in its `Drop`.
+///
+/// Should owning wrappers implement `AsRawFd`, `IntoRawFd`, and `FromRawFd`
+/// too? They can, and there's no need to remove them from a type that already
+/// implements them. But for new code, they can be omitted. Users that really
+/// need the raw value can always do `as_fd().as_raw_fd()`,
+/// `.into_fd().into_raw_fd()`, or `T::from_fd(OwnedFd::from_raw_fd(raw_fd))`.
+/// But if possible, users should use just `as_fd`, `into_fd`, and `from_fd`
+/// and avoid working with raw values altogether.
+struct Thing {
+ filelike: OwnedFilelike,
+}
+
+#[cfg(not(windows))]
+impl AsFd for Thing {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.filelike.as_fd()
+ }
+}
+
+#[cfg(not(windows))]
+impl IntoFd for Thing {
+ #[inline]
+ fn into_fd(self) -> OwnedFd {
+ self.filelike
+ }
+}
+
+#[cfg(not(io_lifetimes_use_std))]
+#[cfg(not(windows))]
+impl From<Thing> for OwnedFd {
+ #[inline]
+ fn from(owned: Thing) -> Self {
+ owned.filelike
+ }
+}
+
+#[cfg(not(windows))]
+impl FromFd for Thing {
+ #[inline]
+ fn from_fd(filelike: OwnedFd) -> Self {
+ Self { filelike }
+ }
+}
+
+#[cfg(not(io_lifetimes_use_std))]
+#[cfg(not(windows))]
+impl From<OwnedFd> for Thing {
+ #[inline]
+ fn from(filelike: OwnedFd) -> Self {
+ Self { filelike }
+ }
+}
+
+#[cfg(windows)]
+impl AsHandle for Thing {
+ #[inline]
+ fn as_handle(&self) -> BorrowedHandle<'_> {
+ self.filelike.as_handle()
+ }
+}
+
+#[cfg(windows)]
+impl IntoHandle for Thing {
+ #[inline]
+ fn into_handle(self) -> OwnedHandle {
+ self.filelike
+ }
+}
+
+#[cfg(not(io_lifetimes_use_std))]
+#[cfg(windows)]
+impl From<Thing> for OwnedHandle {
+ #[inline]
+ fn from(owned: Thing) -> Self {
+ owned.filelike
+ }
+}
+
+#[cfg(windows)]
+impl FromHandle for Thing {
+ #[inline]
+ fn from_handle(filelike: OwnedHandle) -> Self {
+ Self { filelike }
+ }
+}
+
+#[cfg(not(io_lifetimes_use_std))]
+#[cfg(windows)]
+impl From<OwnedHandle> for Thing {
+ #[inline]
+ fn from(filelike: OwnedHandle) -> Self {
+ Self { filelike }
+ }
+}
+
+#[cfg(feature = "close")]
+fn main() {
+ use io_lifetimes::{AsFilelike, FromFilelike, IntoFilelike};
+
+ // Minimally exercise `Thing`'s Posix-ish API.
+ #[cfg(not(windows))]
+ {
+ let file = std::fs::File::open("Cargo.toml").unwrap();
+ let thing = Thing::from_into_fd(file);
+ let _ = thing.as_fd();
+ let _ = thing.into_fd();
+ }
+
+ // Minimally exercise `Thing`'s Windows API.
+ #[cfg(windows)]
+ {
+ let file = std::fs::File::open("Cargo.toml").unwrap();
+ let thing = Thing::from_into_handle(file);
+ let _ = thing.as_handle();
+ let _ = thing.into_handle();
+ }
+
+ // Implementing the above traits makes the blanket impls for the portable
+ // `Filelike` traits available too.
+ {
+ let file = std::fs::File::open("Cargo.toml").unwrap();
+ let thing = Thing::from_into_filelike(file);
+ let _ = thing.as_filelike();
+ let _ = thing.into_filelike();
+ }
+}
+
+#[cfg(not(feature = "close"))]
+fn main() {
+ println!("This example requires the \"close\" feature.");
+}
diff --git a/vendor/io-lifetimes/examples/portable-views.rs b/vendor/io-lifetimes/examples/portable-views.rs
new file mode 100644
index 000000000..410b4c2f0
--- /dev/null
+++ b/vendor/io-lifetimes/examples/portable-views.rs
@@ -0,0 +1,28 @@
+//! io-lifetimes provides safe, convenient, and portable ways to temporarily
+//! view an I/O resource as a `File`, `Socket`, or other types.
+
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+use io_lifetimes::AsFilelike;
+use std::fs::File;
+use std::io::{self, stdout};
+
+fn main() -> io::Result<()> {
+ let stdout = stdout();
+
+ // With `AsFilelike`, any type implementing `AsFd`/`AsHandle` can be viewed
+ // as any type supporting `FromFilelike`, so you can call `File` methods on
+ // `Stdout` or other things.
+ //
+ // Whether or not you can actually do this is up to the OS, of course. In
+ // this case, Unix can do this, but it appears Windows can't.
+ let metadata = stdout.as_filelike_view::<File>().metadata()?;
+
+ if metadata.is_file() {
+ println!("stdout is a file!");
+ } else {
+ println!("stdout is not a file!");
+ }
+
+ Ok(())
+}