edn_rs/edn/
mod.rs

1use alloc::boxed::Box;
2use alloc::collections::BTreeMap;
3#[cfg(feature = "sets")]
4use alloc::collections::BTreeSet;
5use alloc::string::{String, ToString};
6use alloc::vec::Vec;
7use alloc::{fmt, format};
8#[cfg(feature = "sets")]
9use core::cmp::{Ord, PartialOrd};
10use core::convert::{Infallible, TryFrom};
11use core::num;
12
13use crate::deserialize::parse::{self};
14use utils::index::Index;
15
16#[cfg(feature = "sets")]
17use ordered_float::OrderedFloat;
18
19#[doc(hidden)]
20pub mod utils;
21
22/// `EdnType` is an Enum with possible values for an EDN type
23/// Symbol and Char are not yet implemented
24/// String implementation of Edn can be obtained with `.to_string()`
25#[derive(Debug, Clone, PartialEq)]
26#[cfg_attr(feature = "sets", derive(Eq, PartialOrd, Ord))]
27#[non_exhaustive]
28pub enum Edn {
29    Tagged(String, Box<Self>),
30    Vector(Vector),
31    #[cfg(feature = "sets")]
32    Set(Set),
33    Map(Map),
34    List(List),
35    Key(String),
36    Symbol(String),
37    Str(String),
38    Int(i64),
39    UInt(u64),
40    Double(Double),
41    Rational(String),
42    Char(char),
43    Bool(bool),
44    Nil,
45    Empty,
46}
47
48#[derive(Clone, Ord, Debug, Eq, PartialEq, PartialOrd, Hash)]
49#[cfg(feature = "sets")]
50pub struct Double(pub(crate) OrderedFloat<f64>);
51
52#[derive(Clone, Debug, PartialEq)]
53#[cfg(not(feature = "sets"))]
54pub struct Double(f64);
55
56impl fmt::Display for Double {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{}", self.0)
59    }
60}
61
62#[cfg(feature = "sets")]
63impl Double {
64    fn to_float(&self) -> f64 {
65        self.0.into_inner()
66    }
67}
68
69#[cfg(not(feature = "sets"))]
70impl Double {
71    const fn to_float(&self) -> f64 {
72        self.0
73    }
74}
75
76#[cfg(feature = "sets")]
77impl From<f64> for Double {
78    fn from(f: f64) -> Self {
79        Self(OrderedFloat(f))
80    }
81}
82
83#[cfg(not(feature = "sets"))]
84impl From<f64> for Double {
85    fn from(f: f64) -> Self {
86        Self(f)
87    }
88}
89
90#[derive(Debug, Clone, PartialEq)]
91#[cfg_attr(feature = "sets", derive(Eq, PartialOrd, Ord))]
92pub struct Vector(Vec<Edn>);
93impl Vector {
94    #[must_use]
95    pub const fn new(v: Vec<Edn>) -> Self {
96        Self(v)
97    }
98
99    #[must_use]
100    pub const fn empty() -> Self {
101        Self(Vec::new())
102    }
103
104    #[must_use]
105    pub fn to_vec(self) -> Vec<Edn> {
106        self.0
107    }
108}
109
110#[derive(Debug, Clone, PartialEq)]
111#[cfg_attr(feature = "sets", derive(Eq, PartialOrd, Ord))]
112pub struct List(Vec<Edn>);
113impl List {
114    #[must_use]
115    pub const fn new(v: Vec<Edn>) -> Self {
116        Self(v)
117    }
118
119    #[must_use]
120    pub const fn empty() -> Self {
121        Self(Vec::new())
122    }
123
124    #[must_use]
125    pub fn to_vec(self) -> Vec<Edn> {
126        self.0
127    }
128}
129
130#[cfg(feature = "sets")]
131#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
132pub struct Set(BTreeSet<Edn>);
133
134#[cfg(feature = "sets")]
135impl Set {
136    #[must_use]
137    pub const fn new(v: BTreeSet<Edn>) -> Self {
138        Self(v)
139    }
140
141    #[must_use]
142    pub const fn empty() -> Self {
143        Self(BTreeSet::new())
144    }
145
146    #[must_use]
147    pub fn to_set(self) -> BTreeSet<Edn> {
148        self.0
149    }
150}
151
152#[derive(Debug, Clone, PartialEq)]
153#[cfg_attr(feature = "sets", derive(Eq, PartialOrd, Ord))]
154pub struct Map(BTreeMap<String, Edn>);
155impl Map {
156    #[must_use]
157    pub const fn new(m: BTreeMap<String, Edn>) -> Self {
158        Self(m)
159    }
160
161    #[must_use]
162    pub const fn empty() -> Self {
163        Self(BTreeMap::new())
164    }
165
166    #[must_use]
167    pub fn to_map(self) -> BTreeMap<String, Edn> {
168        self.0
169    }
170}
171
172impl core::fmt::Display for Vector {
173    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174        write!(f, "[")?;
175        let mut it = self.0.iter().peekable();
176        while let Some(i) = it.next() {
177            if it.peek().is_some() {
178                write!(f, "{i} ")?;
179            } else {
180                write!(f, "{i}")?;
181            }
182        }
183        write!(f, "]")
184    }
185}
186
187impl core::fmt::Display for List {
188    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189        write!(f, "(")?;
190        let mut it = self.0.iter().peekable();
191        while let Some(i) = it.next() {
192            if it.peek().is_some() {
193                write!(f, "{i} ")?;
194            } else {
195                write!(f, "{i}")?;
196            }
197        }
198        write!(f, ")")
199    }
200}
201
202#[cfg(feature = "sets")]
203impl core::fmt::Display for Set {
204    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
205        write!(f, "#{{")?;
206        let mut it = self.0.iter().peekable();
207        while let Some(i) = it.next() {
208            if it.peek().is_some() {
209                write!(f, "{i} ")?;
210            } else {
211                write!(f, "{i}")?;
212            }
213        }
214        write!(f, "}}")
215    }
216}
217
218impl core::fmt::Display for Map {
219    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
220        write!(f, "{{")?;
221        let mut it = self.0.iter().peekable();
222        while let Some(kv) = it.next() {
223            if it.peek().is_some() {
224                write!(f, "{} {}, ", kv.0, kv.1)?;
225            } else {
226                write!(f, "{} {}", kv.0, kv.1)?;
227            }
228        }
229        write!(f, "}}")
230    }
231}
232
233fn char_to_edn(c: char) -> String {
234    match c {
235        '\n' => "\\newline".to_string(),
236        '\r' => "\\return".to_string(),
237        ' ' => "\\space".to_string(),
238        '\t' => "\\tab".to_string(),
239        _ => format!("\\{c}"),
240    }
241}
242
243impl core::fmt::Display for Edn {
244    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
245        let text = match self {
246            Self::Vector(v) => format!("{v}"),
247            #[cfg(feature = "sets")]
248            Self::Set(s) => format!("{s}"),
249            Self::Map(m) => format!("{m}"),
250            Self::List(l) => format!("{l}"),
251            Self::Symbol(sy) => sy.clone(),
252            Self::Key(k) => k.clone(),
253            Self::Str(s) => format!("{s:?}"),
254            Self::Int(i) => format!("{i}"),
255            Self::UInt(u) => format!("{u}"),
256            Self::Double(d) => format!("{d}"),
257            Self::Rational(r) => r.clone(),
258            Self::Bool(b) => format!("{b}"),
259            Self::Char(c) => char_to_edn(*c),
260            Self::Nil => String::from("nil"),
261            Self::Empty => String::new(),
262            Self::Tagged(tag, edn) => format!("#{tag} {edn}"),
263        };
264        write!(f, "{text}")
265    }
266}
267
268impl Edn {
269    /// `to_float` takes an `Edn` and returns an `Option<f64>` with its value. Most types return None
270    /// ```rust
271    /// use edn_rs::edn::{Edn, Vector};
272    ///
273    /// let key = Edn::Key(String::from(":1234"));
274    /// let q = Edn::Rational(String::from("3/4"));
275    /// let i = Edn::Int(12i64);
276    ///
277    /// assert_eq!(Edn::Vector(Vector::empty()).to_float(), None);
278    /// assert_eq!(key.to_float().unwrap(),1234f64);
279    /// assert_eq!(q.to_float().unwrap(), 0.75f64);
280    /// assert_eq!(i.to_float().unwrap(), 12f64);
281    /// ```
282    #[must_use]
283    pub fn to_float(&self) -> Option<f64> {
284        match self {
285            Self::Key(k) => k.replace(':', "").parse::<f64>().ok(),
286            Self::Str(s) => s.parse::<f64>().ok(),
287            Self::Int(i) => to_double(i).ok(),
288            Self::UInt(u) => to_double(u).ok(),
289            Self::Double(d) => Some(d.to_float()),
290            Self::Rational(r) => rational_to_double(r),
291            _ => None,
292        }
293    }
294
295    /// `to_int` takes an `Edn` and returns an `Option<i64>` with its value. Most types return None
296    /// ```rust
297    /// use edn_rs::edn::{Edn, Vector};
298    ///
299    /// let key = Edn::Key(String::from(":1234"));
300    /// let q = Edn::Rational(String::from("3/4"));
301    /// let f = Edn::Double(12.3f64.into());
302    ///
303    /// assert_eq!(Edn::Vector(Vector::empty()).to_float(), None);
304    /// assert_eq!(key.to_int().unwrap(),1234i64);
305    /// assert_eq!(q.to_int().unwrap(), 1i64);
306    /// assert_eq!(f.to_int().unwrap(), 12i64);
307    /// ```
308    #[must_use]
309    pub fn to_int(&self) -> Option<i64> {
310        match self {
311            Self::Key(k) => k.replace(':', "").parse::<i64>().ok(),
312            Self::Str(s) => s.parse::<i64>().ok(),
313            Self::Int(i) => Some(*i),
314            #[allow(clippy::cast_possible_wrap)]
315            Self::UInt(u) if i64::try_from(*u).is_ok() => Some(*u as i64),
316            #[allow(clippy::cast_possible_truncation)]
317            #[cfg(feature = "std")]
318            Self::Double(d) => Some((*d).to_float().round() as i64),
319            #[allow(clippy::cast_possible_truncation)]
320            #[cfg(feature = "std")]
321            Self::Rational(r) => Some(rational_to_double(r).unwrap_or(0f64).round() as i64),
322            _ => None,
323        }
324    }
325
326    /// Similar to `to_int` but returns an `Option<u64>`
327    #[must_use]
328    pub fn to_uint(&self) -> Option<u64> {
329        match self {
330            Self::Str(s) => s.parse::<u64>().ok(),
331            #[allow(clippy::cast_sign_loss)]
332            Self::Int(i) if i > &0 => Some(*i as u64),
333            Self::UInt(i) => Some(*i),
334            #[cfg(feature = "std")]
335            Self::Double(d) if d.to_float() > 0f64 =>
336            {
337                #[allow(clippy::cast_sign_loss)]
338                #[allow(clippy::cast_possible_truncation)]
339                Some((*d).to_float().round() as u64)
340            }
341            #[cfg(feature = "std")]
342            Self::Rational(r) if !r.contains('-') =>
343            {
344                #[allow(clippy::cast_sign_loss)]
345                #[allow(clippy::cast_possible_truncation)]
346                Some(rational_to_double(r)?.round() as u64)
347            }
348            _ => None,
349        }
350    }
351
352    /// `to_bool` takes an `Edn` and returns an `Option<bool>` with its value. Most types return None
353    /// ```rust
354    /// use edn_rs::edn::{Edn};
355    ///
356    /// let b = Edn::Bool(true);
357    /// let s = Edn::Str("true".to_string());
358    /// let symbol = Edn::Symbol("false".to_string());
359    ///
360    /// assert_eq!(b.to_bool().unwrap(),true);
361    /// assert_eq!(s.to_bool().unwrap(),true);
362    /// assert_eq!(symbol.to_bool().unwrap(),false);
363    /// ```
364    #[must_use]
365    pub fn to_bool(&self) -> Option<bool> {
366        match self {
367            Self::Bool(b) => Some(*b),
368            Self::Str(s) | Self::Symbol(s) => s.parse::<bool>().ok(),
369            _ => None,
370        }
371    }
372
373    /// `to_char` takes an `Edn` and returns an `Option<char>` with its value. Most types return None
374    /// ```rust
375    /// use edn_rs::edn::{Edn};
376    ///
377    /// let c = Edn::Char('c');
378    /// let symbol = Edn::Symbol("false".to_string());
379    ///
380    /// assert_eq!(c.to_char().unwrap(),'c');
381    /// assert_eq!(symbol.to_char(), None);
382    /// ```
383    #[must_use]
384    pub const fn to_char(&self) -> Option<char> {
385        match self {
386            Self::Char(c) => Some(*c),
387            _ => None,
388        }
389    }
390
391    /// `to_vec` converts `Edn` types `Vector`, `List` and `Set` into an `Option<Vec<String>>`.
392    /// Type String was selected because it is the current way to mix floats, integers and Strings.
393    #[must_use]
394    pub fn to_vec(&self) -> Option<Vec<String>> {
395        match self {
396            Self::Vector(_) => Some(
397                self.iter_some()?
398                    .map(|e| match e {
399                        Self::Str(s) => s.clone(),
400                        _ => e.to_string(),
401                    })
402                    .collect::<Vec<String>>(),
403            ),
404            Self::List(_) => Some(
405                self.iter_some()?
406                    .map(|e| match e {
407                        Self::Str(s) => s.clone(),
408                        _ => e.to_string(),
409                    })
410                    .collect::<Vec<String>>(),
411            ),
412            #[cfg(feature = "sets")]
413            Self::Set(_) => Some(
414                self.iter_some()?
415                    .map(|e| match e {
416                        Self::Str(s) => s.clone(),
417                        _ => e.to_string(),
418                    })
419                    .collect::<Vec<String>>(),
420            ),
421            _ => None,
422        }
423    }
424
425    /// `to_int_vec` converts `Edn` types `Vector` `List` and `Set` into an `Option<Vec<i64>>`.
426    /// All elements of this Edn structure should be of the same type
427    #[must_use]
428    pub fn to_int_vec(&self) -> Option<Vec<i64>> {
429        match self {
430            Self::Vector(_) if !self.iter_some()?.any(|e| e.to_int().is_none()) => Some(
431                self.iter_some()?
432                    .map(Self::to_int)
433                    .collect::<Option<Vec<i64>>>()?,
434            ),
435            Self::List(_) if !self.iter_some()?.any(|e| e.to_int().is_none()) => Some(
436                self.iter_some()?
437                    .map(Self::to_int)
438                    .collect::<Option<Vec<i64>>>()?,
439            ),
440            #[cfg(feature = "sets")]
441            Self::Set(_) if !self.iter_some()?.any(|e| e.to_int().is_none()) => Some(
442                self.iter_some()?
443                    .map(Self::to_int)
444                    .collect::<Option<Vec<i64>>>()?,
445            ),
446            _ => None,
447        }
448    }
449
450    /// `to_uint_vec` converts `Edn` types `Vector` `List` and `Set` into an `Option<Vec<u64>>`.
451    /// All elements of this Edn structure should be of the same type
452    #[must_use]
453    pub fn to_uint_vec(&self) -> Option<Vec<u64>> {
454        match self {
455            Self::Vector(_) if !self.iter_some()?.any(|e| e.to_uint().is_none()) => Some(
456                self.iter_some()?
457                    .map(Self::to_uint)
458                    .collect::<Option<Vec<u64>>>()?,
459            ),
460            Self::List(_) if !self.iter_some()?.any(|e| e.to_uint().is_none()) => Some(
461                self.iter_some()?
462                    .map(Self::to_uint)
463                    .collect::<Option<Vec<u64>>>()?,
464            ),
465            #[cfg(feature = "sets")]
466            Self::Set(_) if !self.iter_some()?.any(|e| e.to_uint().is_none()) => Some(
467                self.iter_some()?
468                    .map(Self::to_uint)
469                    .collect::<Option<Vec<u64>>>()?,
470            ),
471            _ => None,
472        }
473    }
474
475    /// `to_float_vec` converts `Edn` types `Vector` `List` and `Set` into an `Option<Vec<f64>>`.
476    /// All elements of this Edn structure should be of the same type
477    #[must_use]
478    pub fn to_float_vec(&self) -> Option<Vec<f64>> {
479        match self {
480            Self::Vector(_) if !self.iter_some()?.any(|e| e.to_float().is_none()) => Some(
481                self.iter_some()?
482                    .map(Self::to_float)
483                    .collect::<Option<Vec<f64>>>()?,
484            ),
485            Self::List(_) if !self.iter_some()?.any(|e| e.to_float().is_none()) => Some(
486                self.iter_some()?
487                    .map(Self::to_float)
488                    .collect::<Option<Vec<f64>>>()?,
489            ),
490            #[cfg(feature = "sets")]
491            Self::Set(_) if !self.iter_some()?.any(|e| e.to_float().is_none()) => Some(
492                self.iter_some()?
493                    .map(Self::to_float)
494                    .collect::<Option<Vec<f64>>>()?,
495            ),
496            _ => None,
497        }
498    }
499
500    /// `to_bool_vec` converts `Edn` types `Vector` `List` and `Set` into an `Option<Vec<bool>>`.
501    /// All elements of this Edn structure should be of the same type
502    #[must_use]
503    pub fn to_bool_vec(&self) -> Option<Vec<bool>> {
504        match self {
505            Self::Vector(_) if !self.iter_some()?.any(|e| e.to_bool().is_none()) => Some(
506                self.iter_some()?
507                    .map(Self::to_bool)
508                    .collect::<Option<Vec<bool>>>()?,
509            ),
510            Self::List(_) if !self.iter_some()?.any(|e| e.to_bool().is_none()) => Some(
511                self.iter_some()?
512                    .map(Self::to_bool)
513                    .collect::<Option<Vec<bool>>>()?,
514            ),
515            #[cfg(feature = "sets")]
516            Self::Set(_) if !self.iter_some()?.any(|e| e.to_bool().is_none()) => Some(
517                self.iter_some()?
518                    .map(Self::to_bool)
519                    .collect::<Option<Vec<bool>>>()?,
520            ),
521            _ => None,
522        }
523    }
524
525    /// **[`std::fmt::Debug`]**
526    /// `to_debug` is a wrapper of `format!("{:?}", &self)` for `&Edn`.
527    /// ```
528    /// use edn_rs::edn::{Edn, Vector};
529    ///
530    /// let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
531    /// let expected = "Vector(Vector([Int(5), Int(6), Int(7)]))";
532    ///
533    /// assert_eq!(edn.to_debug(), expected);
534    /// ```
535    ///
536    /// While `to_string` returns a valid edn:
537    ///
538    ///  ```
539    /// use edn_rs::edn::{Edn, Vector};
540    ///
541    /// let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
542    /// let expected = "[5 6 7]";
543    ///
544    /// assert_eq!(edn.to_string(), expected);
545    /// ```
546    ///
547    #[allow(clippy::must_use_candidate)]
548    pub fn to_debug(&self) -> String {
549        format!("{self:?}")
550    }
551
552    /// Index into a EDN vector, list, set or map. A string index can be used to access a
553    /// value in a map, and a u64 index can be used to access an element of a
554    /// seqs.
555    ///
556    /// Returns `None` if the type of `self` does not match the type of the
557    /// index, for example if the index is a string and `self` is a seq or a
558    /// number. Also returns `None` if the given key does not exist in the map
559    /// or the given index is not within the bounds of the seq.
560    ///
561    /// ```rust
562    /// #[macro_use]
563    /// extern crate edn_rs;
564    /// use edn_rs::edn::{Edn, Map, Vector};
565    ///
566    /// fn main() {
567    ///     let edn = edn!([ 1 1.2 3 {false :f nil 3/4}]);
568    ///
569    ///     assert_eq!(edn[1], edn!(1.2));
570    ///     assert_eq!(edn.get(1).unwrap(), &edn!(1.2));
571    ///     assert_eq!(edn[3]["false"], edn!(:f));
572    ///     assert_eq!(edn[3].get("false").unwrap(), &Edn::Key(":f".to_string()));
573    /// }
574    /// ```
575    #[must_use]
576    pub fn get<I: Index>(&self, index: I) -> Option<&Self> {
577        index.index_into(self)
578    }
579
580    /// Mutably index into a EDN vector, set, list or map. A string index can be used to
581    /// access a value in a map, and a u64 index can be used to access an
582    /// element of a seq.
583    ///
584    /// Returns `None` if the type of `self` does not match the type of the
585    /// index, for example if the index is a string and `self` is a seq or a
586    /// number. Also returns `None` if the given key does not exist in the map
587    /// or the given index is not within the bounds of the seq.
588    ///
589    /// ```rust
590    /// #[macro_use]
591    /// extern crate edn_rs;
592    /// use edn_rs::edn::{Edn, Map, Vector};
593    ///
594    /// fn main() {
595    ///     let mut edn = edn!([ 1 1.2 3 {false :f nil 3/4}]);
596    ///
597    ///     assert_eq!(edn[1], edn!(1.2));
598    ///     assert_eq!(edn.get_mut(1).unwrap(), &edn!(1.2));
599    ///     assert_eq!(edn[3]["false"], edn!(:f));
600    ///     assert_eq!(edn[3].get_mut("false").unwrap(), &Edn::Key(":f".to_string()));
601    /// }
602    /// ```
603    #[must_use]
604    pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Self> {
605        index.index_into_mut(self)
606    }
607
608    /// `iter_some` returns an `Option<Iter<Edn>>` with `Some` for types `Edn::Vector` and `Edn::List`
609    /// Other types return `None`
610    /// ```
611    /// use edn_rs::{Edn, Vector};
612    ///
613    /// fn main() {
614    ///     let v = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
615    ///     let sum = v.iter_some().unwrap().filter(|e| e.to_int().is_some()).map(|e| e.to_int().unwrap()).sum();
616    ///
617    ///     assert_eq!(18i64, sum);
618    /// }
619    /// ```
620    #[allow(clippy::needless_doctest_main)]
621    #[must_use]
622    pub fn iter_some(&self) -> Option<core::slice::Iter<'_, Self>> {
623        match self {
624            Self::Vector(v) => Some(v.0.iter()),
625            Self::List(l) => Some(l.0.iter()),
626            _ => None,
627        }
628    }
629
630    /// `set_iter` returns am `Option<btree_set::Iter<Edn>>` with `Some` for type `Edn::Set`
631    /// Other types return `None`
632    #[cfg(feature = "sets")]
633    #[must_use]
634    pub fn set_iter(&self) -> Option<alloc::collections::btree_set::Iter<'_, Self>> {
635        match self {
636            Self::Set(s) => Some(s.0.iter()),
637            _ => None,
638        }
639    }
640
641    /// `map_iter` returns am `Option<btree_map::Iter<String, Edn>>` with `Some` for type `Edn::Map`
642    /// Other types return `None`
643    #[must_use]
644    pub fn map_iter(&self) -> Option<alloc::collections::btree_map::Iter<'_, String, Self>> {
645        match self {
646            Self::Map(m) => Some(m.0.iter()),
647            _ => None,
648        }
649    }
650
651    /// Method `to_json` allows you to convert a `edn_rs::Edn` into a JSON string. Type convertions are:
652    /// `Edn::Vector(v)` => a vector like `[value1, value2, ..., valueN]`
653    /// `Edn::Set(s)` => a vector like `[value1, value2, ..., valueN]`
654    /// `Edn::Map(map)` => a map like `{\"key1\": value1, ..., \"keyN\": valueN}`
655    /// `Edn::List(l)` => a vector like `[value1, value2, ..., valueN]`
656    /// `Edn::Key(key)` => a `camelCase` version of the `:kebab-case` keyword,
657    /// `Edn::Symbol(s)` => `\"a-simple-string\"`
658    /// `Edn::Str(s)` => `\"a simple string\"`
659    /// `Edn::Int(n)` => a number like `5`
660    /// `Edn::UInt(n)` => a number like `5`
661    /// `Edn::Double(n)` => a number like `3.14`
662    /// `Edn::Rational(r)` => a number like `0.25` for `1/4`.
663    /// `Edn::Char(c)` => a simple char `\'c\'`
664    /// `Edn::Bool(b)` => boolean options, `true` and `false`
665    /// `Edn::Inst(inst)` => a `DateTime` string like `\"2020-10-21T00:00:00.000-00:00\"`
666    /// `Edn::Uuid(uuid)` => a UUID string like `\"7a6b6722-0221-4280-865e-ad41060d53b2\"`
667    /// `Edn::Nil` => `null`
668    /// `Edn::Empty` => empty value, ` `
669    /// ```
670    /// use std::str::FromStr;
671    ///
672    /// fn complex_json() {
673    ///     let edn = "{ :people-list  [ { :first-name \"eva\", :age 22 }, { :first-name \"Julia\", :age 32.0 } ], :country-or-origin \"Brazil\", :queerentener true, :brain nil }";
674    ///     let parsed_edn : edn_rs::Edn = edn_rs::Edn::from_str(edn).unwrap();
675    ///     let actual_json = parsed_edn.to_json();
676    ///
677    ///     let expected = String::from(
678    ///         "{\"brain\": null, \"countryOrOrigin\": \"Brazil\", \"peopleList\": [{\"age\": 22, \"firstName\": \"eva\"}, {\"age\": 32.0, \"firstName\": \"Julia\"}], \"queerentener\": true}",
679    ///     );
680    ///
681    ///     assert_eq!(
682    ///         actual_json,
683    ///         expected
684    ///     );
685    /// }
686    /// ```
687    #[cfg(feature = "json")]
688    #[must_use]
689    pub fn to_json(&self) -> String {
690        crate::json::display_as_json(self)
691    }
692}
693
694impl core::str::FromStr for Edn {
695    type Err = Error;
696
697    /// Parses a `&str` that contains an Edn into `Result<Edn, EdnError>`
698    fn from_str(s: &str) -> Result<Self, Self::Err> {
699        parse::parse(s)
700    }
701}
702
703fn to_double<T>(i: T) -> Result<f64, num::ParseFloatError>
704where
705    T: fmt::Debug,
706{
707    format!("{i:?}").parse::<f64>()
708}
709
710pub(crate) fn rational_to_double(r: &str) -> Option<f64> {
711    if r.split('/').count() == 2 {
712        let vals = r
713            .split('/')
714            .map(ToString::to_string)
715            .map(|v| v.parse::<f64>())
716            .map(Result::ok)
717            .collect::<Option<Vec<f64>>>()?;
718        return Some(vals[0] / vals[1]);
719    }
720    None
721}
722
723#[derive(Debug, PartialEq, Eq)]
724#[non_exhaustive]
725pub enum Error {
726    ParseEdn(String),
727    Deserialize(String),
728    Iter(String),
729    TryFromInt(num::TryFromIntError),
730    #[doc(hidden)]
731    Infallable(), // Makes the compiler happy for converting u64 to u64 and i64 to i64
732}
733
734impl From<String> for Error {
735    fn from(s: String) -> Self {
736        Self::ParseEdn(s)
737    }
738}
739
740impl From<num::ParseIntError> for Error {
741    fn from(s: num::ParseIntError) -> Self {
742        Self::ParseEdn(s.to_string())
743    }
744}
745
746impl From<num::ParseFloatError> for Error {
747    fn from(s: num::ParseFloatError) -> Self {
748        Self::ParseEdn(s.to_string())
749    }
750}
751
752impl From<core::str::ParseBoolError> for Error {
753    fn from(s: core::str::ParseBoolError) -> Self {
754        Self::ParseEdn(s.to_string())
755    }
756}
757
758impl From<num::TryFromIntError> for Error {
759    fn from(e: num::TryFromIntError) -> Self {
760        Self::TryFromInt(e)
761    }
762}
763
764impl From<Infallible> for Error {
765    fn from(_: Infallible) -> Self {
766        Self::Infallable()
767    }
768}
769
770impl fmt::Display for Error {
771    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
772        match self {
773            Self::ParseEdn(s) | Self::Deserialize(s) | Self::Iter(s) => write!(f, "{}", &s),
774            Self::TryFromInt(e) => write!(f, "{e}"),
775            Self::Infallable() => panic!("Infallable conversion"),
776        }
777    }
778}
779
780#[cfg(test)]
781mod test {
782    use alloc::borrow::ToOwned;
783    use alloc::vec;
784
785    use super::*;
786    #[test]
787    #[expect(clippy::float_cmp)]
788    fn parses_rationals() {
789        assert_eq!(rational_to_double("3/4").unwrap(), 0.75f64);
790        assert_eq!(rational_to_double("25/5").unwrap(), 5f64);
791        assert_eq!(rational_to_double("15/4").unwrap(), 3.75f64);
792        assert_eq!(rational_to_double("3 4"), None);
793        assert_eq!(rational_to_double("3/4/5"), None);
794        assert_eq!(rational_to_double("text/moretext"), None);
795    }
796
797    #[test]
798    fn iterator() {
799        let v = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
800        let sum: i64 = v.iter_some().unwrap().filter_map(super::Edn::to_int).sum();
801
802        assert_eq!(18i64, sum);
803    }
804
805    #[test]
806    fn to_vec() {
807        let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
808        let v = vec![String::from("5"), String::from("6"), String::from("7")];
809
810        assert_eq!(edn.to_vec().unwrap(), v);
811    }
812
813    #[test]
814    fn to_char() {
815        let c = Edn::Char('c');
816        let symbol = Edn::Symbol("d".to_string());
817
818        assert_eq!(c.to_char().unwrap(), 'c');
819        assert_eq!(symbol.to_char(), None);
820    }
821
822    #[test]
823    fn to_int_vec() {
824        let edn = Edn::Vector(Vector::new(vec![Edn::Int(5), Edn::Int(6), Edn::Int(7)]));
825        let v = vec![5i64, 6i64, 7i64];
826
827        assert_eq!(edn.to_int_vec().unwrap(), v);
828    }
829
830    #[test]
831    fn to_uint_vec() {
832        let edn = Edn::Vector(Vector::new(vec![Edn::UInt(5), Edn::UInt(6), Edn::UInt(7)]));
833        let v = vec![5u64, 6u64, 7u64];
834
835        assert_eq!(edn.to_uint_vec().unwrap(), v);
836    }
837
838    #[test]
839    fn to_float_vec() {
840        let edn = Edn::Vector(Vector::new(vec![
841            Edn::Double(5.5.into()),
842            Edn::Double(6.6.into()),
843            Edn::Double(7.7.into()),
844        ]));
845        let v = vec![5.5f64, 6.6f64, 7.7f64];
846
847        assert_eq!(edn.to_float_vec().unwrap(), v);
848    }
849
850    #[test]
851    fn to_bool_vec() {
852        let edn = Edn::Vector(Vector::new(vec![
853            Edn::Bool(true),
854            Edn::Bool(true),
855            Edn::Bool(false),
856        ]));
857        let v = vec![true, true, false];
858
859        assert_eq!(edn.to_bool_vec().unwrap(), v);
860    }
861
862    #[test]
863    fn to_bool_vec_with_non_bool_is_none() {
864        let edn = Edn::Vector(Vector::new(vec![
865            Edn::Bool(true),
866            Edn::Int(5),
867            Edn::Bool(false),
868        ]));
869
870        assert_eq!(edn.to_bool_vec(), None);
871    }
872
873    #[test]
874    fn edn_to_string() {
875        let edn = Edn::Map(Map::new(
876            map! {":a".to_string() => Edn::Key(":something".to_string()),
877            ":b".to_string() => Edn::Bool(false), ":c".to_string() => Edn::Nil},
878        ));
879        assert_eq!(edn.to_string(), "{:a :something, :b false, :c nil}");
880    }
881
882    #[test]
883    fn edn_to_debug() {
884        let edn = Edn::Map(Map::new(
885            map! {":a".to_string() => Edn::Key(":something".to_string()),
886            ":b".to_string() => Edn::Bool(false), ":c".to_string() => Edn::Nil},
887        ));
888        let expected = "Map(Map({\":a\": Key(\":something\"), \":b\": Bool(false), \":c\": Nil}))";
889        assert_eq!(edn.to_debug(), expected);
890    }
891
892    #[test]
893    fn negative_i64_to_u64() {
894        let neg_i = Edn::Int(-10);
895
896        assert_eq!(neg_i.to_uint(), None);
897    }
898
899    #[test]
900    fn max_u64_to_uint() {
901        let max_u = Edn::UInt(u64::MAX);
902
903        assert_eq!(max_u.to_int(), None);
904    }
905
906    #[test]
907    fn positive_i64_to_u64() {
908        let max_i = Edn::Int(i64::MAX);
909
910        assert_eq!(max_i.to_uint(), Some(i64::MAX as u64));
911    }
912
913    #[test]
914    fn small_u64_to_i64() {
915        let small_u = Edn::UInt(10);
916
917        assert_eq!(small_u.to_int(), Some(10));
918    }
919
920    #[test]
921    fn regression_to_vec() {
922        let expected = vec!["true", ":b", "test"];
923        let edn = Edn::Vector(Vector(vec![
924            Edn::Bool(true),
925            Edn::Key(":b".to_string()),
926            Edn::Str("test".to_string()),
927        ]));
928        let edn_vec = edn.to_vec().unwrap();
929
930        assert_eq!(edn_vec, expected);
931    }
932
933    #[test]
934    fn get_vec_at() {
935        let expected = &Edn::Key(":b".to_string());
936        let edn = Edn::Vector(Vector(vec![
937            Edn::Bool(true),
938            Edn::Key(":b".to_string()),
939            Edn::Str("test".to_string()),
940        ]));
941        let val = &edn[Edn::UInt(1)];
942
943        assert_eq!(val, expected);
944    }
945
946    #[test]
947    fn get_list_at() {
948        let expected = &Edn::Str("test".to_string());
949        let edn = Edn::Vector(Vector(vec![
950            Edn::Bool(true),
951            Edn::Key(":b".to_string()),
952            Edn::Str("test".to_string()),
953        ]));
954        let val = &edn[Edn::Int(2)];
955
956        assert_eq!(val, expected);
957    }
958
959    #[test]
960    fn get_map() {
961        let expected = &Edn::Key(":val".to_string());
962        let map = Edn::Map(Map::new(map! {
963            ":key".to_string() => Edn::Key(":val".to_string()),
964            "1".to_string() => Edn::Key(":value".to_string())
965        }));
966
967        let val = &map[Edn::Key(":key".to_owned())];
968        assert_eq!(expected, val);
969    }
970}