file_wrap 0.2.0

Quite simply, a trait for structs that represent a file
Documentation
#[cfg(feature = "use_failure")]
#[macro_use] extern crate failure_derive;

#[cfg(feature = "use_failure")]
use std::io;
use std::{
    path::Path,
    fs::File,
    io::{
        Read,
        Write,
    }
};

pub trait FromFile : Sized {
    #[cfg(feature = "use_failure")]
    fn from_file(path: &Path) -> Result<Self, Failure> {
        let mut file_handle = match File::open(path) {
            Ok(handle) => handle,
            Err(cause) => return Err(Failure::FileOpenError { cause }),
        };

        let mut file_contents = Vec::new();

        match file_handle.read_to_end(&mut file_contents) {
            Ok(_i) => (),
            Err(cause) => return Err(Failure::FileReadError { cause }),
        }

        match Self::deserialize(&file_contents) {
            Ok(data) => Ok(data),
            Err(cause) => Err(Failure::DeserializationError { cause }),
        }
    }

    #[cfg(not(feature = "use_failure"))]
    fn from_file(path: &Path) -> Result<Self, String> {
        let mut file_handle = match File::open(path) {
            Ok(handle) => handle,
            Err(cause) => return Err(String::from(format!("failed to open file: {}", cause))),
        };

        let mut file_contents = Vec::new();

        match file_handle.read_to_end(&mut file_contents) {
            Ok(_i) => (),
            Err(cause) => return Err(String::from(format!("failed to read file: {}", cause))),
        }

        match Self::deserialize(&file_contents) {
            Ok(data) => Ok(data),
            Err(cause) => Err(String::from(format!("failed to create file: {}", cause))),
        }
    }

    #[cfg(feature = "use_failure")]
    fn deserialize(data: &Vec<u8>) -> Result<Self, failure::Error>;
    #[cfg(not(feature = "use_failure"))]
    fn deserialize(data: &Vec<u8>) -> Result<Self, String>;
}

pub trait ToFile : Sized {
    #[cfg(feature = "use_failure")]
    fn to_file(&self, path: &Path) -> Result<(), Failure> {
        let mut file_handle = match File::create(path){
            Ok(handle) => handle,
            Err(cause) => return Err(Failure::FileOpenError { cause }),
        };

        let mut file_contents = match self.serialize() {
            Ok(bytes) => bytes,
            Err(cause) => return Err(Failure::SerializationError { cause }),
        };

        match file_handle.write_all(&mut file_contents) {
            Ok(()) => (),
            Err(cause) => return Err(Failure::FileWriteError { cause }),
        }

        match file_handle.flush() {
            Ok(()) => Ok(()),
            Err(cause) => Err(Failure::FileFlushError { cause }),
        }
    }

    #[cfg(not(feature = "use_failure"))]
    fn to_file(&self, path: &Path) -> Result<(), String> {
        let mut file_handle = match File::create(path){
            Ok(handle) => handle,
            Err(cause) => return Err(String::from(format!("failed to create file: {}", cause))),
        };

        let mut file_contents = match self.serialize() {
            Ok(bytes) => bytes,
            Err(cause) => return Err(String::from(format!("failed to serialize data: {}", cause))),
        };

        match file_handle.write_all(&mut file_contents) {
            Ok(()) => (),
            Err(cause) => return Err(String::from(format!("failed to serialize data: {}", cause))),
        }

        match file_handle.flush() {
            Ok(()) => Ok(()),
            Err(cause) => Err(String::from(format!("failed to serialize data: {}", cause))),
        }
    }

    #[cfg(feature = "use_failure")]
    fn serialize(&self) -> Result<Vec<u8>, failure::Error>;
    #[cfg(not(feature = "use_failure"))]
    fn serialize(&self) -> Result<Vec<u8>, String>;
}

#[cfg(feature = "use_failure")]
#[derive(Debug, Fail)]
pub enum Failure {
    #[fail(display = "error flushing to file: {}", cause)]
    FileFlushError {
        #[cause] cause: io::Error,
    },
    #[fail(display = "error opening file: {}", cause)]
    FileOpenError {
        #[cause] cause: io::Error,
    },
    #[fail(display = "error reading from file: {}", cause)]
    FileReadError {
        #[cause] cause: io::Error,
    },
    #[fail(display = "error writing to file: {}", cause)]
    FileWriteError {
        #[cause] cause: io::Error,
    },
    #[fail(display = "error deserializing data: {}", cause)]
    DeserializationError {
        #[cause] cause: failure::Error,
    },
    #[fail(display = "error serializing data: {}", cause)]
    SerializationError {
        #[cause] cause: failure::Error,
    },
}