I am attempting to read values from a file in order to create a struct, and I'm getting a weird pair of errors. A super basic implementation of my code:
extern crate itertools;
use itertools::Itertools;
use std::io::{self, prelude::*, BufReader};
use std::fs::{self, File};
// The struct I will unpack into
struct BasicExample {
a: String,
b: String,
c: String,
d: String,
}
impl BasicExample {
pub fn new(a: String, b: String, c: String, d: String} -> Self {
BasicExample {
a, b, c, d
}
}
// I'm expecting that reading from the config file might fail, so
// I want to return a Result that can be unwrapped. Otherwise an Err
// will be returned with contained value being &'static str
pub fn from_config(filename: &str) -> io::Result<Self, &'static str> {
let file = File::open(filename).expect("Could not open file");
// read args into a Vec<String>, consuming file
let args: Vec<String> = read_config(file);
// I transfer ownership away from args here
let params: Option<(String, String, String, String)> = args.drain(0..4).tuples().next();
// Then I want to match and return, I could probably do if-let here
// but I don't have my hands around the base concept yet, so I'll
// leave that for later
match params {
Some((a, b, c, d)) => Ok(BasicExample::new(a, b, c, d)),
_ => Err("Could not read values into struct")
}
}
fn read_config(file: File) -> Vec<String> {
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Could not parse line"))
.collect()
}
}
Running cargo check
to make sure I didn't miss anything, I get the following error:
error[E0107]: wrong number of type arguments: expected 1, found 2
--> src/lib.rs:37:60
|
37 | pub fn from_config(filename: &str) -> io::Result<Self, &'static str> {
| ^^^^^^^^^^^^ unexpected type argument
error: aborting due to previous error
For more information about this error, try `rustc --explain E0107`.
Seems a bit odd. io::Result
should take <T, E>
, and I've given it E
, so let's remove that type argument and see what happens:
error[E0308]: mismatched types
--> src/lib.rs:54:22
|
54 | _ => Err("Could not read values into AzureAuthentication struct"),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::io::Error`, found reference
|
= note: expected type `std::io::Error`
found type `&'static str`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
For some reason it is really not happy with the E
I provided. I'm a complete beginner with rust, so maybe I'm just not sure what I'm looking at. What am I doing wrong here? The itertools
ownership trick was borrowed (ha) from this wonderful answer.
System Details:
- macOS 10.13.6
- rustc 1.36.0 (a53f9df32 2019-07-03)
- cargo 1.36.0 (c4fcfb725 2019-05-15)
std::io::Result
? You will find that it actually takes only a single type parameter. – TenonResult
, hence "Expected io::Error" – Cormstd::io
means that the nameResult
is safe from shadowing, I just wasn't paying attention. In my code, I even notedio::Result
– Corm