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