|
| 1 | +use super::pack::{f32_to_u32_be_bytes, f64_to_u64_be_bytes}; |
1 | 2 | use super::{Bytes, Versionstamp};
|
2 |
| -use std::borrow::Cow; |
| 3 | +use std::{borrow::Cow, cmp}; |
3 | 4 |
|
4 |
| -#[derive(Clone, PartialEq, Debug)] |
| 5 | +#[cfg(feature = "num-bigint")] |
| 6 | +use std::convert::TryInto; |
| 7 | + |
| 8 | +#[derive(Clone, Debug)] |
5 | 9 | pub enum Element<'a> {
|
6 | 10 | Nil,
|
7 | 11 | Bytes(Bytes<'a>),
|
8 | 12 | String(Cow<'a, str>),
|
9 | 13 | Tuple(Vec<Element<'a>>),
|
10 | 14 | Int(i64),
|
| 15 | + #[cfg(feature = "num-bigint")] |
| 16 | + BigInt(num_bigint::BigInt), |
11 | 17 | Float(f32),
|
12 | 18 | Double(f64),
|
13 | 19 | Bool(bool),
|
14 |
| - Versionstamp(Versionstamp), |
15 | 20 | #[cfg(feature = "uuid")]
|
16 | 21 | Uuid(uuid::Uuid),
|
17 |
| - #[cfg(feature = "num-bigint")] |
18 |
| - BigInt(num_bigint::BigInt), |
| 22 | + Versionstamp(Versionstamp), |
| 23 | +} |
| 24 | + |
| 25 | +struct CmpElement<'a, 'b>(&'a Element<'b>); |
| 26 | + |
| 27 | +impl<'a, 'b> PartialEq for CmpElement<'a, 'b> { |
| 28 | + fn eq(&self, other: &Self) -> bool { |
| 29 | + self.cmp(other) == cmp::Ordering::Equal |
| 30 | + } |
| 31 | +} |
| 32 | +impl<'a, 'b> Eq for CmpElement<'a, 'b> {} |
| 33 | + |
| 34 | +impl<'a, 'b> PartialOrd for CmpElement<'a, 'b> { |
| 35 | + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
| 36 | + Some(self.cmp(other)) |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +impl<'a, 'b> Ord for CmpElement<'a, 'b> { |
| 41 | + fn cmp(&self, other: &Self) -> cmp::Ordering { |
| 42 | + self.0 |
| 43 | + .code() |
| 44 | + .cmp(&other.0.code()) |
| 45 | + .then_with(|| match (&self.0, &other.0) { |
| 46 | + (Element::Bytes(a), Element::Bytes(b)) => a.cmp(b), |
| 47 | + (Element::String(a), Element::String(b)) => a.cmp(b), |
| 48 | + (Element::Tuple(a), Element::Tuple(b)) => { |
| 49 | + let a_values = a.iter().map(CmpElement); |
| 50 | + let b_values = b.iter().map(CmpElement); |
| 51 | + a_values.cmp(b_values) |
| 52 | + } |
| 53 | + (Element::Int(a), Element::Int(b)) => a.cmp(b), |
| 54 | + #[cfg(feature = "num-bigint")] |
| 55 | + (Element::BigInt(a), Element::BigInt(b)) => a.cmp(b), |
| 56 | + (Element::Float(a), Element::Float(b)) => { |
| 57 | + f32_to_u32_be_bytes(*a).cmp(&f32_to_u32_be_bytes(*b)) |
| 58 | + } |
| 59 | + (Element::Double(a), Element::Double(b)) => { |
| 60 | + f64_to_u64_be_bytes(*a).cmp(&f64_to_u64_be_bytes(*b)) |
| 61 | + } |
| 62 | + #[cfg(feature = "uuid")] |
| 63 | + (Element::Uuid(a), Element::Uuid(b)) => a.cmp(b), |
| 64 | + (Element::Versionstamp(a), Element::Versionstamp(b)) => a.cmp(b), |
| 65 | + _ => cmp::Ordering::Equal, |
| 66 | + }) |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +impl<'a> PartialEq for Element<'a> { |
| 71 | + fn eq(&self, other: &Self) -> bool { |
| 72 | + self.cmp(other) == cmp::Ordering::Equal |
| 73 | + } |
| 74 | +} |
| 75 | +impl<'a> Eq for Element<'a> {} |
| 76 | + |
| 77 | +impl<'a> PartialOrd for Element<'a> { |
| 78 | + fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { |
| 79 | + Some(self.cmp(other)) |
| 80 | + } |
| 81 | +} |
| 82 | +impl<'a> Ord for Element<'a> { |
| 83 | + fn cmp(&self, other: &Self) -> cmp::Ordering { |
| 84 | + self.cmp_at_root(other) |
| 85 | + } |
19 | 86 | }
|
20 | 87 |
|
21 | 88 | impl<'a> Element<'a> {
|
| 89 | + fn code(&self) -> u8 { |
| 90 | + match self { |
| 91 | + Element::Nil => super::NIL, |
| 92 | + Element::Bytes(_) => super::BYTES, |
| 93 | + Element::String(_) => super::STRING, |
| 94 | + Element::Tuple(_) => super::NESTED, |
| 95 | + Element::Int(_) => super::INTZERO, |
| 96 | + #[cfg(feature = "num-bigint")] |
| 97 | + Element::BigInt(_) => super::POSINTEND, |
| 98 | + Element::Float(_) => super::FLOAT, |
| 99 | + Element::Double(_) => super::DOUBLE, |
| 100 | + Element::Bool(v) => { |
| 101 | + if *v { |
| 102 | + super::TRUE |
| 103 | + } else { |
| 104 | + super::FALSE |
| 105 | + } |
| 106 | + } |
| 107 | + #[cfg(feature = "uuid")] |
| 108 | + Element::Uuid(_) => super::UUID, |
| 109 | + Element::Versionstamp(_) => super::VERSIONSTAMP, |
| 110 | + } |
| 111 | + } |
| 112 | + |
| 113 | + #[inline] |
| 114 | + fn cmp_values(&self) -> &[Self] { |
| 115 | + match self { |
| 116 | + Element::Tuple(v) => v.as_slice(), |
| 117 | + v => std::slice::from_ref(v), |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + fn cmp_at_root<'b>(&self, b: &Element<'b>) -> cmp::Ordering { |
| 122 | + let a_values = self.cmp_values().iter().map(CmpElement); |
| 123 | + let b_values = b.cmp_values().iter().map(CmpElement); |
| 124 | + a_values.cmp(b_values) |
| 125 | + } |
| 126 | + |
22 | 127 | pub fn into_owned(self) -> Element<'static> {
|
23 | 128 | match self {
|
24 | 129 | Element::Nil => Element::Nil,
|
25 |
| - Element::Bool(v) => Element::Bool(v), |
| 130 | + Element::Bytes(v) => Element::Bytes(v.into_owned().into()), |
| 131 | + Element::String(v) => Element::String(Cow::Owned(v.into_owned())), |
| 132 | + Element::Tuple(v) => Element::Tuple(v.into_iter().map(|e| e.into_owned()).collect()), |
26 | 133 | Element::Int(v) => Element::Int(v),
|
| 134 | + #[cfg(feature = "num-bigint")] |
| 135 | + Element::BigInt(v) => Element::BigInt(v), |
27 | 136 | Element::Float(v) => Element::Float(v),
|
28 | 137 | Element::Double(v) => Element::Double(v),
|
29 |
| - Element::String(v) => Element::String(Cow::Owned(v.into_owned())), |
30 |
| - Element::Bytes(v) => Element::Bytes(v.into_owned().into()), |
31 |
| - Element::Versionstamp(v) => Element::Versionstamp(v), |
32 |
| - Element::Tuple(v) => Element::Tuple(v.into_iter().map(|e| e.into_owned()).collect()), |
| 138 | + Element::Bool(v) => Element::Bool(v), |
33 | 139 | #[cfg(feature = "uuid")]
|
34 | 140 | Element::Uuid(v) => Element::Uuid(v),
|
35 |
| - #[cfg(feature = "num-bigint")] |
36 |
| - Element::BigInt(v) => Element::BigInt(v), |
| 141 | + Element::Versionstamp(v) => Element::Versionstamp(v), |
37 | 142 | }
|
38 | 143 | }
|
39 | 144 |
|
40 |
| - pub fn as_bool(&self) -> Option<bool> { |
41 |
| - match *self { |
42 |
| - Element::Bool(v) => Some(v), |
| 145 | + pub fn as_bytes(&self) -> Option<&Bytes> { |
| 146 | + match self { |
| 147 | + Element::Bytes(v) => Some(v), |
| 148 | + _ => None, |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + pub fn as_str(&self) -> Option<&str> { |
| 153 | + match self { |
| 154 | + Element::String(v) => Some(&v), |
| 155 | + _ => None, |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + pub fn as_tuple(&self) -> Option<&[Element<'a>]> { |
| 160 | + match self { |
| 161 | + Element::Tuple(v) => Some(v.as_slice()), |
43 | 162 | _ => None,
|
44 | 163 | }
|
45 | 164 | }
|
46 | 165 |
|
47 | 166 | pub fn as_i64(&self) -> Option<i64> {
|
48 |
| - match *self { |
49 |
| - Element::Int(v) => Some(v), |
| 167 | + match self { |
| 168 | + Element::Int(v) => Some(*v), |
| 169 | + #[cfg(feature = "num-bigint")] |
| 170 | + Element::BigInt(v) => v.try_into().ok(), |
50 | 171 | _ => None,
|
51 | 172 | }
|
52 | 173 | }
|
53 | 174 |
|
54 |
| - pub fn as_str(&self) -> Option<&str> { |
| 175 | + #[cfg(feature = "num-bigint")] |
| 176 | + pub fn as_bigint(&self) -> Option<&num_bigint::BigInt> { |
55 | 177 | match self {
|
56 |
| - Element::String(v) => Some(&v), |
| 178 | + Element::BigInt(v) => Some(v), |
57 | 179 | _ => None,
|
58 | 180 | }
|
59 | 181 | }
|
60 | 182 |
|
61 |
| - pub fn as_bytes(&self) -> Option<&Bytes> { |
| 183 | + pub fn as_f32(&self) -> Option<f32> { |
62 | 184 | match self {
|
63 |
| - Element::Bytes(v) => Some(v), |
| 185 | + Element::Float(v) => Some(*v), |
64 | 186 | _ => None,
|
65 | 187 | }
|
66 | 188 | }
|
67 | 189 |
|
68 |
| - pub fn as_tuple(&self) -> Option<&[Element<'a>]> { |
| 190 | + pub fn as_f64(&self) -> Option<f64> { |
69 | 191 | match self {
|
70 |
| - Element::Tuple(v) => Some(v.as_slice()), |
| 192 | + Element::Double(v) => Some(*v), |
| 193 | + _ => None, |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | + pub fn as_bool(&self) -> Option<bool> { |
| 198 | + match *self { |
| 199 | + Element::Bool(v) => Some(v), |
| 200 | + _ => None, |
| 201 | + } |
| 202 | + } |
| 203 | + |
| 204 | + #[cfg(feature = "uuid")] |
| 205 | + pub fn as_uuid(&self) -> Option<&uuid::Uuid> { |
| 206 | + match self { |
| 207 | + Element::Uuid(v) => Some(v), |
| 208 | + _ => None, |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + pub fn as_versionstamp(&self) -> Option<&Versionstamp> { |
| 213 | + match self { |
| 214 | + Element::Versionstamp(v) => Some(v), |
71 | 215 | _ => None,
|
72 | 216 | }
|
73 | 217 | }
|
|
0 commit comments