sambia39
sambia39

Reputation: 35

Some errors E0425 & E0599 write_fmt

mod loginfo{

    use std::io::Error;
    use chrono::prelude::*;
    use std::io::prelude::*;
    use std::fs::OpenOptions;

    const LOG_SYS :&'static str = "log.txt";
    const LOG_ERR :&'static str = "log_error.txt";

    pub fn set_log_error(info: String)->Result<(), String>{
        let mut handler = OpenOptions::new().append(true)
            .open(LOG_ERR);
        if handler.is_err(){
            create_file(LOG_ERR.to_owned()).unwrap();
            set_log_error(info).unwrap();
        }

        if let Err(_errno) = handler.write_fmt(
            format_args!("{:?}\t{:?} ->[Last OS error({:?})]\n",
                Utc::now().to_rfc2822().to_string(), info,
                Error::last_os_error()) ){
                panic!(
                    "\nCannot write info log error\t Info\t:{:?}\n",
                    Error::last_os_error()); 
        }

        Ok(())
    }

    pub fn set_log(info: String)->Result<(), String>{

        let mut handler = OpenOptions::new().append(true)
            .open(LOG_SYS);
        if handler.is_err(){
            set_log_error("Cannot write info log".to_owned())
                .unwrap();
        }

        if let Err(_errno) = handler.write_fmt(
            format_args!("{:?}\t{:?}\n",
                Utc::now().to_rfc2822().to_string(), info)){
                set_log_error("Cannot write data log file".to_owned())
                    .unwrap();       
        }

        Ok(())
    }

    pub fn create_file(filename : String)->Result<(), String>{
        let handler = OpenOptions::new().write(true)
            .create(true).open(filename);
        if handler.is_err(){
            panic!(
                "\nCannot create log file\t Info\t:{:?}\n",
                Error::last_os_error());
        }
        Ok(())
    }
}

When compiling, I get the following errors, "error[E0599]: no method named write_fmt found for enum std::result::Result<std::fs::File, std::io::Error> in the current scope --> src/loginfo.rs:19:38`"

but despite using the right imports, I still get the same errors. Is this due to a bad implementation of the module? Thank you in advance for your answers and remarks?


+1 @Masklinn Ok I think I understand it would be easier to just write

pub fn foo_write_log( info: String){
        let mut handler = OpenOptions::new().append(true)
            .create(true).open(LOG_SYS).expect("Cannot create log");
        handler.write_fmt(
            format_args!("{:?}\t{:?} ->[Last OS error({:?})]\n",
                Utc::now().to_rfc2822().to_string(), info,
                Error::last_os_error())).unwrap();
    }

Upvotes: 0

Views: 224

Answers (1)

Masklinn
Masklinn

Reputation: 42272

but despite using the right imports, I still get the same errors. Is this due to a bad implementation of the module?

Kind-of? If you look at the type specified in the error, handler is a Result<File, Error>. And while io::Write is implemented on File, it's not implemented on Result.

The problem is that while you're checking whether handler.is_err() you never get the file out of it, nor do you ever return in the error case. Normally you'd use something like match or if let or one of the higher-order methods (e.g. Result::map, Result::and_then) in order to handle or propagate the various cases.

And to be honest the entire thing is rather odd and awkward e.g. your functions can fail but they panic instead (you never actually return an Err); if you're going to try and create a file when opening it for writing fails, why not just do that directly[0]; you are manually calling write_fmt and format_args why not just write!; write_fmt already returns an io::Error why do you discard it then ask for it again via Error::last_os_error; etc...

It's also a bit strange to hand-roll your own logger thing when the rust ecosystem already has a bunch of them though you do you; and the naming is also somewhat awkward e.g. I'd expect something called set_X to actually set the X, so to me set_log would be a way to set the file being logged to.

[0] .create(true).append(true) should open the file in append mode if it exists and create it otherwise; not to mention your version has a concurrency issue: if the open-for-append fails you create the file in write mode, but someone else could have created the file -- with content -- between the two calls, in which case you're going to partially overwrite the file

Upvotes: 2

Related Questions