1use std::borrow::Cow;
2
3use rust_decimal::{Decimal, prelude::ToPrimitive};
4
5use crate::parse::token::{
6 Comment as ParsedComment, Field as ParsedField, Flag as ParsedFlag,
7 InlineComment as ParsedInlineComment, Value as ParsedValue,
8};
9
10#[derive(Clone, PartialEq, Debug)]
11pub enum Token<'a> {
15 Field(Field<'a>),
16 Flag(Flag<'a>),
17 Comment {
18 is_inline: bool,
19 inner: Cow<'a, str>,
20 },
21}
22
23impl<'input> From<&ParsedField<'input>> for Token<'input> {
24 fn from(field: &ParsedField<'input>) -> Self {
25 Self::Field(field.into())
26 }
27}
28
29impl<'input> From<&ParsedFlag<'input>> for Token<'input> {
30 fn from(flag: &ParsedFlag<'input>) -> Self {
31 Self::Flag(flag.into())
32 }
33}
34
35impl<'a, 'input: 'a> From<&'a ParsedInlineComment<'input>> for Token<'input> {
36 fn from(comment: &'a ParsedInlineComment<'input>) -> Self {
37 Self::Comment {
38 is_inline: true,
39 inner: Cow::Borrowed(
40 comment
41 .inner
42 .strip_prefix('(')
43 .unwrap()
44 .strip_suffix(')')
45 .unwrap(),
46 ),
47 }
48 }
49}
50
51impl<'input> From<&ParsedComment<'input>> for Token<'input> {
52 fn from(comment: &ParsedComment<'input>) -> Self {
53 Self::Comment {
54 is_inline: false,
55 inner: Cow::Borrowed(comment.inner.strip_prefix(';').unwrap()),
56 }
57 }
58}
59
60#[derive(Clone, PartialEq, Debug)]
64pub struct Field<'a> {
65 pub letters: Cow<'a, str>,
66 pub value: Value<'a>,
67}
68
69impl<'input> From<&ParsedField<'input>> for Field<'input> {
70 fn from(field: &ParsedField<'input>) -> Self {
71 Self {
72 letters: field.letters.into(),
73 value: Value::from(&field.value),
74 }
75 }
76}
77
78impl<'a> From<Field<'a>> for Token<'a> {
79 fn from(field: Field<'a>) -> Token<'a> {
80 Self::Field(field)
81 }
82}
83
84impl Field<'_> {
85 pub fn into_owned(self) -> Field<'static> {
89 Field {
90 letters: self.letters.into_owned().into(),
91 value: self.value.into_owned(),
92 }
93 }
94}
95
96#[derive(Clone, PartialEq, Debug)]
97pub struct Flag<'a> {
98 pub letter: Cow<'a, str>,
99}
100
101impl<'input> From<&ParsedFlag<'input>> for Flag<'input> {
102 fn from(flag: &ParsedFlag<'input>) -> Self {
103 Self {
104 letter: flag.letter.into(),
105 }
106 }
107}
108
109#[derive(Clone, PartialEq, Debug)]
114pub enum Value<'a> {
115 Rational(Decimal),
116 Float(f64),
117 Integer(usize),
118 String(Cow<'a, str>),
119}
120
121impl Value<'_> {
122 pub fn as_f64(&self) -> Option<f64> {
126 match self {
127 Self::Rational(r) => r.to_f64(),
128 Self::Integer(i) => Some(*i as f64),
129 Self::Float(f) => Some(*f),
130 Self::String(_) => None,
131 }
132 }
133
134 pub fn into_owned(self) -> Value<'static> {
138 match self {
139 Self::String(s) => Value::String(s.into_owned().into()),
140 Self::Rational(r) => Value::Rational(r),
141 Self::Integer(i) => Value::Integer(i),
142 Self::Float(f) => Value::Float(f),
143 }
144 }
145}
146
147impl<'input> From<&ParsedValue<'input>> for Value<'input> {
148 fn from(val: &ParsedValue<'input>) -> Self {
149 use ParsedValue::*;
150 match val {
151 Rational(r) => Self::Rational(*r),
152 Integer(i) => Self::Integer(*i),
153 String(s) => {
154 Self::String(Cow::Borrowed(
156 s.strip_prefix('"').unwrap().strip_suffix('"').unwrap(),
157 ))
158 }
159 }
160 }
161}