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