11a0216d1Sopenharmony_ci//! A simple testcase that prints a few messages to the console, demonstrating
21a0216d1Sopenharmony_ci//! the io-lifetimes API.
31a0216d1Sopenharmony_ci
41a0216d1Sopenharmony_ci#![cfg_attr(not(io_safety_is_in_std), allow(unused_imports))]
51a0216d1Sopenharmony_ci
61a0216d1Sopenharmony_ci#[cfg(feature = "close")]
71a0216d1Sopenharmony_ciuse io_lifetimes::example_ffi::*;
81a0216d1Sopenharmony_ci#[cfg(feature = "close")]
91a0216d1Sopenharmony_ciuse std::{
101a0216d1Sopenharmony_ci    fs::File,
111a0216d1Sopenharmony_ci    io::{self, Write},
121a0216d1Sopenharmony_ci};
131a0216d1Sopenharmony_ci
141a0216d1Sopenharmony_ci#[cfg(all(unix, feature = "close"))]
151a0216d1Sopenharmony_ciuse io_lifetimes::{AsFd, OwnedFd};
161a0216d1Sopenharmony_ci
171a0216d1Sopenharmony_ci#[cfg(all(windows, feature = "close"))]
181a0216d1Sopenharmony_ciuse io_lifetimes::{AsHandle, OwnedHandle};
191a0216d1Sopenharmony_ci#[cfg(all(windows, feature = "close"))]
201a0216d1Sopenharmony_ciuse std::{convert::TryInto, os::windows::io::RawHandle, ptr::null_mut};
211a0216d1Sopenharmony_ci
221a0216d1Sopenharmony_ci#[cfg(all(io_safety_is_in_std, unix, feature = "close"))]
231a0216d1Sopenharmony_cifn main() -> io::Result<()> {
241a0216d1Sopenharmony_ci    let fd = unsafe {
251a0216d1Sopenharmony_ci        // Open a file, which returns an `Option<OwnedFd>`, which we can
261a0216d1Sopenharmony_ci        // maybe convert into an `OwnedFile`.
271a0216d1Sopenharmony_ci        let fd: OwnedFd = open("/dev/stdout\0".as_ptr() as *const _, O_WRONLY | O_CLOEXEC)
281a0216d1Sopenharmony_ci            .ok_or_else(io::Error::last_os_error)?;
291a0216d1Sopenharmony_ci
301a0216d1Sopenharmony_ci        // Borrow the fd to write to it.
311a0216d1Sopenharmony_ci        let result = write(fd.as_fd(), "hello, world\n".as_ptr() as *const _, 13);
321a0216d1Sopenharmony_ci        match result {
331a0216d1Sopenharmony_ci            -1 => return Err(io::Error::last_os_error()),
341a0216d1Sopenharmony_ci            13 => (),
351a0216d1Sopenharmony_ci            _ => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
361a0216d1Sopenharmony_ci        }
371a0216d1Sopenharmony_ci
381a0216d1Sopenharmony_ci        fd
391a0216d1Sopenharmony_ci    };
401a0216d1Sopenharmony_ci
411a0216d1Sopenharmony_ci    // Convert into a `File`. No `unsafe` here!
421a0216d1Sopenharmony_ci    let mut file = File::from(fd);
431a0216d1Sopenharmony_ci    writeln!(&mut file, "greetings, y'all")?;
441a0216d1Sopenharmony_ci
451a0216d1Sopenharmony_ci    // We can borrow a `BorrowedFd` from a `File`.
461a0216d1Sopenharmony_ci    unsafe {
471a0216d1Sopenharmony_ci        let result = write(file.as_fd(), "sup?\n".as_ptr() as *const _, 5);
481a0216d1Sopenharmony_ci        match result {
491a0216d1Sopenharmony_ci            -1 => return Err(io::Error::last_os_error()),
501a0216d1Sopenharmony_ci            5 => (),
511a0216d1Sopenharmony_ci            _ => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
521a0216d1Sopenharmony_ci        }
531a0216d1Sopenharmony_ci    }
541a0216d1Sopenharmony_ci
551a0216d1Sopenharmony_ci    // `OwnedFd` closes the fd in its `Drop` implementation.
561a0216d1Sopenharmony_ci
571a0216d1Sopenharmony_ci    Ok(())
581a0216d1Sopenharmony_ci}
591a0216d1Sopenharmony_ci
601a0216d1Sopenharmony_ci/// The Windows analog of the above.
611a0216d1Sopenharmony_ci#[cfg(all(windows, feature = "close"))]
621a0216d1Sopenharmony_cifn main() -> io::Result<()> {
631a0216d1Sopenharmony_ci    let handle = unsafe {
641a0216d1Sopenharmony_ci        // Open a file, which returns an `HandleOrInvalid`, which we can fallibly
651a0216d1Sopenharmony_ci        // convert into an `OwnedFile`.
661a0216d1Sopenharmony_ci        let handle: OwnedHandle = CreateFileW(
671a0216d1Sopenharmony_ci            ['C' as u16, 'O' as _, 'N' as _, 0].as_ptr(),
681a0216d1Sopenharmony_ci            FILE_GENERIC_WRITE,
691a0216d1Sopenharmony_ci            0,
701a0216d1Sopenharmony_ci            null_mut(),
711a0216d1Sopenharmony_ci            OPEN_EXISTING,
721a0216d1Sopenharmony_ci            FILE_ATTRIBUTE_NORMAL,
731a0216d1Sopenharmony_ci            null_mut() as RawHandle as HANDLE,
741a0216d1Sopenharmony_ci        )
751a0216d1Sopenharmony_ci        .try_into()
761a0216d1Sopenharmony_ci        .map_err(|_err| io::Error::last_os_error())?;
771a0216d1Sopenharmony_ci
781a0216d1Sopenharmony_ci        // Borrow the handle to write to it.
791a0216d1Sopenharmony_ci        let mut number_of_bytes_written = 0;
801a0216d1Sopenharmony_ci        let result = WriteFile(
811a0216d1Sopenharmony_ci            handle.as_handle(),
821a0216d1Sopenharmony_ci            "hello, world\n".as_ptr() as *const _,
831a0216d1Sopenharmony_ci            13,
841a0216d1Sopenharmony_ci            &mut number_of_bytes_written,
851a0216d1Sopenharmony_ci            null_mut(),
861a0216d1Sopenharmony_ci        );
871a0216d1Sopenharmony_ci        match (result, number_of_bytes_written) {
881a0216d1Sopenharmony_ci            (0, _) => return Err(io::Error::last_os_error()),
891a0216d1Sopenharmony_ci            (_, 13) => (),
901a0216d1Sopenharmony_ci            (_, _) => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
911a0216d1Sopenharmony_ci        }
921a0216d1Sopenharmony_ci
931a0216d1Sopenharmony_ci        handle
941a0216d1Sopenharmony_ci    };
951a0216d1Sopenharmony_ci
961a0216d1Sopenharmony_ci    // Convert into a `File`. No `unsafe` here!
971a0216d1Sopenharmony_ci    let mut file = File::from(handle);
981a0216d1Sopenharmony_ci    writeln!(&mut file, "greetings, y'all")?;
991a0216d1Sopenharmony_ci
1001a0216d1Sopenharmony_ci    // We can borrow a `BorrowedHandle` from a `File`.
1011a0216d1Sopenharmony_ci    unsafe {
1021a0216d1Sopenharmony_ci        let mut number_of_bytes_written = 0;
1031a0216d1Sopenharmony_ci        let result = WriteFile(
1041a0216d1Sopenharmony_ci            file.as_handle(),
1051a0216d1Sopenharmony_ci            "sup?\n".as_ptr() as *const _,
1061a0216d1Sopenharmony_ci            5,
1071a0216d1Sopenharmony_ci            &mut number_of_bytes_written,
1081a0216d1Sopenharmony_ci            null_mut(),
1091a0216d1Sopenharmony_ci        );
1101a0216d1Sopenharmony_ci        match (result, number_of_bytes_written) {
1111a0216d1Sopenharmony_ci            (0, _) => return Err(io::Error::last_os_error()),
1121a0216d1Sopenharmony_ci            (_, 5) => (),
1131a0216d1Sopenharmony_ci            (_, _) => return Err(io::Error::new(io::ErrorKind::Other, "short write")),
1141a0216d1Sopenharmony_ci        }
1151a0216d1Sopenharmony_ci    }
1161a0216d1Sopenharmony_ci
1171a0216d1Sopenharmony_ci    // `OwnedHandle` closes the handle in its `Drop` implementation.
1181a0216d1Sopenharmony_ci
1191a0216d1Sopenharmony_ci    Ok(())
1201a0216d1Sopenharmony_ci}
1211a0216d1Sopenharmony_ci
1221a0216d1Sopenharmony_ci#[cfg(all(
1231a0216d1Sopenharmony_ci    not(all(io_safety_is_in_std, unix, feature = "close")),
1241a0216d1Sopenharmony_ci    not(all(windows, feature = "close"))
1251a0216d1Sopenharmony_ci))]
1261a0216d1Sopenharmony_cifn main() {
1271a0216d1Sopenharmony_ci    println!("On Unix, this example requires Rust >= 1.63 and the \"close\" feature.");
1281a0216d1Sopenharmony_ci}
129