use super::{TokenKind, detect};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Finding {
kind: TokenKind,
start: usize,
end: usize,
}
impl Finding {
#[must_use]
pub fn kind(&self) -> TokenKind {
self.kind
}
#[must_use]
pub fn start(&self) -> usize {
self.start
}
#[must_use]
pub fn end(&self) -> usize {
self.end
}
}
#[must_use]
pub fn scan(text: &str) -> Vec<Finding> {
let mut findings = Vec::new();
let mut offset = 0;
for line in text.split_inclusive('\n') {
let trimmed = line.trim();
if let Some(kind) = detect(trimmed).filter(|kind| *kind == TokenKind::PrivateKey) {
let start = offset + line.find(trimmed).unwrap_or(0);
findings.push(Finding {
kind,
start,
end: start + trimmed.len(),
});
} else {
let mut word_start = None;
for (i, c) in line
.char_indices()
.chain(std::iter::once((line.len(), ' ')))
{
let in_word = c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | '.');
match (word_start, in_word) {
(None, true) => word_start = Some(i),
(Some(start), false) => {
if let Some(kind) = detect(&line[start..i]) {
findings.push(Finding {
kind,
start: offset + start,
end: offset + i,
});
}
word_start = None;
}
_ => {}
}
}
}
offset += line.len();
}
findings
}
#[cfg(test)]
#[path = "scan.test.rs"]
mod tests;
#[cfg(test)]
#[path = "scan.spec.rs"]
mod spec;