stdin / stdout
Closed this issue · 8 comments
Implement reading and writing streams
@mbhall88 how would i go about implementing fastq::Reader::from_file(filename)
with stdin
- is there an idiomatic way in rust-bio
?
Oh man, it's literally in the first header comments of the code:
let reader = fastq::Reader::new(io::stdin());
Hmmm but how to implement so it doesn't complain about different types assigned to reader in the match arms:
let reader = match cli.value_of("fastq") {
Some(filename) => fastq::Reader::from_file(filename).expect("Error"),
None | Some("-") => fastq::Reader::new(io::stdin())
};
i.e. expected struct std::fs::File, found struct std::io::Stdin
You need to indicate that your reader
implements the trait Read
.
use std::env;
use std::fs;
use std::io::{self, BufReader, Read};
use bio::io::fastq;
fn main() {
let input = env::args().nth(1);
let handle: Box<dyn Read> = match input {
Some(filename) if filename != "-" => Box::new(fs::File::open(filename).unwrap()),
_ => Box::new(BufReader::new(io::stdin())),
};
let reader = fastq::Reader::new(handle);
for record in reader.records() {
match record {
Ok(r) => println!("{:?}", r),
_ => println!("Bad record")
}
}
}
This is adapted as a combination of this SO answer and my own Fastx
implementation in rasusa
.
Right ok and the Box
has to do with how to allocate the type to memory? Why is that necessary? Thanks so much for taking the time!
I changed this now to
let input_handle: Box<dyn Read> = match cli.value_of("fastq") {
Some(filename) => Box::new(fs::File::open(filename).unwrap()),
None => Box::new(BufReader::new(io::stdin()))
};
Very nice!
Box
is a smart pointer. Basically, Rust wants to know how much memory to allocate (and where to allocate it stack/heap) during compilation (hence its memory safety). Because we are saying the return value just needs to implement the trait Read
, the object being returned could theoretically be of any size. Therefore it is going to need to be allocated memory from the heap. From the always-wonderful documentation in the rust book about Box
.
[When to use a
Box<T>
] When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type
NB: It would be nice to allow for being verbose about stdin with "-"
in your implementation.
Dude that's a great explanation. I was trying to figure this out. I'll add the conditional to add the "-"
back into it. Thanks heaps!