Hello! I'm newbie in rust so I meet some issues due to try to implement application that would parse some files. I have Format trait that describe parsed format somehow and create Reader object that is responsible for provide some data from file.
Please help me compile the code and understand how to correctly write such kind of application.
So the parameted R does not live long enough errors can be fixed by changing R: blah to R: blah + 'static
However, this error here:
impl<R: io::Read + 'static> Format for Csv<R>
{
fn reader(&self) -> Box<dyn Reader>
{
Box::new(self.reader)
}
}
I'm not sure what you intention is for fixing this. The problem is Box::new(...) wants to own the argument passed to it, but we only have a ref to self, so we only have a ref to self.reader.
What is best way to implement such hierarchy of objects. I just need detect format, return instance of Format and then get Reader from it. Later I would like to read records using the reader. Perhaps it should be Iterator implementation
(needless to say, this is not idiomatic / suggested Rust style; just the result of manually fixing compile errors w/ the first idea that comes to mind)
The task is following. I have several trace files with different formats (all of them are CSV-like but with
different columns). I need to write a command line tool that gets one file, detect its format (which columns are there), read all record one by one and send each record to some destination (for example db or socket).
The code you fixed is compiled! Thanks!
Could you describe what is idiomatic way to solve the issue, please?
Do not build too many abstractions. How large are the files? Are all formats text based? Is there a fixed set of formats?
From your description I would have a struct CSVReader, a trait DataRead with a read method, a DataFormat enum with a detect_format(&str) -> Self method and a send_data<T: DataRead> function. Your main could look like this
fn main() {
let file_contents = fs::read_to_string(file_path);
match detect_format(file_contents) {
DataFormat::CSV => send_data(CSVReader::new(file_contents)),
_ => todo!()
}
}
Certainly enough for a small CLI if your files are small enough.
Thanks a lot for suggestion. But I would like to understand how to make objects hierarchy. Main idea of the example is create entities which have some relationships. Here are Factory->Format->Reader. So Factory create formats with detect method. Each format provide it own reader. Reader return it own record
Later new formats can be added. One file can be big - more than 4 GB.
Sounds like you might be describing inheritance. Rust does have some object oriented features like encapsulation and associated methods, but inheritance is not one of them.
Rust doesn't lend itself well to traditional object oriented code with inheritance and what comes along with that, namely factories.
To be more precise, what Rust doesn’t have is implementation inheritance.
If your hierarchy is only made (except for the last child / leafs ) of pure virtual class / interface / class with only function but no attribute, then you can model your hierarchy using trait without issue. If your original hierarchy had attributes in any of the parents class, you will have to change the design. But keep also in mind that most class hierarchy can be replaced by enum.
class Animal {…};
class Cat: Animal {…};
class BlackCat: Cat {…};