cloudfront_logs/raw/view/
smart.rs

1use crate::shared::*;
2use std::cell::RefCell;
3
4/// View into a borrowed log line
5///
6/// Unlike [`CheckedRawLogLine`](crate::raw::CheckedRawLogLine), this struct does not compute all the fields upfront,
7/// but instead provides methods to access the fields on demand.
8///
9/// This can be useful when you need to access only one or two fields from a log line.
10/// Performance gets worse if you need to access many fields;
11/// cloning the iterator becomes more expensive compared to a pre-computed struct like [`CheckedRawLogLine`](crate::raw::CheckedRawLogLine).
12#[derive(Debug)]
13pub struct LogLineView<'a> {
14    line: &'a str,
15    iter: RefCell<MemchrTabSplitter<'a>>,
16    prev: RefCell<usize>,
17    last: RefCell<&'a str>,
18}
19
20impl<'a> LogLineView<'a> {
21    /// Creates a new `RawLogLineView` from a borrowed log line
22    ///
23    /// The line is checked for the correct number of fields and
24    /// that it's not a comment line (like the version or fields header).
25    ///
26    pub fn new(line: &'a str) -> Result<Self, &'static str> {
27        validate_line(line)?;
28
29        let iter = RefCell::new(MemchrTabSplitter::new(line));
30        let prev = RefCell::new(0);
31        let last = RefCell::new(line);
32
33        Ok(LogLineView {
34            line,
35            iter,
36            prev,
37            last,
38        })
39    }
40
41    #[inline]
42    fn field(&self, index: usize) -> &'a str {
43        use std::cmp::Ordering;
44
45        let mut prev = self.prev.borrow_mut();
46        let mut last = self.last.borrow_mut();
47
48        let v = match index.cmp(&*prev) {
49            Ordering::Greater => {
50                let rel = index - *prev - 1;
51                *prev = index;
52                self.iter.borrow_mut().nth(rel).unwrap()
53            }
54            Ordering::Equal => *last,
55            Ordering::Less => {
56                let mut iter = self.iter.borrow_mut();
57                *iter = split(self.line);
58                *prev = index;
59                iter.nth(index).unwrap()
60            }
61        };
62        *last = v;
63        v
64    }
65
66    /// Returns the date field of the log line
67    ///
68    /// This is the fallible version, though it should never fail,
69    /// as the line has been checked for the correct number of fields
70    /// when the struct was initialised
71    pub fn date(&self) -> &'a str {
72        self.field(0)
73    }
74
75    pub fn time(&self) -> &'a str {
76        self.field(1)
77    }
78
79    pub fn x_edge_location(&self) -> &'a str {
80        self.field(2)
81    }
82
83    pub fn sc_bytes(&self) -> &'a str {
84        self.field(3)
85    }
86
87    pub fn c_ip(&self) -> &'a str {
88        self.field(4)
89    }
90
91    pub fn cs_method(&self) -> &'a str {
92        self.field(5)
93    }
94
95    pub fn cs_host(&self) -> &'a str {
96        self.field(6)
97    }
98
99    pub fn cs_uri_stem(&self) -> &'a str {
100        self.field(7)
101    }
102
103    pub fn sc_status(&self) -> &'a str {
104        self.field(8)
105    }
106
107    pub fn cs_referer(&self) -> &'a str {
108        self.field(9)
109    }
110
111    pub fn cs_user_agent(&self) -> &'a str {
112        self.field(10)
113    }
114
115    pub fn cs_uri_query(&self) -> &'a str {
116        self.field(11)
117    }
118
119    pub fn cs_cookie(&self) -> &'a str {
120        self.field(12)
121    }
122
123    pub fn x_edge_result_type(&self) -> &'a str {
124        self.field(13)
125    }
126
127    pub fn x_edge_request_id(&self) -> &'a str {
128        self.field(14)
129    }
130
131    pub fn x_host_header(&self) -> &'a str {
132        self.field(15)
133    }
134
135    pub fn cs_protocol(&self) -> &'a str {
136        self.field(16)
137    }
138
139    pub fn cs_bytes(&self) -> &'a str {
140        self.field(17)
141    }
142
143    pub fn time_taken(&self) -> &'a str {
144        self.field(18)
145    }
146
147    pub fn x_forwarded_for(&self) -> &'a str {
148        self.field(19)
149    }
150
151    pub fn ssl_protocol(&self) -> &'a str {
152        self.field(20)
153    }
154
155    pub fn ssl_cipher(&self) -> &'a str {
156        self.field(21)
157    }
158
159    pub fn x_edge_response_result_type(&self) -> &'a str {
160        self.field(22)
161    }
162
163    pub fn cs_protocol_version(&self) -> &'a str {
164        self.field(23)
165    }
166
167    pub fn fle_status(&self) -> &'a str {
168        self.field(24)
169    }
170
171    pub fn fle_encrypted_fields(&self) -> &'a str {
172        self.field(25)
173    }
174
175    pub fn c_port(&self) -> &'a str {
176        self.field(26)
177    }
178
179    pub fn time_to_first_byte(&self) -> &'a str {
180        self.field(27)
181    }
182
183    pub fn x_edge_detailed_result_type(&self) -> &'a str {
184        self.field(28)
185    }
186
187    pub fn sc_content_type(&self) -> &'a str {
188        self.field(29)
189    }
190
191    pub fn sc_content_len(&self) -> &'a str {
192        self.field(30)
193    }
194
195    pub fn sc_range_start(&self) -> &'a str {
196        self.field(31)
197    }
198
199    pub fn sc_range_end(&self) -> &'a str {
200        self.field(32)
201    }
202}