1use std::ops::Range;
4
5#[derive(Debug, Clone)]
7pub struct Line {
8 pub no: u64,
9 pub bytes: Vec<u8>,
10}
11
12impl Line {
13 pub fn new(no: u64, bytes: Vec<u8>) -> Self {
14 Self { no, bytes }
15 }
16
17 pub fn as_str_lossy(&self) -> std::borrow::Cow<'_, str> {
19 String::from_utf8_lossy(&self.bytes)
20 }
21}
22
23#[derive(Debug, Default, Clone)]
25pub struct MatchInfo {
26 pub hit: bool,
28 pub spans: Vec<Range<usize>>,
30 pub col: Option<usize>,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum Role {
37 Target,
39 Context,
41}
42
43#[derive(Debug, Clone)]
45pub struct Emit<'a> {
46 pub line: &'a Line,
47 pub role: Role,
48 pub match_info: &'a MatchInfo,
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn line_as_str_lossy_handles_invalid_utf8() {
57 let line = Line::new(1, vec![0xFF, b'a']);
58 let s = line.as_str_lossy();
59 assert!(s.ends_with('a'));
60 }
61
62 #[test]
63 fn match_info_default_is_miss() {
64 let mi = MatchInfo::default();
65 assert!(!mi.hit);
66 assert!(mi.spans.is_empty());
67 assert!(mi.col.is_none());
68 }
69}