Help with std::File


#1

Help with std::File

I’m relatively new to rust and I’m trying to write a formatter of sorts for a blog project . The idea is that it will take 4 different pieces of an html doc and then format them all into a single doc based on the template provided.

extern crate strfmt;
extern crate pandoc;

use strfmt::strfmt;

use std::io;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

struct Post {
    head: Option<String>,
    header: Option<String>,
    body: Option<String>,
    footer: Option<String>,
    template: Option<String>,
}

impl Post {
    fn new() -> Post {
        Post {
            head: None,
            header: None,
            body: None,
            footer: None,
            template: None,
        }
    }
    
    fn head(mut self, path: &str) -> Post {
        let mut file_string = String::new();
        
        match File::open(path) {
            Ok(v)   => v.read_to_string(&mut file_string),
            Err(e)  => panic!("Unable to open head file!"),
        }
        self.head = Some(file_string);
        self
    }
}

fn main() {
    let mut args: Vec<String> = env::args().collect();
    args.remove(0);

    for arg in args {
        println!("{}", arg);
    }

    let mut fmt = String::new();
    let mut vars = HashMap::new();
    let mut file = try!(File::open("html/head.html"));

    vars.insert("PageTitle".to_string(), "This is a test a formatter!");
    file.read_to_string(&mut fmt);

    let fmtd = strfmt(&fmt, &vars).unwrap();
    println!("{}", fmtd);
}

Upon trying to build, I get the following error and it makes very little sense to me:

   Compiling kryll v0.1.0 (file:///home/mike/Development/Rust/Cargo%20Projects/kryll)
error[E0308]: match arms have incompatible types
  --> src/main.rs:31:9
   |
31 |         match File::open(path) {
   |         ^ expected enum `std::result::Result`, found ()
   |
   = note: expected type `std::result::Result<usize, std::io::Error>`
   = note:    found type `()`
note: match arm with an incompatible type
  --> <std macros>:2:1
   |
2  | {
   | ^
src/main.rs:33:24: 33:59 note: in this expansion of panic! (defined in <std macros>)

error[E0308]: mismatched types
 --> <std macros>:5:8
  |
5 | return $ crate :: result :: Result :: Err (
  |        ^ expected (), found enum `std::result::Result`
src/main.rs:50:20: 50:54 note: in this expansion of try! (defined in <std macros>)
  |
  = note: expected type `()`
  = note:    found type `std::result::Result<_, _>`

error: aborting due to 2 previous errors

error: Could not compile `kryll`.

In the second error it states that it cannot use try!() on the result of File::open() because it returns std::result::Result<_, _> and not (), but in the first error it’s completely the opposite. What’s going on here?


#2

First error tells you that your expressions in match do not return the same type. First arm returns Result<usize>, and second arm returns (). A straightforward fix would be like:

match File::open(path) {
    Ok(v)   => { v.read_to_string(&mut file_string); },
    Err(e)  => panic!("Unable to open head file!"),
}

But you should check the result returned by read_to_string function by wrapping it in try!(), calling unwrap(), another match or something else.

The second error happens because you can only use try! only inside functions that return Result. It implicitly tries to return Result but compiler only allows to return ().


#3

Muchas Gracias