Struct npyz::NpyFile

source ·
pub struct NpyFile<R: Read> { /* private fields */ }
Expand description

Object for reading an npy file.

This type represents a partially read npy file, where the header has been parsed and we are ready to begin parsing data.

use std::fs::File;
use std::io;

let file = io::BufReader::new(File::open("./test-data/c-order.npy")?);
let npy = npyz::NpyFile::new(file)?;

// Helper methods for inspecting the layout of the data.
assert_eq!(npy.shape(), &[2, 3, 4]);
assert_eq!(npy.strides(), &[12, 4, 1]);
assert_eq!(npy.order(), npyz::Order::C);

// Get the data!
let data: Vec<i64> = npy.into_vec()?;
assert_eq!(data.len(), 24);

Working with large files

For large files, it may be undesirable to read all of the data into a Vec. The NpyFile::data method allows you to iterate over the data instead.

let npy = npyz::NpyFile::new(file)?;

let mut sum = 0;
for x in npy.data::<i64>()? {
    sum += x?;  // items are Result
}
assert_eq!(sum, 84);

Is a read adaptor too heavy for you? NpyFile is ultimately just a NpyHeader paired with its input stream, so you may consider parsing NpyHeader instead if you need something easier to clone or send.

let mut file = io::BufReader::new(File::open("./test-data/c-order.npy")?);
let header = npyz::NpyHeader::from_reader(&mut file)?;
assert_eq!(header.shape(), &[2, 3, 4]);

// now you can store `header` somewhere
// ...
// and later in your program you can construct an NpyFile to read the data

let npy = npyz::NpyFile::with_header(header, file);
let data: Vec<i64> = npy.into_vec()?;
assert_eq!(data.len(), 24);

Migrating from npy-rs 0.4.0

NpyData is still provided, but it is deprecated in favor of NpyFile. At construction, since &[u8] impls Read, you can still use them as input.

was:
    npyz::NpyData::<i64>::from_bytes(&bytes).to_vec()
now:
    npyz::NpyFile::new(&bytes[..]).into_vec::<i64>()

If you were using the iterator API of NpyData, this is now on NpyReader, which requires us to call NpyFile::data:

was:
    let iter = npyz::NpyData::<i64>::new(&bytes)?;
now:
    let iter = npyz::NpyFile::new(&bytes[..]).data::<i64>.map_err(invalid_data)?;

where the following function has been used to paper over the fact that NpyFile::data has a different Error type:

fn invalid_data<S: ToString>(err: S) -> std::io::Error {
    std::io::Error::new(std::io::ErrorKind::InvalidData, err.to_string())
}

NpyData::is_empty is gone due to possible ambiguity between NpyReader::len and NpyReader::total_len. Use the one that is appropriate for what you are doing.

If you were using NpyData::get… well, honestly, you should first consider whether you could just iterate over the reader instead. But if you were using NpyData::get because you genuinely need random access, then there is NpyReader::read_at.

was:
    // note:  0 <= i < arr.len()
    arr.get(i)
now:
    // note:  0 <= i < reader.total_len()
    reader.read_at(i)?

Implementations§

source§

impl<R: Read> NpyFile<R>

source

pub fn new(reader: R) -> Result<Self>

Read the header of an npy file and construct an NpyFile for reading the data.

source

pub fn with_header(header: NpyHeader, data_reader: R) -> Self

Construct from a previously parsed header and a reader for the raw data bytes.

source

pub fn header(&self) -> &NpyHeader

Access the underlying NpyHeader object.

source§

impl<R: Read> NpyFile<R>

source

pub fn into_vec<T: Deserialize>(self) -> Result<Vec<T>>

Read all elements into a flat Vec, in the order they are stored as.

This is a convenience wrapper around Self::data and Iterator::collect.

source

pub fn data<T: Deserialize>(self) -> Result<NpyReader<T, R>, DTypeError>

Produce an NpyReader to begin reading elements, if T can be deserialized from the file’s dtype.

The returned type implements Iterator<Item=io::Result<T>>, and provides additional methods for random access when R: Seek. See NpyReader for more details.

source

pub fn try_data<T: Deserialize>(self) -> Result<NpyReader<T, R>, Self>

Produce an NpyReader to begin reading elements, if T can be deserialized from the file’s dtype.

This fallible form of the function returns self on error, so that you can try again with a different T.

Methods from Deref<Target = NpyHeader>§

source

pub fn dtype(&self) -> DType

Get the dtype as written in the file.

source

pub fn shape(&self) -> &[u64]

Get the shape as written in the file.

source

pub fn strides(&self) -> &[u64]

Get strides for each of the dimensions.

This is the amount by which the item index changes as you move along each dimension. It is a function of both Self::order and Self::shape, provided for your convenience.

source

pub fn order(&self) -> Order

Get whether the data is in C order or fortran order.

source

pub fn len(&self) -> u64

Get the total number of elements in the file. (This is the product of Self::shape)

Trait Implementations§

source§

impl<R: Clone + Read> Clone for NpyFile<R>

source§

fn clone(&self) -> NpyFile<R>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<R: Read> Deref for NpyFile<R>

§

type Target = NpyHeader

The resulting type after dereferencing.
source§

fn deref(&self) -> &NpyHeader

Dereferences the value.

Auto Trait Implementations§

§

impl<R> RefUnwindSafe for NpyFile<R>
where R: RefUnwindSafe,

§

impl<R> Send for NpyFile<R>
where R: Send,

§

impl<R> Sync for NpyFile<R>
where R: Sync,

§

impl<R> Unpin for NpyFile<R>
where R: Unpin,

§

impl<R> UnwindSafe for NpyFile<R>
where R: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.