use std::{
fs::File,
io::{Read, Write},
mem::{self, MaybeUninit},
os::{
fd::{FromRawFd, OwnedFd, RawFd},
raw,
},
thread,
time::Duration,
};
use async_main::{async_main, Spawn};
use pasts::prelude::*;
use smelling_salts::{Device, Watch};
const O_CLOEXEC: raw::c_int = 0o2000000;
const O_NONBLOCK: raw::c_int = 0o0004000;
const O_DIRECT: raw::c_int = 0o0040000;
extern "C" {
fn pipe2(pipefd: *mut [RawFd; 2], flags: raw::c_int) -> RawFd;
}
pub struct PipeReceiver(Device);
impl Notify for PipeReceiver {
type Event = u32;
fn poll_next(mut self: Pin<&mut Self>, task: &mut Task<'_>) -> Poll<u32> {
while let Ready(()) = Pin::new(&mut self.0).poll_next(task) {
let mut bytes = [0; mem::size_of::<u32>()];
let Err(e) = self.0.read_exact(&mut bytes) else {
return Ready(u32::from_ne_bytes(bytes));
};
dbg!(e);
}
Pending
}
}
pub struct PipeSender(File);
impl PipeSender {
pub fn send(&mut self, value: u32) {
self.0
.write_all(&value.to_ne_bytes())
.expect("Failed to send");
}
}
pub fn pipe() -> (PipeReceiver, PipeSender) {
let (fd, sender) = unsafe {
let mut pipe = MaybeUninit::<[raw::c_int; 2]>::uninit();
let ret = pipe2(pipe.as_mut_ptr(), O_CLOEXEC | O_NONBLOCK | O_DIRECT);
assert!(ret >= 0);
let [fd, sender] = pipe.assume_init();
assert_ne!(fd, -1);
assert_ne!(sender, -1);
(OwnedFd::from_raw_fd(fd), OwnedFd::from_raw_fd(sender))
};
let device = Device::new(fd, Watch::INPUT);
(PipeReceiver(device), PipeSender(sender.into()))
}
#[async_main]
async fn main(_spawner: impl Spawn) {
const MAGIC_NUMBER: u32 = 0xDEAD_BEEF;
let (mut recver, mut sender) = pipe();
thread::spawn(move || {
println!("Sleeping for 1 second");
thread::sleep(Duration::from_secs(1));
println!("Sending magic number");
sender.send(MAGIC_NUMBER);
});
let value = recver.next().await;
assert_eq!(value, MAGIC_NUMBER);
println!("Received magic number");
}