pcap_processor/tshark/
validator.rs1use crate::error::{PcapError, Result};
2use crate::tshark::TsharkRunner;
3use glob::glob;
4use std::path::PathBuf;
5
6pub struct TsharkValidator<'a> {
7 runner: &'a TsharkRunner,
8 field_cache: Option<String>,
9}
10
11impl<'a> TsharkValidator<'a> {
12 pub fn new(runner: &'a TsharkRunner) -> Self {
13 Self {
14 runner,
15 field_cache: None,
16 }
17 }
18
19 pub fn validate_field(&mut self, field: &str) -> Result<()> {
20 let fields = match &self.field_cache {
21 Some(cache) => cache.clone(),
22 None => {
23 let fields = self.runner.get_field_list()?;
24 self.field_cache = Some(fields.clone());
25 fields
26 }
27 };
28
29 let field_pattern = format!("\t{}\t", field);
32 if fields.contains(&field_pattern) {
33 return Ok(());
34 }
35
36 for line in fields.lines() {
38 let parts: Vec<&str> = line.split('\t').collect();
39 if parts.len() >= 3 && parts[2] == field {
40 return Ok(());
41 }
42 }
43
44 Err(PcapError::InvalidField {
45 field: field.to_string(),
46 })
47 }
48
49 pub fn validate_filter(&self, filter: &str) -> Result<()> {
50 self.runner.validate_filter(filter)
51 }
52
53 pub fn expand_files(&self, patterns: &[String]) -> Result<Vec<PathBuf>> {
54 let mut files = Vec::new();
55
56 for pattern in patterns {
57 if pattern.contains('*') || pattern.contains('?') || pattern.contains('[') {
59 let matches: Vec<_> = glob(pattern)
60 .map_err(|e| PcapError::FileRead {
61 path: PathBuf::from(pattern),
62 message: e.to_string(),
63 })?
64 .filter_map(|r| r.ok())
65 .collect();
66
67 if matches.is_empty() {
68 return Err(PcapError::NoFilesMatched {
69 pattern: pattern.clone(),
70 });
71 }
72
73 files.extend(matches);
74 } else {
75 let path = PathBuf::from(pattern);
76 if !path.exists() {
77 return Err(PcapError::FileNotFound { path });
78 }
79 files.push(path);
80 }
81 }
82
83 if files.is_empty() {
84 return Err(PcapError::NoFilesMatched {
85 pattern: patterns.join(", "),
86 });
87 }
88
89 Ok(files)
90 }
91}