use super::Handler;
use crate::{error, path::Path};
use std::{fs, io::Write};
pub struct File {
file: fs::File,
use_path: bool,
separator: String,
}
impl File {
pub fn new(fs_path: &str) -> Result<Self, error::Handler> {
let file = fs::File::create(fs_path).map_err(|err| error::Handler::new(err.to_string()))?;
Ok(Self {
file,
use_path: false,
separator: "\n".into(),
})
}
pub fn set_use_path(mut self, use_path: bool) -> Self {
self.use_path = use_path;
self
}
pub fn set_separator<S>(mut self, separator: S) -> Self
where
S: ToString,
{
self.separator = separator.to_string();
self
}
}
impl Handler for File {
fn use_path(&self) -> bool {
self.use_path
}
fn separator(&self) -> &str {
&self.separator
}
fn handle(
&mut self,
path: &Path,
_matcher_idx: usize,
data: Option<&[u8]>,
) -> Result<Option<Vec<u8>>, error::Handler> {
if self.use_path {
self.file
.write(format!("{}: ", path).as_bytes())
.map_err(|err| error::Handler::new(err.to_string()))?;
}
self.file
.write(data.unwrap())
.map_err(|err| error::Handler::new(err.to_string()))?;
let separator = self.separator().to_string();
self.file
.write(separator.as_bytes())
.map_err(|err| error::Handler::new(err.to_string()))?;
Ok(None)
}
}
#[cfg(test)]
mod tests {
use crate::{handler, matcher, strategy};
use std::{
fs, str,
sync::{Arc, Mutex},
};
use tempfile::NamedTempFile;
fn make_output(
path: &str,
matcher: matcher::Simple,
handler: handler::File,
input: &[u8],
) -> String {
let handler = Arc::new(Mutex::new(handler));
let mut trigger = strategy::Trigger::new();
trigger.add_matcher(Box::new(matcher), &[handler]);
trigger.process(input).unwrap();
fs::read_to_string(path).unwrap()
}
#[test]
fn basic() {
let tmp_path = NamedTempFile::new().unwrap().into_temp_path();
let str_path = tmp_path.to_str().unwrap();
let matcher = matcher::Simple::new(r#"{"aa"}[]"#).unwrap();
let handler = handler::File::new(str_path).unwrap();
let output = make_output(
str_path,
matcher,
handler,
br#"{"aa": [1, 2, "u"], "b": true}"#,
);
assert_eq!(
output,
str::from_utf8(
br#"1
2
"u"
"#
)
.unwrap()
);
}
#[test]
fn separator() {
let tmp_path = NamedTempFile::new().unwrap().into_temp_path();
let str_path = tmp_path.to_str().unwrap();
let matcher = matcher::Simple::new(r#"{"aa"}[]"#).unwrap();
let handler = handler::File::new(str_path).unwrap().set_separator("XXX");
let output = make_output(
str_path,
matcher,
handler,
br#"{"aa": [1, 2, "u"], "b": true}"#,
);
assert_eq!(output, str::from_utf8(br#"1XXX2XXX"u"XXX"#).unwrap());
}
#[test]
fn use_path() {
let tmp_path = NamedTempFile::new().unwrap().into_temp_path();
let str_path = tmp_path.to_str().unwrap();
let matcher = matcher::Simple::new(r#"{"aa"}[]"#).unwrap();
let handler = handler::File::new(str_path).unwrap().set_use_path(true);
let output = make_output(
str_path,
matcher,
handler,
br#"{"aa": [1, 2, "u"], "b": true}"#,
);
assert_eq!(
output,
str::from_utf8(
br#"{"aa"}[0]: 1
{"aa"}[1]: 2
{"aa"}[2]: "u"
"#
)
.unwrap()
);
}
}