use std::error::Error; use std::fmt; use std::io; use std::ops::Deref; use symbols::Symbol; #[derive(Debug)] pub enum FileError { ExecError(E), GenericError } impl From for FileError { fn from(err: io::Error) -> FileError { FileError::ExecError(err) } } impl Error for FileError { fn description(&self) -> &str { match self { &FileError::ExecError(ref e) => e.description(), &FileError::GenericError => "Generic error" } } fn cause(&self) -> Option<&Error> { match self { &FileError::ExecError(ref e) => Some(e), _ => None } } } impl fmt::Display for FileError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "{}", self.description()) } } use std::convert::AsRef; pub struct File where C: Deref, D: AsRef + fmt::Display { path: D, content: C } impl File where C: Deref, D: AsRef + fmt::Display { pub fn new(path: D, content: C) -> Self { File { path: path, content: content } } } use std::fs::File as FsFile; use std::io::{Read, Write}; impl Symbol for File where C: Deref, D: AsRef + fmt::Display { type Error = FileError; fn target_reached(&self) -> Result { let file = FsFile::open(self.path.as_ref()); // Check if file exists if let Err(e) = file { return if e.kind() == io::ErrorKind::NotFound { Ok(false) } else { Err(e.into()) }; } // Check if content is the same let file_content = file.unwrap().bytes(); let content_equal = try!(self.content.bytes().zip(file_content).fold( Ok(true), |state, (target_byte, file_byte_option)| state.and_then(|s| file_byte_option.map(|file_byte| s && file_byte == target_byte)) )); return Ok(content_equal) } fn execute(&self) -> Result<(), Self::Error> { //try!(self.command_runner.run_with_args("mkdir", &["-p", Path::new(&path).parent().unwrap().to_str().unwrap()])); // FIXME: Permissions // try!(create_dir_all(Path::new(&path).parent().unwrap())); try!(try!(FsFile::create(self.path.as_ref())).write_all(self.content.as_bytes())); Ok(()) } } impl fmt::Display for File where C: Deref, D: AsRef + fmt::Display { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ write!(f, "File {}", self.path) } }