Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamed Volumes #52

Merged
merged 16 commits into from
Jul 3, 2019
5 changes: 3 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ quick_error! {
cause(err)
description(err.description())
}
/// Raw data and buffer length are incompatible
IncompatibleLength {
/// Raw data buffer length and volume dimensions are incompatible
IncompatibleLength(got: usize, expected: usize) {
description("The buffer length and the header dimensions are incompatible.")
display("The buffer length ({}) and header dimensions ({} elements) are incompatible", got, expected)
}
/// Description length must be lower than or equal to 80 bytes
IncorrectDescriptionLength(len: usize) {
Expand Down
33 changes: 31 additions & 2 deletions src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ pub struct Extender([u8; 4]);

impl Extender {
/// Fetch the extender code from the given source, while expecting it to exist.
pub fn from_stream<S: Read>(mut source: S) -> Result<Self> {
#[deprecated(since = "0.8.0", note = "use `from_reader` instead")]
pub fn from_stream<S: Read>(source: S) -> Result<Self> {
Self::from_reader(source)
}

/// Fetch the extender code from the given source, while expecting it to exist.
pub fn from_reader<S: Read>(mut source: S) -> Result<Self> {
let mut extension = [0u8; 4];
source.read_exact(&mut extension)?;
Ok(extension.into())
Expand All @@ -24,7 +30,16 @@ impl Extender {
/// being possible to not be available.
/// Returns `None` if the source reaches EoF prematurely.
/// Any other I/O error is delegated to a `NiftiError`.
pub fn from_stream_optional<S: Read>(mut source: S) -> Result<Option<Self>> {
#[deprecated(since = "0.8.0", note = "use `from_reader_optional` instead")]
pub fn from_stream_optional<S: Read>(source: S) -> Result<Option<Self>> {
Self::from_reader_optional(source)
}

/// Fetch the extender code from the given source, while
/// being possible to not be available.
/// Returns `None` if the source reaches EoF prematurely.
/// Any other I/O error is delegated to a `NiftiError`.
pub fn from_reader_optional<S: Read>(mut source: S) -> Result<Option<Self>> {
let mut extension = [0u8; 4];
match source.read_exact(&mut extension) {
Ok(()) => Ok(Some(extension.into())),
Expand Down Expand Up @@ -131,7 +146,21 @@ impl<'a> IntoIterator for &'a ExtensionSequence {

impl ExtensionSequence {
/// Read a sequence of extensions from a source, up until `len` bytes.
#[deprecated(since = "0.8.0", note = "use `from_reader` instead")]
pub fn from_stream<S, E>(
extender: Extender,
source: ByteOrdered<S, E>,
len: usize,
) -> Result<Self>
where
S: Read,
E: Endian,
{
Self::from_reader(extender, source, len)
}

/// Read a sequence of extensions from a source, up until `len` bytes.
pub fn from_reader<S, E>(
extender: Extender,
mut source: ByteOrdered<S, E>,
len: usize,
Expand Down
31 changes: 17 additions & 14 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::io::{BufReader, Read};
use std::ops::Deref;
use std::path::Path;
use typedef::*;
use util::is_gz_file;
use util::{is_gz_file, validate_dim, validate_dimensionality};

/// Magic code for NIFTI-1 header files (extention ".hdr[.gz]").
pub const MAGIC_CODE_NI1: &'static [u8; 4] = b"ni1\0";
Expand Down Expand Up @@ -226,16 +226,27 @@ impl NiftiHeader {
let gz = is_gz_file(&path);
let file = BufReader::new(File::open(path)?);
if gz {
NiftiHeader::from_stream(GzDecoder::new(file))
NiftiHeader::from_reader(GzDecoder::new(file))
} else {
NiftiHeader::from_stream(file)
NiftiHeader::from_reader(file)
}
}

/// Read a NIfTI-1 header, along with its byte order, from the given byte stream.
/// It is assumed that the input is currently at the start of the
/// NIFTI header.
#[deprecated(since = "0.8.0", note = "use `from_reader` instead")]
pub fn from_stream<S: Read>(input: S) -> Result<NiftiHeader> {
Self::from_reader(input)
}

/// Read a NIfTI-1 header, along with its byte order, from the given byte stream.
/// It is assumed that the input is currently at the start of the
/// NIFTI header.
pub fn from_reader<S>(input: S) -> Result<NiftiHeader>
where
S: Read,
{
parse_header_1(input)
}

Expand All @@ -248,12 +259,7 @@ impl NiftiHeader {
/// `NiftiError::InconsistentDim` if `dim[0]` does not represent a valid
/// dimensionality, or any of the real dimensions are zero.
pub fn dim(&self) -> Result<&[u16]> {
let ndim = self.dimensionality()?;
let o = &self.dim[1..ndim + 1];
if let Some(i) = o.into_iter().position(|&x| x == 0) {
return Err(NiftiError::InconsistentDim(i as u8, self.dim[i]));
}
Ok(o)
validate_dim(&self.dim)
}

/// Retrieve and validate the number of dimensions of the volume. This is
Expand All @@ -263,11 +269,8 @@ impl NiftiHeader {
///
/// `NiftiError::` if `dim[0]` does not represent a valid dimensionality
/// (it must be positive and not higher than 7).
pub fn dimensionality(&self) -> Result <usize> {
if self.dim[0] == 0 || self.dim[0] > 7 {
return Err(NiftiError::InconsistentDim(0, self.dim[0]));
}
Ok(usize::from(self.dim[0]))
pub fn dimensionality(&self) -> Result<usize> {
validate_dimensionality(&self.dim)
}

/// Get the data type as a validated enum.
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ pub mod typedef;
mod util;

pub use error::{NiftiError, Result};
pub use object::{NiftiObject, InMemNiftiObject};
pub use object::{NiftiObject, InMemNiftiObject, StreamedNiftiObject};
pub use extension::{Extender, Extension, ExtensionSequence};
pub use header::{NiftiHeader, NiftiHeaderBuilder};
pub use volume::{NiftiVolume, InMemNiftiVolume, Sliceable};
pub use volume::{NiftiVolume, RandomAccessNiftiVolume, InMemNiftiVolume, StreamedNiftiVolume, Sliceable};
pub use volume::element::DataElement;
#[cfg(feature = "ndarray_volumes")] pub use volume::ndarray::IntoNdArray;
pub use typedef::{NiftiType, Unit, Intent, XForm, SliceOrder};
Expand Down
Loading