Refactor UserInput to use channels
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
use std::cell::RefCell;
|
use std::borrow::Cow;
|
||||||
use std::io::{Seek, SeekFrom, Write};
|
use std::io::Write;
|
||||||
use std::rc::Rc;
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||||
use std::{borrow::Cow, io::Cursor};
|
|
||||||
|
|
||||||
use rand::{rngs::StdRng, SeedableRng};
|
use rand::{rngs::StdRng, SeedableRng};
|
||||||
|
|
||||||
@@ -40,14 +39,12 @@ impl StreamConfig {
|
|||||||
///
|
///
|
||||||
/// This also returns a handler to the stdin do the [`Machine`](crate::Machine).
|
/// This also returns a handler to the stdin do the [`Machine`](crate::Machine).
|
||||||
pub fn with_callbacks(stdout: Option<Callback>, stderr: Option<Callback>) -> (UserInput, Self) {
|
pub fn with_callbacks(stdout: Option<Callback>, stderr: Option<Callback>) -> (UserInput, Self) {
|
||||||
let stdin = Rc::new(RefCell::new(Cursor::new(Vec::new())));
|
let (sender, receiver) = channel();
|
||||||
(
|
(
|
||||||
UserInput {
|
UserInput { inner: sender },
|
||||||
inner: stdin.clone(),
|
|
||||||
},
|
|
||||||
StreamConfig {
|
StreamConfig {
|
||||||
inner: StreamConfigInner::Callbacks {
|
inner: StreamConfigInner::Callbacks {
|
||||||
stdin,
|
stdin: receiver,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
},
|
},
|
||||||
@@ -59,23 +56,19 @@ impl StreamConfig {
|
|||||||
/// A handler for the stdin of the [`Machine`](crate::Machine).
|
/// A handler for the stdin of the [`Machine`](crate::Machine).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UserInput {
|
pub struct UserInput {
|
||||||
inner: Rc<RefCell<Cursor<Vec<u8>>>>,
|
inner: Sender<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for UserInput {
|
impl Write for UserInput {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
let mut inner = self.inner.borrow_mut();
|
self.inner
|
||||||
let pos = inner.position();
|
.send(buf.into())
|
||||||
|
.map(|_| buf.len())
|
||||||
inner.seek(SeekFrom::End(0))?;
|
.map_err(|_| std::io::ErrorKind::BrokenPipe.into())
|
||||||
let result = inner.write(buf);
|
|
||||||
inner.seek(SeekFrom::Start(pos))?;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> std::io::Result<()> {
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
self.inner.borrow_mut().flush()
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +78,7 @@ enum StreamConfigInner {
|
|||||||
#[default]
|
#[default]
|
||||||
Memory,
|
Memory,
|
||||||
Callbacks {
|
Callbacks {
|
||||||
stdin: Rc<RefCell<Cursor<Vec<u8>>>>,
|
stdin: Receiver<Vec<u8>>,
|
||||||
stdout: Option<Callback>,
|
stdout: Option<Callback>,
|
||||||
stderr: Option<Callback>,
|
stderr: Option<Callback>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -620,7 +620,7 @@ fn callback_streams() {
|
|||||||
|
|
||||||
let (mut user_input, streams) = StreamConfig::with_callbacks(
|
let (mut user_input, streams) = StreamConfig::with_callbacks(
|
||||||
Some(Box::new(move |x| {
|
Some(Box::new(move |x| {
|
||||||
x.read_to_string(&mut *test_string2.borrow_mut()).unwrap();
|
x.read_to_string(&mut test_string2.borrow_mut()).unwrap();
|
||||||
})),
|
})),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ pub use scryer_modular_bitfield::prelude::*;
|
|||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
use bytes::{buf::Reader as BufReader, Buf, Bytes};
|
use bytes::{buf::Reader as BufReader, Buf, Bytes};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -30,7 +29,8 @@ use std::net::{Shutdown, TcpStream};
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::sync::mpsc::Receiver;
|
||||||
|
use std::sync::mpsc::TryRecvError;
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use native_tls::TlsStream;
|
use native_tls::TlsStream;
|
||||||
@@ -414,13 +414,50 @@ impl Write for CallbackStream {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InputChannelStream {
|
pub struct InputChannelStream {
|
||||||
pub(crate) inner: Rc<RefCell<Cursor<Vec<u8>>>>,
|
pub(crate) inner: Cursor<Vec<u8>>,
|
||||||
|
pub eof: bool,
|
||||||
|
channel: Receiver<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for InputChannelStream {
|
impl Read for InputChannelStream {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
self.inner.borrow_mut().read(buf)
|
if self.eof {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let to_read = buf.len();
|
||||||
|
let mut total_read = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
total_read += self.inner.read(&mut buf[total_read..])?;
|
||||||
|
|
||||||
|
if total_read < to_read {
|
||||||
|
// We need to get more data to read
|
||||||
|
match self.channel.try_recv() {
|
||||||
|
Ok(data) => {
|
||||||
|
// Append into self.inner
|
||||||
|
let pos = self.inner.position();
|
||||||
|
assert_eq!(pos as usize, self.inner.get_ref().len());
|
||||||
|
self.inner.write_all(&data)?;
|
||||||
|
self.inner.seek(SeekFrom::Start(pos))?;
|
||||||
|
}
|
||||||
|
Err(TryRecvError::Empty) => {
|
||||||
|
// Data is pending
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(TryRecvError::Disconnected) => {
|
||||||
|
// The other end of the channel was closed so we are EOF
|
||||||
|
self.eof = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert_eq!(total_read, to_read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total_read)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,9 +639,14 @@ impl Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn input_channel(cursor: Rc<RefCell<Cursor<Vec<u8>>>>, arena: &mut Arena) -> Stream {
|
pub fn input_channel(channel: Receiver<Vec<u8>>, arena: &mut Arena) -> Stream {
|
||||||
|
let inner = Cursor::new(Vec::new());
|
||||||
Stream::InputChannel(arena_alloc!(
|
Stream::InputChannel(arena_alloc!(
|
||||||
StreamLayout::new(CharReader::new(InputChannelStream { inner: cursor })),
|
StreamLayout::new(CharReader::new(InputChannelStream {
|
||||||
|
inner,
|
||||||
|
eof: false,
|
||||||
|
channel
|
||||||
|
})),
|
||||||
arena
|
arena
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -1239,6 +1281,13 @@ impl Stream {
|
|||||||
AtEndOfStream::Past
|
AtEndOfStream::Past
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Stream::InputChannel(stream_layout) => {
|
||||||
|
if stream_layout.stream.get_ref().eof {
|
||||||
|
AtEndOfStream::At
|
||||||
|
} else {
|
||||||
|
AtEndOfStream::Not
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => AtEndOfStream::Not,
|
_ => AtEndOfStream::Not,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1519,6 +1568,10 @@ impl Stream {
|
|||||||
readline_stream.reset();
|
readline_stream.reset();
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
Stream::InputChannel(ref mut input_channel_stream) => {
|
||||||
|
input_channel_stream.stream.get_mut().inner.set_position(0);
|
||||||
|
true
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user