1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! A generic scalar [`Value`] enum which supports collation.

pub extern crate uuid;

use std::cmp::Ordering;
use std::sync::Arc;

use collate::{Collate, Collator};

use tcgeneric::Instance;

pub use class::*;
pub use link::*;
pub use number::*;
pub use string::*;
pub use value::*;
pub use version::*;

mod class;

mod link {
    pub use pathlink::{Address, Host, Link, Protocol, ToUrl};
}

mod number {
    pub use number_general::{
        Boolean, BooleanType, Complex, ComplexType, DType, Float, FloatInstance, FloatType, Int,
        IntType, Number, NumberClass, NumberCollator, NumberInstance, NumberType, Trigonometry,
        UInt, UIntType,
    };
}

mod string;
mod value;
mod version;

/// [`Collate`] support for [`Value`]
#[derive(Default, Clone, Eq, PartialEq)]
pub struct ValueCollator {
    bytes: Collator<Arc<[u8]>>,
    link: Collator<Link>,
    number: NumberCollator,
    string: StringCollator,
    version: Collator<Version>,
}

impl Collate for ValueCollator {
    type Value = Value;

    fn cmp(&self, left: &Self::Value, right: &Self::Value) -> Ordering {
        match (left, right) {
            (Value::Bytes(l), Value::Bytes(r)) => self.bytes.cmp(l, r),
            (Value::Link(l), Value::Link(r)) => self.link.cmp(l, r),
            (Value::Number(l), Value::Number(r)) => self.number.cmp(l, r),
            (Value::Version(l), Value::Version(r)) => self.version.cmp(l, r),
            (Value::String(l), Value::String(r)) => self.string.cmp(l, r),
            (Value::Tuple(l), Value::Tuple(r)) => {
                for i in 0..Ord::min(l.len(), r.len()) {
                    match self.cmp(&l[i], &r[i]) {
                        Ordering::Equal => {}
                        ordering => return ordering,
                    }
                }

                Ordering::Equal
            }
            (l, r) => l.class().cmp(&r.class()),
        }
    }
}