Make StdIo backend abstract over IO->"fs"->IO mapper
This commit is contained in:
parent
146e2a1140
commit
447f2610ef
1 changed files with 61 additions and 12 deletions
|
@ -387,6 +387,10 @@ mod stdio {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use libimagerror::into::IntoError;
|
||||||
|
use libimagerror::trace::*;
|
||||||
|
|
||||||
|
use error::StoreErrorKind as SEK;
|
||||||
use error::StoreError as SE;
|
use error::StoreError as SE;
|
||||||
use super::FileAbstraction;
|
use super::FileAbstraction;
|
||||||
use super::FileAbstractionInstance;
|
use super::FileAbstractionInstance;
|
||||||
|
@ -395,26 +399,55 @@ mod stdio {
|
||||||
// Because this is not exported in super::inmemory;
|
// Because this is not exported in super::inmemory;
|
||||||
type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Cursor<Vec<u8>>>>>>;
|
type Backend = Arc<Mutex<RefCell<HashMap<PathBuf, Cursor<Vec<u8>>>>>>;
|
||||||
|
|
||||||
pub struct StdIoFileAbstraction {
|
mod mapper {
|
||||||
mem: InMemoryFileAbstraction,
|
use std::collections::HashMap;
|
||||||
stdin: Box<Read>,
|
use std::io::Cursor;
|
||||||
stdout: Box<Write>,
|
use std::io::{Read, Write};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use store::Result;
|
||||||
|
|
||||||
|
pub trait Mapper {
|
||||||
|
fn read_to_fs(&self, Box<Read>, &mut HashMap<PathBuf, Cursor<Vec<u8>>>) -> Result<()>;
|
||||||
|
fn fs_to_write(&self, &mut HashMap<PathBuf, Cursor<Vec<u8>>>, &mut Write) -> Result<()>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for StdIoFileAbstraction {
|
use self::mapper::Mapper;
|
||||||
|
|
||||||
|
pub struct StdIoFileAbstraction<M: Mapper> {
|
||||||
|
mapper: M,
|
||||||
|
mem: InMemoryFileAbstraction,
|
||||||
|
out: Box<Write>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Debug for StdIoFileAbstraction<M>
|
||||||
|
where M: Mapper
|
||||||
|
{
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
|
||||||
write!(f, "StdIoFileAbstraction({:?}", self.mem)
|
write!(f, "StdIoFileAbstraction({:?}", self.mem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdIoFileAbstraction {
|
impl<M> StdIoFileAbstraction<M>
|
||||||
|
where M: Mapper
|
||||||
|
{
|
||||||
|
|
||||||
pub fn new(in_stream: Box<Read>, out_stream: Box<Write>) -> StdIoFileAbstraction {
|
pub fn new(in_stream: Box<Read>, out_stream: Box<Write>, mapper: M) -> Result<StdIoFileAbstraction<M>, SE> {
|
||||||
StdIoFileAbstraction {
|
let mem = InMemoryFileAbstraction::new();
|
||||||
mem: InMemoryFileAbstraction::new(),
|
|
||||||
stdin: in_stream,
|
{
|
||||||
stdout: out_stream
|
let fill_res = match mem.backend().lock() {
|
||||||
|
Err(_) => Err(SEK::LockError.into_error()),
|
||||||
|
Ok(mut mtx) => mapper.read_to_fs(in_stream, mtx.get_mut())
|
||||||
|
};
|
||||||
|
let _ = try!(fill_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(StdIoFileAbstraction {
|
||||||
|
mapper: mapper,
|
||||||
|
mem: mem,
|
||||||
|
out: out_stream,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backend(&self) -> &Backend {
|
pub fn backend(&self) -> &Backend {
|
||||||
|
@ -423,7 +456,23 @@ mod stdio {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileAbstraction for StdIoFileAbstraction {
|
impl<M> Drop for StdIoFileAbstraction<M>
|
||||||
|
where M: Mapper
|
||||||
|
{
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let fill_res = match self.mem.backend().lock() {
|
||||||
|
Err(_) => Err(SEK::LockError.into_error()),
|
||||||
|
Ok(mut mtx) => self.mapper.fs_to_write(mtx.get_mut(), &mut *self.out)
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can do nothing but end this here with a trace.
|
||||||
|
// As this drop gets called when imag almost exits, there is no point in exit()ing here
|
||||||
|
// again.
|
||||||
|
let _ = fill_res.map_err_trace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Mapper> FileAbstraction for StdIoFileAbstraction<M> {
|
||||||
|
|
||||||
fn remove_file(&self, path: &PathBuf) -> Result<(), SE> {
|
fn remove_file(&self, path: &PathBuf) -> Result<(), SE> {
|
||||||
self.mem.remove_file(path)
|
self.mem.remove_file(path)
|
||||||
|
|
Loading…
Reference in a new issue