Skip to content

Commit a5b0add

Browse files
authored
Merge pull request #42 from farodin91/file-content-predicate
Implement a file content predicate
2 parents efd199b + 363c2cd commit a5b0add

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

src/path/fc.rs

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2018 The predicates-rs Project Developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use std::fmt;
10+
use std::fs;
11+
use std::io::{self, Read};
12+
use std::path;
13+
14+
use Predicate;
15+
16+
/// Predicate adaper that converts a `path` to file content predicate to byte predicate.
17+
///
18+
/// This is created by `pred.from_path()`.
19+
#[derive(Clone, Debug)]
20+
pub struct FileContentPredicate<P>
21+
where
22+
P: Predicate<[u8]>,
23+
{
24+
p: P,
25+
}
26+
27+
impl<P> FileContentPredicate<P>
28+
where
29+
P: Predicate<[u8]>,
30+
{
31+
fn eval(&self, path: &path::Path) -> io::Result<bool> {
32+
let mut buffer = Vec::new();
33+
34+
// read the whole file
35+
fs::File::open(path)?.read_to_end(&mut buffer)?;
36+
Ok(self.p.eval(&buffer))
37+
}
38+
}
39+
40+
impl<P> fmt::Display for FileContentPredicate<P>
41+
where
42+
P: Predicate<[u8]>,
43+
{
44+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45+
write!(f, "{}", self.p)
46+
}
47+
}
48+
49+
impl<P> Predicate<path::Path> for FileContentPredicate<P>
50+
where
51+
P: Predicate<[u8]>,
52+
{
53+
fn eval(&self, path: &path::Path) -> bool {
54+
self.eval(path).unwrap_or(false)
55+
}
56+
}
57+
58+
/// `Predicate` extension adapting a `slice` Predicate.
59+
pub trait PredicateFileContentExt
60+
where
61+
Self: Predicate<[u8]>,
62+
Self: Sized,
63+
{
64+
/// Returns a `FileContentPredicate` that adapts `Self` to a file content `Predicate`.
65+
///
66+
/// # Examples
67+
///
68+
/// ```
69+
/// use predicates::prelude::*;
70+
/// use std::path::Path;
71+
///
72+
/// let predicate_fn = predicate::str::is_empty().not().from_utf8().from_file_path();
73+
/// assert_eq!(true, predicate_fn.eval(Path::new("./tests/hello_world")));
74+
/// assert_eq!(false, predicate_fn.eval(Path::new("./tests/empty_file")));
75+
/// ```
76+
fn from_file_path(self) -> FileContentPredicate<Self> {
77+
FileContentPredicate { p: self }
78+
}
79+
}
80+
81+
impl<P> PredicateFileContentExt for P
82+
where
83+
P: Predicate<[u8]>,
84+
{
85+
}

src/path/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ mod existence;
1414
pub use self::existence::{exists, missing, ExistencePredicate};
1515
mod ft;
1616
pub use self::ft::{is_dir, is_file, is_symlink, FileTypePredicate};
17+
mod fc;
18+
pub use self::fc::{FileContentPredicate, PredicateFileContentExt};

src/prelude.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
pub use core::Predicate;
1212
pub use boolean::PredicateBooleanExt;
1313
pub use boxed::PredicateBoxExt;
14+
pub use path::PredicateFileContentExt;
1415
pub use str::PredicateStrExt;
1516
pub use name::PredicateNameExt;
1617

tests/empty_file

Whitespace-only changes.

tests/hello_world

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World!

0 commit comments

Comments
 (0)