1use super::ast::{Span, Spanned};
2use rust_decimal::Decimal;
3use std::cmp::PartialEq;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Field<'input> {
8 pub(crate) letters: &'input str,
9 pub(crate) value: Value<'input>,
10 pub(crate) raw_value: Vec<&'input str>,
11 pub(crate) span: Span,
12}
13
14impl<'input> Field<'input> {
15 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> {
17 self.letters
18 .as_bytes()
19 .iter()
20 .chain(self.raw_value.iter().flat_map(|s| s.as_bytes().iter()))
21 }
22}
23
24impl<'input> Spanned for Field<'input> {
25 fn span(&self) -> Span {
26 self.span
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub struct Flag<'input> {
32 pub(crate) letter: &'input str,
33 pub(crate) span: Span,
34}
35
36impl<'input> Flag<'input> {
37 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> {
39 self.letter.as_bytes().iter()
40 }
41}
42
43impl<'input> Spanned for Flag<'input> {
44 fn span(&self) -> Span {
45 self.span
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum Value<'input> {
51 Rational(Decimal),
58 Integer(usize),
61 String(&'input str),
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct Checksum {
70 pub(crate) inner: u8,
74 pub(crate) span: Span,
75}
76
77impl Spanned for Checksum {
78 fn span(&self) -> Span {
79 self.span
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct Newline {
86 pub(crate) pos: usize,
87}
88
89impl Spanned for Newline {
90 fn span(&self) -> Span {
91 Span(self.pos, self.pos + 1)
92 }
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct Percent {
98 pub(crate) pos: usize,
99}
100
101impl Spanned for Percent {
102 fn span(&self) -> Span {
103 Span(self.pos, self.pos + 1)
104 }
105}
106
107#[derive(Debug, Clone, PartialEq, Eq)]
108pub struct Whitespace<'input> {
110 pub(crate) inner: &'input str,
111 pub(crate) pos: usize,
112}
113
114impl<'input> Whitespace<'input> {
115 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> {
116 self.inner.as_bytes().iter()
117 }
118}
119
120impl<'input> Spanned for Whitespace<'input> {
121 fn span(&self) -> Span {
122 Span(self.pos, self.pos + self.inner.len())
123 }
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct Comment<'input> {
135 pub(crate) inner: &'input str,
136 pub(crate) pos: usize,
137}
138
139impl<'input> Comment<'input> {
140 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> {
141 self.inner.as_bytes().iter()
142 }
143}
144
145impl<'input> Spanned for Comment<'input> {
146 fn span(&self) -> Span {
147 Span(self.pos, self.pos + self.inner.len())
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq)]
157pub struct InlineComment<'input> {
158 pub(crate) inner: &'input str,
159 pub(crate) pos: usize,
160}
161
162impl<'input> InlineComment<'input> {
163 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> {
164 self.inner.as_bytes().iter()
165 }
166}
167
168impl<'input> Spanned for InlineComment<'input> {
169 fn span(&self) -> Span {
170 Span(self.pos, self.pos + self.inner.len())
171 }
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, Default)]
175pub struct LineComponent<'input> {
177 pub(crate) field: Option<Field<'input>>,
178 pub(crate) flag: Option<Flag<'input>>,
179 pub(crate) whitespace: Option<Whitespace<'input>>,
180 pub(crate) inline_comment: Option<InlineComment<'input>>,
181}
182
183impl<'input> LineComponent<'input> {
184 pub fn iter_bytes(&'input self) -> impl Iterator<Item = &'input u8> + 'input {
185 self.field
186 .iter()
187 .flat_map(|f| f.iter_bytes())
188 .chain(self.flag.iter().flat_map(|f| f.iter_bytes()))
189 .chain(self.whitespace.iter().flat_map(|w| w.iter_bytes()))
190 .chain(self.inline_comment.iter().flat_map(|i| i.iter_bytes()))
191 }
192}