added input reading

serial
Avril 4 years ago
parent 6c0f9e53f3
commit 09508a9c5d
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -104,6 +104,22 @@ impl Read for Job
}
}
/// Create a job description for this opened input
///
/// `sz` is the offset of the *end* of the last job. (or 0 for the first).
/// `sz` is then updated with this file's size for this method to be used again on the next file.
pub fn create(file_num: usize, open::Input(file, stat): open::Input, sz: &mut usize) -> Prelude
{
let offset = *sz;
let prelude = Prelude {
file, stat, offset, file_num
};
*sz += prelude.len();
prelude
}
/// Create a job description for this file.
///
/// `sz` is the offset of the *end* of the last job. (or 0 for the first).

@ -26,6 +26,7 @@ mod map;
mod job;
mod work;
mod arg;
mod open;
mod consts;
@ -36,6 +37,7 @@ fn work(arg::Operation{output, inputs}: arg::Operation) -> Result<(), Box<dyn st
// - create and open output file
let output = open::output(output)?;
// - open and stat all input files in order (`job::create_from_file`).
let inputs = open::input(inputs)?;
// - `fallocate` the output file fd to the sum of all input file sizes
// - `mmap` the output file as writable

@ -49,7 +49,7 @@ impl Output
.create(true)
.write(true)
.read(true)
//.truncate(true) //TODO: Remove this, and truncate any excess space that may exist from a clobbered previous file at the end
//.truncate(true) //TODO: Remove this, and truncate any excess space that may exist from a clobbered previous file at the end
.open(path)
.map(Output)
@ -102,3 +102,81 @@ impl fmt::Display for OutputError
}
#[derive(Debug)]
pub struct Input(pub File, pub fs::Metadata);
impl Input
{
fn try_from_file(file: File) -> Result<Self,InputError>
{
let stat = file.metadata().map_err(InputError::Stat)?;
Ok(Self(file,stat))
}
/// Open an input file
pub fn open(filename: impl AsRef<Path>) -> Result<Self, InputError>
{
let file = fs::OpenOptions::new()
.read(true)
.open(filename).map_err(InputError::Open)?;
Self::try_from_file(file)
}
}
/// Open all these inputs and return them.
///
/// If one or more fail, then the operation will terminate early and return the error.
pub fn input<U: AsRef<Path> + fmt::Debug, I>(inputs: I) -> Result<Vec<Input>, InputError<U>>
where I: IntoIterator<Item = U>
{
let inputs = inputs.into_iter();
let mut outputs = {
match inputs.size_hint() {
(0, Some(0)) => Vec::default(),
(0, None) => Vec::new(),
(_, Some(x)) | (x, None) => Vec::with_capacity(x),
}
};
for input in inputs
{
outputs.push(Input::open(&input)
.map_err(move |inner| InputError::WithData(Box::new(inner), input))?);
}
Ok(outputs)
}
#[derive(Debug)]
#[non_exhaustive]
pub enum InputError<T = std::convert::Infallible>
where T: fmt::Debug
{
Open(io::Error),
Stat(io::Error),
WithData(Box<InputError>, T),
}
impl<T> error::Error for InputError<T>
where T: fmt::Debug
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
match &self {
Self::Open(io) | Self::Stat(io) => Some(io),
Self::WithData(inner, _) => inner.source(),
}
}
}
impl<T> fmt::Display for InputError<T>
where T: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Open(io) => write!(f, "failed to open file for reading: {}", io),
Self::Stat(io) => write!(f, "failed to stat file: {}", io),
Self::WithData(inner, msg) => write!(f, "for {:?}: {}", msg, inner),
}
}
}

Loading…
Cancel
Save