Skip to main content

conjure_object/
private.rs

1// Copyright 2018 Palantir Technologies, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15pub use conjure_macros::DeriveWith;
16pub use educe::Educe;
17use ordered_float::OrderedFloat;
18use serde::de::{self, IntoDeserializer};
19use serde::{Deserialize, Serialize};
20pub use staged_builder;
21use std::cmp::Ordering;
22use std::collections::BTreeMap;
23use std::hash::{Hash, Hasher};
24use std::marker::PhantomData;
25use std::ops::Deref;
26use std::str::FromStr;
27use std::{fmt, mem};
28
29use crate::plain::ParseEnumError;
30
31pub struct DoubleWrapper<T>(pub T);
32
33impl<T> PartialEq for DoubleWrapper<&T>
34where
35    T: DoubleOps,
36{
37    #[inline]
38    fn eq(&self, other: &Self) -> bool {
39        self.0.eq(other.0)
40    }
41}
42
43impl<T> Eq for DoubleWrapper<&T> where T: DoubleOps {}
44
45impl<T> PartialOrd for DoubleWrapper<&T>
46where
47    T: DoubleOps,
48{
49    #[inline]
50    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51        Some(self.cmp(other))
52    }
53}
54
55impl<T> Ord for DoubleWrapper<&T>
56where
57    T: DoubleOps,
58{
59    #[inline]
60    fn cmp(&self, other: &Self) -> Ordering {
61        self.0.cmp(other.0)
62    }
63}
64
65impl<T> Hash for DoubleWrapper<&T>
66where
67    T: DoubleOps,
68{
69    #[inline]
70    fn hash<H: Hasher>(&self, state: &mut H) {
71        self.0.hash(state)
72    }
73}
74
75// FIXME make private
76pub trait DoubleOps {
77    fn cmp(&self, other: &Self) -> Ordering;
78
79    fn eq(&self, other: &Self) -> bool;
80
81    fn hash<H>(&self, hasher: &mut H)
82    where
83        H: Hasher;
84}
85
86impl DoubleOps for f64 {
87    #[inline]
88    fn cmp(&self, other: &Self) -> Ordering {
89        OrderedFloat(*self).cmp(&OrderedFloat(*other))
90    }
91
92    #[inline]
93    fn eq(&self, other: &Self) -> bool {
94        OrderedFloat(*self) == OrderedFloat(*other)
95    }
96
97    #[inline]
98    fn hash<H>(&self, hasher: &mut H)
99    where
100        H: Hasher,
101    {
102        OrderedFloat(*self).hash(hasher)
103    }
104}
105
106impl<T> DoubleOps for Option<T>
107where
108    T: DoubleOps,
109{
110    #[inline]
111    fn cmp(&self, other: &Self) -> Ordering {
112        match (self, other) {
113            (Some(a), Some(b)) => a.cmp(b),
114            (Some(_), None) => Ordering::Greater,
115            (None, Some(_)) => Ordering::Less,
116            (None, None) => Ordering::Equal,
117        }
118    }
119
120    #[inline]
121    fn eq(&self, other: &Self) -> bool {
122        match (self, other) {
123            (Some(a), Some(b)) => a.eq(b),
124            (Some(_), None) | (None, Some(_)) => false,
125            (None, None) => true,
126        }
127    }
128
129    #[inline]
130    fn hash<H>(&self, hasher: &mut H)
131    where
132        H: Hasher,
133    {
134        mem::discriminant(self).hash(hasher);
135        if let Some(v) = self {
136            v.hash(hasher);
137        }
138    }
139}
140
141impl<T> DoubleOps for Vec<T>
142where
143    T: DoubleOps,
144{
145    #[inline]
146    fn cmp(&self, other: &Self) -> Ordering {
147        let l = usize::min(self.len(), other.len());
148
149        let lhs = &self[..l];
150        let rhs = &other[..l];
151
152        for i in 0..l {
153            match lhs[i].cmp(&rhs[i]) {
154                Ordering::Equal => {}
155                v => return v,
156            }
157        }
158
159        self.len().cmp(&other.len())
160    }
161
162    #[inline]
163    fn eq(&self, other: &Self) -> bool {
164        if self.len() != other.len() {
165            return false;
166        }
167
168        for i in 0..self.len() {
169            if !self[i].eq(&other[i]) {
170                return false;
171            }
172        }
173
174        true
175    }
176
177    #[inline]
178    fn hash<H>(&self, hasher: &mut H)
179    where
180        H: Hasher,
181    {
182        self.len().hash(hasher);
183        for v in self {
184            v.hash(hasher);
185        }
186    }
187}
188
189impl<K, V> DoubleOps for BTreeMap<K, V>
190where
191    K: Eq + Ord + Hash,
192    V: DoubleOps,
193{
194    #[inline]
195    fn cmp(&self, other: &Self) -> Ordering {
196        self.iter()
197            .map(|(k, v)| (k, DoubleWrapper(v)))
198            .cmp(other.iter().map(|(k, v)| (k, DoubleWrapper(v))))
199    }
200
201    #[inline]
202    fn eq(&self, other: &Self) -> bool {
203        self.iter()
204            .map(|(k, v)| (k, DoubleWrapper(v)))
205            .eq(other.iter().map(|(k, v)| (k, DoubleWrapper(v))))
206    }
207
208    #[inline]
209    fn hash<H>(&self, hasher: &mut H)
210    where
211        H: Hasher,
212    {
213        self.len().hash(hasher);
214        for (k, v) in self {
215            (k, DoubleWrapper(v)).hash(hasher);
216        }
217    }
218}
219
220fn valid_enum_variant(s: &str) -> bool {
221    if s.is_empty() {
222        return false;
223    }
224
225    s.as_bytes()
226        .iter()
227        .all(|b| matches!(b, b'A'..=b'Z' | b'0'..=b'9' | b'_'))
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
231#[serde(transparent)]
232pub struct Variant(Box<str>);
233
234impl Deref for Variant {
235    type Target = str;
236
237    #[inline]
238    fn deref(&self) -> &Self::Target {
239        &self.0
240    }
241}
242
243impl fmt::Display for Variant {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        fmt::Display::fmt(&self.0, f)
246    }
247}
248
249impl FromStr for Variant {
250    type Err = ParseEnumError;
251
252    fn from_str(s: &str) -> Result<Self, Self::Err> {
253        if valid_enum_variant(s) {
254            Ok(Variant(s.into()))
255        } else {
256            Err(ParseEnumError::new())
257        }
258    }
259}
260
261impl<'de> Deserialize<'de> for Variant {
262    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
263    where
264        D: de::Deserializer<'de>,
265    {
266        struct Visitor;
267
268        impl de::Visitor<'_> for Visitor {
269            type Value = Variant;
270
271            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
272                formatter.write_str("an enum variant")
273            }
274
275            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
276            where
277                E: de::Error,
278            {
279                v.parse()
280                    .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(v), &self))
281            }
282        }
283
284        deserializer.deserialize_str(Visitor)
285    }
286}
287
288pub enum UnionField_<T> {
289    Type,
290    Value(T),
291}
292
293impl<'de, T> de::Deserialize<'de> for UnionField_<T>
294where
295    T: de::Deserialize<'de>,
296{
297    fn deserialize<D>(d: D) -> Result<UnionField_<T>, D::Error>
298    where
299        D: de::Deserializer<'de>,
300    {
301        d.deserialize_str(UnionFieldVisitor(PhantomData))
302    }
303}
304
305struct UnionFieldVisitor<T>(PhantomData<T>);
306
307impl<'de, T> de::Visitor<'de> for UnionFieldVisitor<T>
308where
309    T: de::Deserialize<'de>,
310{
311    type Value = UnionField_<T>;
312
313    fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
314        fmt.write_str("string")
315    }
316
317    fn visit_str<E>(self, value: &str) -> Result<UnionField_<T>, E>
318    where
319        E: de::Error,
320    {
321        match value {
322            "type" => Ok(UnionField_::Type),
323            value => T::deserialize(value.into_deserializer()).map(UnionField_::Value),
324        }
325    }
326}
327
328pub struct UnionTypeField_;
329
330impl<'de> de::Deserialize<'de> for UnionTypeField_ {
331    fn deserialize<D>(d: D) -> Result<UnionTypeField_, D::Error>
332    where
333        D: de::Deserializer<'de>,
334    {
335        d.deserialize_str(UnionTypeFieldVisitor)
336    }
337}
338
339struct UnionTypeFieldVisitor;
340
341impl de::Visitor<'_> for UnionTypeFieldVisitor {
342    type Value = UnionTypeField_;
343
344    fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
345        fmt.write_str("type field")
346    }
347
348    fn visit_str<E>(self, value: &str) -> Result<UnionTypeField_, E>
349    where
350        E: de::Error,
351    {
352        match value {
353            "type" => Ok(UnionTypeField_),
354            value => Err(E::invalid_value(de::Unexpected::Str(value), &self)),
355        }
356    }
357}