use mtk::{Lock, Error};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Handle {
Stdout,
Stdin,
Stderr
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct IOHandle {
stdout: (String, Lock),
stdin: (String, Lock),
stderr: (String, Lock)
}
impl IOHandle {
pub fn new() -> IOHandle {
IOHandle {
stdout: (String::new(), Lock::new()),
stdin: (String::new(), Lock::new()),
stderr: (String::new(), Lock::new())
}
}
pub fn print<S: AsRef<str>>(&mut self, handle: Handle, string: S) -> Result<usize, Error> {
match handle {
Handle::Stdout => {
if !self.stdout.1.is_locked() {
self.stdout.1.lock();
self.stdout.0.push_str(string.as_ref());
self.stdout.1.unlock();
Ok(string.as_ref().len())
} else {
Err(Error::from("stdout is locked"))
}
},
Handle::Stderr => {
if !self.stderr.1.is_locked() {
self.stderr.1.lock();
self.stderr.0.push_str(string.as_ref());
self.stderr.1.unlock();
Ok(string.as_ref().len())
} else {
Err(Error::from("stderr is locked"))
}
},
Handle::Stdin => Err(Error::from("cannot write to stdin"))
}
}
pub fn read(&self, handle: Handle) -> Result<String, Error> {
match handle {
Handle::Stdout => Ok(self.stdout.0.clone()),
Handle::Stderr => Ok(self.stderr.0.clone()),
Handle::Stdin => Ok(read!("{}\n"))
}
}
pub fn output(&self, handle: Handle) -> Result<usize, Error> {
match handle {
Handle::Stdout => {
print!("{}", self.stdout.0);
Ok(self.stdout.0.len())
},
Handle::Stderr => {
print!("{}", self.stderr.0);
Ok(self.stderr.0.len())
},
Handle::Stdin => Err(Error::from("cannot do output from stdin"))
}
}
}