/sub_cursor

This library provides a SubCursor, that allows to only have access to parts of a reader or writer.

Primary LanguageRust

sub_cursor

Crates.io: sub_cursor Documentation Build Status Code Coverage License: Apache License: MIT

What is a SubCursor?

You can think of a SubCursor as slices for Readers or Writers.

Why?

A SubCursor provides a more efficient way, to handle data in apis.

Let's imagine you have an archive, that requires files:

use std::io::{self, Cursor, Read, Seek};

pub struct Archive<T> {
    files: Vec<T>,
}

impl<T: Read + Seek> Archive<T> {
    pub fn new() -> Self {
        Self {
            files: vec![]
        }
    }

    pub fn push(&mut self, value: T) {
        self.files.push(value)
    }
}

fn main() -> io::Result<()> {
    let mut archive = Archive::new();
    // imagine, that these are Files instead of Cursor
    archive.push(Cursor::new(b"This is an example file".to_vec()));
    archive.push(Cursor::new(b"This is another example file".to_vec()));

    Ok(())
}

Now you have a single file, that contains many smaller files (for example a .zip) and you want to add them to the Archive, without reading the entire file into memory and wrapping each of them in a Cursor. This can be achieved with a SubCursor, which is like slices, but for Reader and Writeer.

use std::io::{self, Seek, Read, Cursor};
use std::sync::{Arc, Mutex};

use sub_cursor::SubCursor;

pub struct Archive<T> {
    files: Vec<T>,
}

impl<T: Read + Seek> Archive<T> {
    pub fn new() -> Self {
        Self {
            files: vec![]
        }
    }

    pub fn push(&mut self, value: T) {
        self.files.push(value)
    }

    pub fn print_files(&mut self) -> io::Result<()> {
        for file in &mut self.files {
            let mut string = String::new();
            file.read_to_string(&mut string)?;
            println!("{}", string);
        }
        Ok(())
    }
}

fn main() -> io::Result<()> {
    let mut archive = Archive::new();

    archive.push(SubCursor::from(b"This is an example file".to_vec()));
    archive.push(SubCursor::from(b"This is another example file".to_vec()));

    let file = Arc::new(Mutex::new(Cursor::new(b"file1,file2,file3".to_vec())));

    archive.push(
        SubCursor::from(file.clone())
            // first file starts at index 0
            .start(0)
            // and ends at 5
            .end(5)
    );

    archive.push(
        SubCursor::from(file.clone())
            .start(7)
            .end(11)
    );

    archive.push(
        // the end will be set automatically
        SubCursor::from(file.clone()).start(12)
    );

    archive.print_files()?;

    Ok(())
}

Usage

Add the following to your Cargo.toml:

[dependencies]
sub_cursor = "0.1"

Documentation

You can find the documentation here.

Inspiration

This project is loosely inspired by slice.

License

This project is licensed under either of

at your option.