Home > Blockchain >  Does Rust have equivalent Stream classes like in Java?
Does Rust have equivalent Stream classes like in Java?

Time:04-25

I am learning Rust by writing a simple ZIP handler. It works well, and I am happy with it. However, I want to return a Java like Stream for the extract_file() functionality.

Currently I am returning a Vec, which can be done by both STORE and DEFLATE pathways. (no compression and compressed).

However, I can't find a class or Trait that I can return for both these options where I don't pre-read the whole input data.

I am looking for a equivalent to Java's IO Streams:

Stream fileStream;
if (stored) {
  return fileStream;
} else if (deflate) {
  return DeflateStream(fileStream);
}

Any pointers?

CodePudding user response:

The std::io::Read and std::io::Write traits. They are implemented for files, TCP streams, and more. See std::io's docs for more.

CodePudding user response:

Rust prefers to use the std::io::Read and std::io::Write traits for this. Additionally you will probably want to also add a requirement on std::io::Seek so you can move your cursor within the byte stream.

Here is the general idea:

// Wrap around another Read type so we can use it as we parse
pub struct Deflater<R> {
    stream: R,
}

impl<R> Deflater<R> {
    pub fn new(stream: R) -> Self {
        Deflater { stream }
    }
}

// We provide our own Read implementation which can then refer to our inner Read type
impl<R: Read> Read for Deflater<R> {
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        // Just defer to our inner read
        self.stream.read(buffer)
    }
}

As for your example, since we need to know a concrete type we have 2 approaches. We can either create an enum for it or use it as an anonymous trait.

fn box_approach<'a, R: 'a   Read>(file_stream: R, stored: bool, deflate: bool) -> Box<dyn 'a   Read> {
    if stored {
        return Box::new(file_stream)
    } else if deflate {
        return Box::new(Deflater::new(file_stream))
    }
    
    panic!("Must be either stored or deflate!")
}

fn enum_approach<R>(file_stream: R, stored: bool, deflate: bool) -> HandleStream<R> {
    if stored {
        return HandleStream::Stored(file_stream)
    } else if deflate {
        return HandleStream::Deflate(Deflater::new(file_stream))
    }
    
    panic!("Must be either stored or deflate!")
}


enum HandleStream<R> {
    Stored(R),
    Deflate(Deflater<R>),
}

impl<R: Read> Read for HandleStream<R> {
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        match self {
            HandleStream::Stored(stream) => stream.read(buffer),
            HandleStream::Deflate(deflater) => deflater.read(buffer),
        }
    }
}
  • Related