1use alloc::boxed::Box;
10use alloc::collections::{BTreeMap, BTreeSet};
11use alloc::vec::Vec;
12use core::fmt;
13
14#[cfg(feature = "arbitrary-nums")]
15use bigdecimal::BigDecimal;
16#[cfg(feature = "arbitrary-nums")]
17use num_bigint::BigInt;
18#[cfg(feature = "floats")]
19use ordered_float::OrderedFloat;
20
21use crate::{error, parse};
22
23#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
24#[non_exhaustive]
25pub enum Edn<'e> {
26 Vector(Vec<Edn<'e>>),
27 Set(BTreeSet<Edn<'e>>),
28 Map(BTreeMap<Edn<'e>, Edn<'e>>),
29 List(Vec<Edn<'e>>),
30 Key(&'e str),
31 Symbol(&'e str),
32 Str(&'e str),
33 Int(i64),
34 Tagged(&'e str, Box<Edn<'e>>),
35 #[cfg(feature = "floats")]
36 Double(OrderedFloat<f64>),
37 Rational((i64, i64)),
38 #[cfg(feature = "arbitrary-nums")]
39 BigInt(BigInt),
40 #[cfg(feature = "arbitrary-nums")]
41 BigDec(BigDecimal),
42 Char(char),
43 Bool(bool),
44 Nil,
45}
46
47pub fn read_string(edn: &str) -> Result<Edn<'_>, error::Error> {
53 Ok(parse::parse(edn)?.0)
54}
55
56pub fn read(edn: &str) -> Result<(Edn<'_>, &str), error::Error> {
65 let r = parse::parse(edn)?;
66 if r.0 == Edn::Nil && r.1.is_empty() {
67 return Err(error::Error {
68 code: error::Code::UnexpectedEOF,
69 line: None,
70 column: None,
71 ptr: None,
72 });
73 }
74 Ok((r.0, r.1))
75}
76
77fn get_tag<'a>(tag: &'a str, key: &'a str) -> Option<&'a str> {
78 if !key.contains('/') {
80 return None;
81 }
82
83 if !tag.starts_with(':') {
85 return None;
86 }
87 let tag = tag.get(1..)?;
88 Some(tag)
89}
90
91fn check_key<'a>(tag: &'a str, key: &'a str) -> &'a str {
92 if key.starts_with(tag) {
94 let (_, key) = key.rsplit_once(tag).expect("Tag must exist, because it starts with it.");
95
96 if let Some(k) = key.strip_prefix('/') {
98 return k;
99 }
100 }
101 key
102}
103
104impl Edn<'_> {
105 pub fn get(&self, e: &Self) -> Option<&Self> {
106 if let Edn::Map(m) = self {
107 return m.get(e);
108 } else if let Edn::Tagged(tag, m) = self {
109 if let Edn::Key(key) = e {
110 let tag = get_tag(tag, key)?;
111 let key = check_key(tag, key);
112
113 return m.get(&Edn::Key(key));
114 }
115
116 return m.get(e);
118 }
119 None
120 }
121 pub fn nth(&self, i: usize) -> Option<&Self> {
122 let vec = match self {
123 Edn::Vector(v) => v,
124 Edn::List(l) => l,
125 _ => return None,
126 };
127
128 vec.get(i)
129 }
130
131 pub fn contains(&self, e: &Self) -> bool {
132 match self {
133 Edn::Map(m) => m.contains_key(e),
134 Edn::Tagged(tag, m) => {
135 if let Edn::Key(key) = e {
136 let Some(tag) = get_tag(tag, key) else { return false };
137 let key = check_key(tag, key);
138
139 return m.contains(&Edn::Key(key));
140 }
141
142 m.contains(e)
144 }
145 Edn::Vector(v) => v.contains(e),
146 Edn::Set(s) => s.contains(e),
147 Edn::List(l) => l.contains(e),
148 _ => false,
149 }
150 }
151}
152
153pub(crate) const fn char_to_edn(c: char) -> Option<&'static str> {
154 match c {
155 '\n' => Some("newline"),
156 '\r' => Some("return"),
157 ' ' => Some("space"),
158 '\t' => Some("tab"),
159 _ => None,
160 }
161}
162
163impl fmt::Display for Edn<'_> {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 match self {
166 Self::Vector(v) => {
167 write!(f, "[")?;
168 let mut it = v.iter().peekable();
169 while let Some(i) = it.next() {
170 if it.peek().is_some() {
171 write!(f, "{i} ")?;
172 } else {
173 write!(f, "{i}")?;
174 }
175 }
176 write!(f, "]")
177 }
178 Self::Set(s) => {
179 write!(f, "#{{")?;
180 let mut it = s.iter().peekable();
181 while let Some(i) = it.next() {
182 if it.peek().is_some() {
183 write!(f, "{i} ")?;
184 } else {
185 write!(f, "{i}")?;
186 }
187 }
188 write!(f, "}}")
189 }
190 Self::Map(m) => {
191 write!(f, "{{")?;
192 let mut it = m.iter().peekable();
193 while let Some(kv) = it.next() {
194 if it.peek().is_some() {
195 write!(f, "{} {}, ", kv.0, kv.1)?;
196 } else {
197 write!(f, "{} {}", kv.0, kv.1)?;
198 }
199 }
200 write!(f, "}}")
201 }
202 Self::List(l) => {
203 write!(f, "(")?;
204 let mut it = l.iter().peekable();
205 while let Some(i) = it.next() {
206 if it.peek().is_some() {
207 write!(f, "{i} ")?;
208 } else {
209 write!(f, "{i}")?;
210 }
211 }
212 write!(f, ")")
213 }
214 Self::Symbol(sy) => write!(f, "{sy}"),
215 Self::Tagged(t, s) => write!(f, "#{t} {s}"),
216 Self::Key(k) => write!(f, ":{k}"),
217 Self::Str(s) => write!(f, "\"{s}\""),
218 Self::Int(i) => write!(f, "{i}"),
219 #[cfg(feature = "floats")]
220 Self::Double(d) => write!(f, "{d}"),
221 #[cfg(feature = "arbitrary-nums")]
222 Self::BigInt(bi) => write!(f, "{bi}N"),
223 #[cfg(feature = "arbitrary-nums")]
224 Self::BigDec(bd) => write!(f, "{bd}M"),
225 Self::Rational((n, d)) => write!(f, "{n}/{d}"),
226 Self::Bool(b) => write!(f, "{b}"),
227 Self::Char(c) => {
228 write!(f, "\\")?;
229 if let Some(c) = char_to_edn(*c) {
230 return write!(f, "{c}");
231 }
232 write!(f, "{c}")
233 }
234 Self::Nil => write!(f, "nil"),
235 }
236 }
237}