I am porting some Python to Rust as a learning exercise and need to take input from either a file or stdin. I keep a handle to my input in a struct so I thought I'd just make a Box<io::Read>
but I ran into a situation where I need to seek on the input, and seek
isn't part of the Read
trait. I know you can't seek in pipes, so I'm going ahead and assuming for now that this method only gets called when the input is a file, but my problem is that I can't check that and downcast in Rust.
I know that I could use an enum for the two input types, but it seems like there should be a more elegant way to do this. And that's my question, how do you do this and not make a mess?
Is it possible to wrap stdin or a file in the same sort of buffer so I could just use that type and not worry about the type of IO?
I know, you said you wanted something more elegant and without enums, but I think the enum-solution is fairly elegant. So here is one attempt:
Put code like that in some sub module of yours and don't worry about it too much anymore. You can use an object of type
Input
just like you would use aFile
: you have to handle seek errors anyway, so handling the inability to seek by stdin should be super easy. An example:That's exactly what the trait
Read
does. It seems that what you want is an abstraction (trait) forStdin
andFile
that has optional support forseek
and allows to query about this support. In the following code,OptionalSeekRead
trait is used to fulfill this intend: