1#![allow(clippy::linkedlist)]
12
13use std::cmp::{Ord, Ordering, PartialOrd};
14use std::collections::{BTreeMap, BTreeSet, LinkedList};
15use std::f64;
16use std::fmt::{Display, Formatter};
17
18use chrono::{DateTime, SecondsFormat, Utc};
19use num::BigInt;
20use ordered_float::OrderedFloat;
21use uuid::Uuid;
22
23use crate::symbols;
24
25#[derive(PartialEq, Eq, Hash, Clone, Debug)]
27pub enum Value {
28 Nil,
29 Boolean(bool),
30 Integer(i64),
31 Instant(DateTime<Utc>),
32 BigInteger(BigInt),
33 Float(OrderedFloat<f64>),
34 Text(String),
35 Uuid(Uuid),
36 PlainSymbol(symbols::PlainSymbol),
37 NamespacedSymbol(symbols::NamespacedSymbol),
38 Keyword(symbols::Keyword),
39 Vector(Vec<Value>),
40 List(LinkedList<Value>),
44 Set(BTreeSet<Value>),
49 Map(BTreeMap<Value, Value>),
50}
51
52#[derive(PartialEq, Eq, Hash, Clone, Debug)]
55pub enum SpannedValue {
56 Nil,
57 Boolean(bool),
58 Integer(i64),
59 Instant(DateTime<Utc>),
60 BigInteger(BigInt),
61 Float(OrderedFloat<f64>),
62 Text(String),
63 Uuid(Uuid),
64 PlainSymbol(symbols::PlainSymbol),
65 NamespacedSymbol(symbols::NamespacedSymbol),
66 Keyword(symbols::Keyword),
67 Vector(Vec<ValueAndSpan>),
68 List(LinkedList<ValueAndSpan>),
69 Set(BTreeSet<ValueAndSpan>),
70 Map(BTreeMap<ValueAndSpan, ValueAndSpan>),
71}
72
73#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
75pub struct Span(pub u32, pub u32);
76
77impl Span {
78 pub fn new(start: usize, end: usize) -> Span {
79 Span(start as u32, end as u32)
80 }
81}
82
83#[derive(PartialEq, Eq, Hash, Clone, Debug)]
86pub struct ValueAndSpan {
87 pub inner: SpannedValue,
88 pub span: Span,
89}
90
91impl ValueAndSpan {
92 pub fn new<I>(spanned_value: SpannedValue, span: I) -> ValueAndSpan
93 where
94 I: Into<Option<Span>>,
95 {
96 ValueAndSpan {
97 inner: spanned_value,
98 span: span.into().unwrap_or(Span(0, 0)), }
100 }
101
102 pub fn into_atom(self) -> Option<ValueAndSpan> {
103 if self.inner.is_atom() {
104 Some(self)
105 } else {
106 None
107 }
108 }
109
110 pub fn is_atom(&self) -> bool {
111 self.inner.is_atom()
112 }
113
114 pub fn as_atom(&self) -> Option<&ValueAndSpan> {
115 if self.inner.is_atom() {
116 Some(self)
117 } else {
118 None
119 }
120 }
121
122 pub fn into_text(self) -> Option<String> {
123 self.inner.into_text()
124 }
125
126 pub fn as_text(&self) -> Option<&String> {
127 self.inner.as_text()
128 }
129}
130
131impl Value {
132 pub fn with_spans(self) -> ValueAndSpan {
136 let s = self.to_pretty(120).unwrap();
137 use crate::parse;
138 let with_spans = parse::value(&s).unwrap();
139 assert_eq!(self, with_spans.clone().without_spans());
140 with_spans
141 }
142}
143
144impl From<SpannedValue> for Value {
145 fn from(src: SpannedValue) -> Value {
146 match src {
147 SpannedValue::Nil => Value::Nil,
148 SpannedValue::Boolean(v) => Value::Boolean(v),
149 SpannedValue::Integer(v) => Value::Integer(v),
150 SpannedValue::Instant(v) => Value::Instant(v),
151 SpannedValue::BigInteger(v) => Value::BigInteger(v),
152 SpannedValue::Float(v) => Value::Float(v),
153 SpannedValue::Text(v) => Value::Text(v),
154 SpannedValue::Uuid(v) => Value::Uuid(v),
155 SpannedValue::PlainSymbol(v) => Value::PlainSymbol(v),
156 SpannedValue::NamespacedSymbol(v) => Value::NamespacedSymbol(v),
157 SpannedValue::Keyword(v) => Value::Keyword(v),
158 SpannedValue::Vector(v) => {
159 Value::Vector(v.into_iter().map(|x| x.without_spans()).collect())
160 }
161 SpannedValue::List(v) => {
162 Value::List(v.into_iter().map(|x| x.without_spans()).collect())
163 }
164 SpannedValue::Set(v) => Value::Set(v.into_iter().map(|x| x.without_spans()).collect()),
165 SpannedValue::Map(v) => Value::Map(
166 v.into_iter()
167 .map(|(x, y)| (x.without_spans(), y.without_spans()))
168 .collect(),
169 ),
170 }
171 }
172}
173
174impl From<ValueAndSpan> for Value {
175 fn from(src: ValueAndSpan) -> Value {
176 src.inner.into()
177 }
178}
179
180macro_rules! def_from {
183 ($name: ident, $out: ty, $kind: path, $t: ty, $( $transform: expr ),* ) => {
184 pub fn $name(src: $t) -> $out {
185 $( let src = $transform(src); )*
186 $kind(src)
187 }
188 }
189}
190
191macro_rules! def_from_option {
194 ($name: ident, $out: ty, $kind: path, $t: ty, $( $transform: expr ),* ) => {
195 pub fn $name(src: $t) -> Option<$out> {
196 $( let src = $transform(src); )*
197 src.map($kind)
198 }
199 }
200}
201
202macro_rules! def_is {
205 ($name: ident, $pat: pat) => {
206 pub fn $name(&self) -> bool {
207 match *self {
208 $pat => true,
209 _ => false,
210 }
211 }
212 };
213}
214
215macro_rules! def_as {
219 ($name: ident, $kind: path, $t: ty, $( $transform: expr ),* ) => {
220 pub fn $name(&self) -> Option<$t> {
221 match *self { $kind(v) => { $( let v = $transform(v); )* Some(v) }, _ => None }
222 }
223 }
224}
225
226macro_rules! def_as_ref {
230 ($name: ident, $kind: path, $t: ty) => {
231 pub fn $name(&self) -> Option<&$t> {
232 match *self {
233 $kind(ref v) => Some(v),
234 _ => None,
235 }
236 }
237 };
238}
239
240macro_rules! def_into {
244 ($name: ident, $kind: path, $t: ty, $( $transform: expr ),* ) => {
245 pub fn $name(self) -> Option<$t> {
246 match self { $kind(v) => { $( let v = $transform(v); )* Some(v) }, _ => None }
247 }
248 }
249}
250
251macro_rules! to_symbol {
273 ( $namespace:expr, $name:expr, $t:tt ) => {
274 $namespace.into().map_or_else(
275 || $t::PlainSymbol(symbols::PlainSymbol::plain($name)),
276 |ns| $t::NamespacedSymbol(symbols::NamespacedSymbol::namespaced(ns, $name)),
277 )
278 };
279}
280
281macro_rules! to_keyword {
303 ( $namespace:expr, $name:expr, $t:tt ) => {
304 $namespace.into().map_or_else(
305 || $t::Keyword(symbols::Keyword::plain($name)),
306 |ns| $t::Keyword(symbols::Keyword::namespaced(ns, $name)),
307 )
308 };
309}
310
311macro_rules! def_common_value_methods {
314 ( $t:tt<$tchild:tt> ) => {
315 def_is!(is_nil, $t::Nil);
316 def_is!(is_boolean, $t::Boolean(_));
317 def_is!(is_integer, $t::Integer(_));
318 def_is!(is_instant, $t::Instant(_));
319 def_is!(is_big_integer, $t::BigInteger(_));
320 def_is!(is_float, $t::Float(_));
321 def_is!(is_text, $t::Text(_));
322 def_is!(is_uuid, $t::Uuid(_));
323 def_is!(is_symbol, $t::PlainSymbol(_));
324 def_is!(is_namespaced_symbol, $t::NamespacedSymbol(_));
325 def_is!(is_vector, $t::Vector(_));
326 def_is!(is_list, $t::List(_));
327 def_is!(is_set, $t::Set(_));
328 def_is!(is_map, $t::Map(_));
329
330 pub fn is_keyword(&self) -> bool {
331 match self {
332 &$t::Keyword(ref k) => !k.is_namespaced(),
333 _ => false,
334 }
335 }
336
337 pub fn is_namespaced_keyword(&self) -> bool {
338 match self {
339 &$t::Keyword(ref k) => k.is_namespaced(),
340 _ => false,
341 }
342 }
343
344 pub fn as_nil(&self) -> Option<()> {
347 match *self { $t::Nil => Some(()), _ => None }
348 }
349
350 def_as!(as_boolean, $t::Boolean, bool,);
351 def_as!(as_integer, $t::Integer, i64,);
352 def_as!(as_instant, $t::Instant, DateTime<Utc>,);
353 def_as!(as_float, $t::Float, f64, |v: OrderedFloat<f64>| v.into_inner());
354
355 def_as_ref!(as_big_integer, $t::BigInteger, BigInt);
356 def_as_ref!(as_ordered_float, $t::Float, OrderedFloat<f64>);
357 def_as_ref!(as_text, $t::Text, String);
358 def_as_ref!(as_uuid, $t::Uuid, Uuid);
359 def_as_ref!(as_symbol, $t::PlainSymbol, symbols::PlainSymbol);
360 def_as_ref!(as_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol);
361
362 pub fn as_keyword(&self) -> Option<&symbols::Keyword> {
363 match self {
364 &$t::Keyword(ref k) => Some(k),
365 _ => None,
366 }
367 }
368
369 pub fn as_plain_keyword(&self) -> Option<&symbols::Keyword> {
370 match self {
371 &$t::Keyword(ref k) if !k.is_namespaced() => Some(k),
372 _ => None,
373 }
374 }
375
376 pub fn as_namespaced_keyword(&self) -> Option<&symbols::Keyword> {
377 match self {
378 &$t::Keyword(ref k) if k.is_namespaced() => Some(k),
379 _ => None,
380 }
381 }
382
383 def_as_ref!(as_vector, $t::Vector, Vec<$tchild>);
384 def_as_ref!(as_list, $t::List, LinkedList<$tchild>);
385 def_as_ref!(as_set, $t::Set, BTreeSet<$tchild>);
386 def_as_ref!(as_map, $t::Map, BTreeMap<$tchild, $tchild>);
387
388 def_into!(into_boolean, $t::Boolean, bool,);
389 def_into!(into_integer, $t::Integer, i64,);
390 def_into!(into_instant, $t::Instant, DateTime<Utc>,);
391 def_into!(into_big_integer, $t::BigInteger, BigInt,);
392 def_into!(into_ordered_float, $t::Float, OrderedFloat<f64>,);
393 def_into!(into_float, $t::Float, f64, |v: OrderedFloat<f64>| v.into_inner());
394 def_into!(into_text, $t::Text, String,);
395 def_into!(into_uuid, $t::Uuid, Uuid,);
396 def_into!(into_symbol, $t::PlainSymbol, symbols::PlainSymbol,);
397 def_into!(into_namespaced_symbol, $t::NamespacedSymbol, symbols::NamespacedSymbol,);
398
399 pub fn into_keyword(self) -> Option<symbols::Keyword> {
400 match self {
401 $t::Keyword(k) => Some(k),
402 _ => None,
403 }
404 }
405
406 pub fn into_plain_keyword(self) -> Option<symbols::Keyword> {
407 match self {
408 $t::Keyword(k) => {
409 if !k.is_namespaced() {
410 Some(k)
411 } else {
412 None
413 }
414 },
415 _ => None,
416 }
417 }
418
419 pub fn into_namespaced_keyword(self) -> Option<symbols::Keyword> {
420 match self {
421 $t::Keyword(k) => {
422 if k.is_namespaced() {
423 Some(k)
424 } else {
425 None
426 }
427 },
428 _ => None,
429 }
430 }
431
432
433 def_into!(into_vector, $t::Vector, Vec<$tchild>,);
434 def_into!(into_list, $t::List, LinkedList<$tchild>,);
435 def_into!(into_set, $t::Set, BTreeSet<$tchild>,);
436 def_into!(into_map, $t::Map, BTreeMap<$tchild, $tchild>,);
437
438 def_from_option!(from_bigint, $t, $t::BigInteger, &str, |src: &str| src.parse::<BigInt>().ok());
439 def_from!(from_float, $t, $t::Float, f64, |src: f64| OrderedFloat::from(src));
440 def_from!(from_ordered_float, $t, $t::Float, OrderedFloat<f64>,);
441
442 pub fn from_symbol<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> $t {
443 to_symbol!(namespace, name, $t)
444 }
445
446 pub fn from_keyword<'a, T: Into<Option<&'a str>>>(namespace: T, name: &str) -> $t {
447 to_keyword!(namespace, name, $t)
448 }
449
450 fn precedence(&self) -> i32 {
451 match *self {
452 $t::Nil => 0,
453 $t::Boolean(_) => 1,
454 $t::Integer(_) => 2,
455 $t::BigInteger(_) => 3,
456 $t::Float(_) => 4,
457 $t::Instant(_) => 5,
458 $t::Text(_) => 6,
459 $t::Uuid(_) => 7,
460 $t::PlainSymbol(_) => 8,
461 $t::NamespacedSymbol(_) => 9,
462 $t::Keyword(ref k) if !k.is_namespaced() => 10,
463 $t::Keyword(_) => 11,
464 $t::Vector(_) => 12,
465 $t::List(_) => 13,
466 $t::Set(_) => 14,
467 $t::Map(_) => 15,
468 }
469 }
470
471 pub fn is_collection(&self) -> bool {
472 match *self {
473 $t::Nil => false,
474 $t::Boolean(_) => false,
475 $t::Integer(_) => false,
476 $t::Instant(_) => false,
477 $t::BigInteger(_) => false,
478 $t::Float(_) => false,
479 $t::Text(_) => false,
480 $t::Uuid(_) => false,
481 $t::PlainSymbol(_) => false,
482 $t::NamespacedSymbol(_) => false,
483 $t::Keyword(_) => false,
484 $t::Vector(_) => true,
485 $t::List(_) => true,
486 $t::Set(_) => true,
487 $t::Map(_) => true,
488 }
489 }
490
491 pub fn is_atom(&self) -> bool {
492 !self.is_collection()
493 }
494
495 pub fn into_atom(self) -> Option<$t> {
496 if self.is_atom() {
497 Some(self)
498 } else {
499 None
500 }
501 }
502 }
503}
504
505macro_rules! def_common_value_ord {
508 ( $t:tt, $value:expr, $other:expr ) => {
509 match ($value, $other) {
510 (&$t::Nil, &$t::Nil) => Ordering::Equal,
511 (&$t::Boolean(a), &$t::Boolean(b)) => b.cmp(&a),
512 (&$t::Integer(a), &$t::Integer(b)) => b.cmp(&a),
513 (&$t::Instant(a), &$t::Instant(b)) => b.cmp(&a),
514 (&$t::BigInteger(ref a), &$t::BigInteger(ref b)) => b.cmp(a),
515 (&$t::Float(ref a), &$t::Float(ref b)) => b.cmp(a),
516 (&$t::Text(ref a), &$t::Text(ref b)) => b.cmp(a),
517 (&$t::Uuid(ref a), &$t::Uuid(ref b)) => b.cmp(a),
518 (&$t::PlainSymbol(ref a), &$t::PlainSymbol(ref b)) => b.cmp(a),
519 (&$t::NamespacedSymbol(ref a), &$t::NamespacedSymbol(ref b)) => b.cmp(a),
520 (&$t::Keyword(ref a), &$t::Keyword(ref b)) => b.cmp(a),
521 (&$t::Vector(ref a), &$t::Vector(ref b)) => b.cmp(a),
522 (&$t::List(ref a), &$t::List(ref b)) => b.cmp(a),
523 (&$t::Set(ref a), &$t::Set(ref b)) => b.cmp(a),
524 (&$t::Map(ref a), &$t::Map(ref b)) => b.cmp(a),
525 _ => $value.precedence().cmp(&$other.precedence()),
526 }
527 };
528}
529
530macro_rules! def_common_value_display {
534 ( $t:tt, $value:expr, $f:expr ) => {
535 match *$value {
536 $t::Nil => write!($f, "nil"),
537 $t::Boolean(v) => write!($f, "{}", v),
538 $t::Integer(v) => write!($f, "{}", v),
539 $t::Instant(v) => write!(
540 $f,
541 "#inst \"{}\"",
542 v.to_rfc3339_opts(SecondsFormat::AutoSi, true)
543 ),
544 $t::BigInteger(ref v) => write!($f, "{}N", v),
545 $t::Float(ref v) => {
547 if *v == OrderedFloat(f64::INFINITY) {
548 write!($f, "#f +Infinity")
549 } else if *v == OrderedFloat(f64::NEG_INFINITY) {
550 write!($f, "#f -Infinity")
551 } else if *v == OrderedFloat(f64::NAN) {
552 write!($f, "#f NaN")
553 } else {
554 write!($f, "{}", v)
555 }
556 }
557 $t::Text(ref v) => write!($f, "\"{}\"", v),
559 $t::Uuid(ref u) => write!($f, "#uuid \"{}\"", u.hyphenated().to_string()),
560 $t::PlainSymbol(ref v) => v.fmt($f),
561 $t::NamespacedSymbol(ref v) => v.fmt($f),
562 $t::Keyword(ref v) => v.fmt($f),
563 $t::Vector(ref v) => {
564 write!($f, "[")?;
565 for x in v {
566 write!($f, " {}", x)?;
567 }
568 write!($f, " ]")
569 }
570 $t::List(ref v) => {
571 write!($f, "(")?;
572 for x in v {
573 write!($f, " {}", x)?;
574 }
575 write!($f, " )")
576 }
577 $t::Set(ref v) => {
578 write!($f, "#{{")?;
579 for x in v {
580 write!($f, " {}", x)?;
581 }
582 write!($f, " }}")
583 }
584 $t::Map(ref v) => {
585 write!($f, "{{")?;
586 for (key, val) in v {
587 write!($f, " {} {}", key, val)?;
588 }
589 write!($f, " }}")
590 }
591 }
592 };
593}
594
595macro_rules! def_common_value_impl {
596 ( $t:tt<$tchild:tt> ) => {
597 impl $t {
598 def_common_value_methods!($t<$tchild>);
599 }
600
601 impl PartialOrd for $t {
602 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
603 Some(Ord::cmp(self, other))
604 }
605 }
606
607 impl Ord for $t {
608 fn cmp(&self, other: &$t) -> Ordering {
609 def_common_value_ord!($t, self, other)
610 }
611 }
612
613 impl Display for $t {
614 fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
615 def_common_value_display!($t, self, f)
616 }
617 }
618 };
619}
620
621def_common_value_impl!(Value<Value>);
622def_common_value_impl!(SpannedValue<ValueAndSpan>);
623
624impl ValueAndSpan {
625 pub fn without_spans(self) -> Value {
626 self.inner.into()
627 }
628}
629
630impl PartialOrd for ValueAndSpan {
631 fn partial_cmp(&self, other: &ValueAndSpan) -> Option<Ordering> {
632 Some(Ord::cmp(self, other))
633 }
634}
635
636impl Ord for ValueAndSpan {
637 fn cmp(&self, other: &ValueAndSpan) -> Ordering {
638 self.inner.cmp(&other.inner)
639 }
640}
641
642impl Display for ValueAndSpan {
643 fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
644 self.inner.fmt(f)
645 }
646}
647
648pub trait FromMicros {
649 fn from_micros(ts: i64) -> Self;
650}
651
652impl FromMicros for DateTime<Utc> {
653 fn from_micros(ts: i64) -> Self {
654 DateTime::from_timestamp(
655 ts / 1_000_000,
656 ((ts % 1_000_000).unsigned_abs() as u32) * 1_000,
657 )
658 .unwrap()
659 }
660}
661
662pub trait ToMicros {
663 fn to_micros(&self) -> i64;
664}
665
666impl ToMicros for DateTime<Utc> {
667 fn to_micros(&self) -> i64 {
668 let major: i64 = self.timestamp() * 1_000_000;
669 let minor: i64 = self.timestamp_subsec_micros() as i64;
670 major + minor
671 }
672}
673
674pub trait FromMillis {
675 fn from_millis(ts: i64) -> Self;
676}
677
678impl FromMillis for DateTime<Utc> {
679 fn from_millis(ts: i64) -> Self {
680 DateTime::from_timestamp(ts / 1_000, ((ts % 1_000).unsigned_abs() as u32) * 1_000).unwrap()
681 }
682}
683
684pub trait ToMillis {
685 fn to_millis(&self) -> i64;
686}
687
688impl ToMillis for DateTime<Utc> {
689 fn to_millis(&self) -> i64 {
690 let major: i64 = self.timestamp() * 1_000;
691 let minor: i64 = self.timestamp_subsec_millis() as i64;
692 major + minor
693 }
694}
695
696#[cfg(test)]
697mod test {
698 use super::*;
699
700 use std::cmp::Ordering;
701 use std::collections::{BTreeMap, BTreeSet, LinkedList};
702 use std::f64;
703 use std::iter::FromIterator;
704
705 use crate::parse;
706
707 use chrono::{DateTime, Utc};
708 use num::BigInt;
709 use ordered_float::OrderedFloat;
710
711 #[test]
712 fn test_micros_roundtrip() {
713 let ts_micros: i64 = 1493399581314000;
714 let dt = DateTime::<Utc>::from_micros(ts_micros);
715 assert_eq!(dt.to_micros(), ts_micros);
716 }
717
718 #[test]
719 fn test_value_from() {
720 assert_eq!(
721 Value::from_float(42f64),
722 Value::Float(OrderedFloat::from(42f64))
723 );
724 assert_eq!(
725 Value::from_ordered_float(OrderedFloat::from(42f64)),
726 Value::Float(OrderedFloat::from(42f64))
727 );
728 assert_eq!(
729 Value::from_bigint("42").unwrap(),
730 Value::BigInteger(BigInt::from(42))
731 );
732 }
733
734 #[test]
735 #[allow(clippy::approx_constant)]
736 fn test_print_edn() {
737 assert_eq!("1234N", Value::from_bigint("1234").unwrap().to_string());
738
739 let string = "[ 1 2 ( 3.14 ) #{ 4N } { foo/bar 42 :baz/boz 43 } [ ] :five :six/seven eight nine/ten true false nil #f NaN #f -Infinity #f +Infinity ]";
740
741 let data = Value::Vector(vec![
742 Value::Integer(1),
743 Value::Integer(2),
744 Value::List(LinkedList::from_iter(vec![Value::from_float(3.14)])),
745 Value::Set(BTreeSet::from_iter(vec![Value::from_bigint("4").unwrap()])),
746 Value::Map(BTreeMap::from_iter(vec![
747 (Value::from_symbol("foo", "bar"), Value::Integer(42)),
748 (Value::from_keyword("baz", "boz"), Value::Integer(43)),
749 ])),
750 Value::Vector(vec![]),
751 Value::from_keyword(None, "five"),
752 Value::from_keyword("six", "seven"),
753 Value::from_symbol(None, "eight"),
754 Value::from_symbol("nine", "ten"),
755 Value::Boolean(true),
756 Value::Boolean(false),
757 Value::Nil,
758 Value::from_float(f64::NAN),
759 Value::from_float(f64::NEG_INFINITY),
760 Value::from_float(f64::INFINITY),
761 ]);
762
763 assert_eq!(string, data.to_string());
764 assert_eq!(string, parse::value(&data.to_string()).unwrap().to_string());
765 assert_eq!(
766 string,
767 parse::value(&data.to_string())
768 .unwrap()
769 .without_spans()
770 .to_string()
771 );
772 }
773
774 #[test]
775 fn test_ord() {
776 assert_eq!(Value::Nil.cmp(&Value::Nil), Ordering::Equal);
778 assert_eq!(
779 Value::Boolean(false).cmp(&Value::Boolean(true)),
780 Ordering::Greater
781 );
782 assert_eq!(Value::Integer(1).cmp(&Value::Integer(2)), Ordering::Greater);
783 assert_eq!(
784 Value::from_bigint("1").cmp(&Value::from_bigint("2")),
785 Ordering::Greater
786 );
787 assert_eq!(
788 Value::from_float(1f64).cmp(&Value::from_float(2f64)),
789 Ordering::Greater
790 );
791 assert_eq!(
792 Value::Text("1".to_string()).cmp(&Value::Text("2".to_string())),
793 Ordering::Greater
794 );
795 assert_eq!(
796 Value::from_symbol("a", "b").cmp(&Value::from_symbol("c", "d")),
797 Ordering::Greater
798 );
799 assert_eq!(
800 Value::from_symbol(None, "a").cmp(&Value::from_symbol(None, "b")),
801 Ordering::Greater
802 );
803 assert_eq!(
804 Value::from_keyword(":a", ":b").cmp(&Value::from_keyword(":c", ":d")),
805 Ordering::Greater
806 );
807 assert_eq!(
808 Value::from_keyword(None, ":a").cmp(&Value::from_keyword(None, ":b")),
809 Ordering::Greater
810 );
811 assert_eq!(
812 Value::Vector(vec![]).cmp(&Value::Vector(vec![])),
813 Ordering::Equal
814 );
815 assert_eq!(
816 Value::List(LinkedList::new()).cmp(&Value::List(LinkedList::new())),
817 Ordering::Equal
818 );
819 assert_eq!(
820 Value::Set(BTreeSet::new()).cmp(&Value::Set(BTreeSet::new())),
821 Ordering::Equal
822 );
823 assert_eq!(
824 Value::Map(BTreeMap::new()).cmp(&Value::Map(BTreeMap::new())),
825 Ordering::Equal
826 );
827 }
828
829 #[test]
830 fn test_keyword_as() {
831 let namespaced = symbols::Keyword::namespaced("foo", "bar");
832 let plain = symbols::Keyword::plain("bar");
833 let n_v = Value::Keyword(namespaced);
834 let p_v = Value::Keyword(plain);
835
836 assert!(n_v.as_keyword().is_some());
837 assert!(n_v.as_plain_keyword().is_none());
838 assert!(n_v.as_namespaced_keyword().is_some());
839
840 assert!(p_v.as_keyword().is_some());
841 assert!(p_v.as_plain_keyword().is_some());
842 assert!(p_v.as_namespaced_keyword().is_none());
843
844 assert!(n_v.clone().into_keyword().is_some());
845 assert!(n_v.clone().into_plain_keyword().is_none());
846 assert!(n_v.clone().into_namespaced_keyword().is_some());
847
848 assert!(p_v.clone().into_keyword().is_some());
849 assert!(p_v.clone().into_plain_keyword().is_some());
850 assert!(p_v.clone().into_namespaced_keyword().is_none());
851 }
852}