1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use super::super::provider::{Provider, WriteRequester}; use super::super::*; use std::fmt::Debug; use std::io::{Read, Result as IoResult, Write}; use std::path::Path; use diff; pub trait TextDiffExtension { fn text_writer<N>(&self, filename: N) -> Writer where N: AsRef<Path>; fn text<N, S>(&self, filename: N, text: S) -> IoResult<()> where N: AsRef<Path>, S: AsRef<str>, { let mut w = self.text_writer(filename); write!(w, "{}", text.as_ref()) } fn debug<N, D>(&self, filename: N, object: D) -> IoResult<()> where N: AsRef<Path>, D: Debug, { let mut w = self.text_writer(filename); write!(w, "{:#?}", object) } } impl TextDiffExtension for Provider { fn text_writer<S>(&self, filename: S) -> Writer where S: AsRef<Path>, { self.custom_test( filename, |a, b| text_eq(a, b), |a, b, c, d| text_diff(a, b, c, d), ) } } fn text_eq<R1: Read, R2: Read>(mut r1: R1, mut r2: R2) -> IoResult<bool> { let mut v1 = Vec::new(); let mut v2 = Vec::new(); r1.read_to_end(&mut v1)?; r2.read_to_end(&mut v2)?; Ok(v1 == v2) } fn add_extension(p: &Path, new_ext: &str) -> PathBuf { let old_ext = match p.extension() { Some(e) => e.to_string_lossy().into_owned(), None => "".to_owned(), }; p.with_extension(format!("{}{}", old_ext, new_ext)) } fn text_diff<R1: Read, R2: Read>( mut r1: R1, mut r2: R2, path: &Path, write_requester: &mut WriteRequester, ) -> IoResult<()> { let mut s1 = String::new(); let mut s2 = String::new(); r1.read_to_string(&mut s1)?; r2.read_to_string(&mut s2)?; write_requester.request(add_extension(path, ".diff"), |w| { for diff in diff::lines(&s1, &s2) { match diff { diff::Result::Left(l) => writeln!(w, "+{}", l)?, diff::Result::Both(l, _) => writeln!(w, " {}", l)?, diff::Result::Right(r) => writeln!(w, "-{}", r)?, } } Ok(()) }) }