Basic question: Extending File. Is this the correct way?


#1

Hi,

I am new to rust and learning too.

I am trying to extend File by having a new method implemented to it. I want to know whether my approach is correct or not?

trait ReadInto {
    fn read_into_array(&self) -> Vec<String>;
}

impl ReadInto for File {
    fn read_into_array(&self) -> Vec<String> {
        let buf = BufReader::new(self);
        buf.lines().map(|l| l.expect("Could not parse line")).collect()
    }
}

#2

Yes, that’s how you’d extend it.

I wouldn’t call it read_into_array though: You’re using vectors here, not arrays.


#3

Thanks. Yes I should change the name.


#4

Please have a look at this:
https://doc.rust-lang.org/std/convert/trait.Into.html

You could try to write this:

impl Into<Vec<String>> for &File {
//...
}

(We implement it for &File because we don’t consume the file. You’d probably also have to fiddle around with lifetimes to make this compile.)

However, this is forbidden in Rust: You may only implement your own traits for external types, and you may implement external traits for your own types, but you can’t implement external traits for external types.
I think this may be a hint from the Rust gods, that it is not how to do it. Not everything has to be a trait and not everything has to be a “method”. Sometimes a simple function is the idiomatic answer. Do you have any function, which needs a parameter type to implement ReadInto? Like

fn do_something<T:ReadInto>(a: T, b: i32) -> whatever

If there is no such function (or anything related), I think it would be simpler and more idiomatic to just create a function and use it directly. Like this:

fn read_file_to_string_vec(f: &File) -> Vec<String>