1use fxhash::FxBuildHasher;
4use hashlink::LinkedHashMap;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::{
7 cmp::Ordering, fmt::{self, Debug}, ops::Index, slice::SliceIndex, str, sync::Arc
8};
9
10use super::{util::IteratorExt, AmadeusOrd, Downcast, DowncastError, DowncastFrom, Value};
11
12#[derive(Clone, PartialEq)]
18pub struct Group {
19 fields: Vec<Value>,
20 field_names: Option<Arc<LinkedHashMap<String, usize, FxBuildHasher>>>,
21}
22
23impl Group {
24 #[doc(hidden)]
25 pub fn new(
26 fields: Vec<Value>, field_names: Option<Arc<LinkedHashMap<String, usize, FxBuildHasher>>>,
27 ) -> Self {
28 Self {
29 fields,
30 field_names,
31 }
32 }
33 #[doc(hidden)]
34 pub fn fields(&self) -> &[Value] {
35 &self.fields
36 }
37 #[doc(hidden)]
38 pub fn field_names(&self) -> Option<&Arc<LinkedHashMap<String, usize, FxBuildHasher>>> {
39 self.field_names.as_ref()
40 }
41 pub fn get(&self, k: &str) -> Option<&Value> {
44 self.field_names
45 .as_ref()?
46 .get(k)
47 .map(|&offset| &self.fields[offset])
48 }
49 #[doc(hidden)]
50 pub fn into_fields(self) -> Vec<Value> {
51 self.fields
52 }
53}
54
55impl Serialize for Group {
56 fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
57 where
58 S: Serializer,
59 {
60 unimplemented!()
62 }
63}
64impl<'de> Deserialize<'de> for Group {
65 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
66 where
67 D: Deserializer<'de>,
68 {
69 unimplemented!()
71 }
72}
73
74impl<I> Index<I> for Group
81where
82 I: SliceIndex<[Value]>,
83{
84 type Output = <I as SliceIndex<[Value]>>::Output;
85
86 fn index(&self, index: I) -> &Self::Output {
87 self.fields.index(index)
88 }
89}
90impl PartialOrd for Group {
91 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
92 if match (self.field_names.as_ref(), other.field_names.as_ref()) {
93 (Some(a), Some(b)) => a == b,
94 _ => self.fields.len() == other.fields.len(),
95 } {
96 self.fields.partial_cmp(&other.fields)
97 } else {
98 None
99 }
100 }
101}
102impl AmadeusOrd for Group {
103 fn amadeus_cmp(&self, other: &Self) -> Ordering {
104 match (self.field_names.as_ref(), other.field_names.as_ref()) {
105 (Some(a), Some(b)) => a
106 .iter()
107 .map(|(name, _index)| name)
108 .zip(&self.fields)
109 .cmp_by_(
110 b.iter().map(|(name, _index)| name).zip(&other.fields),
111 |a, b| a.amadeus_cmp(&b),
112 ),
113 (None, None) => self
114 .fields
115 .iter()
116 .cmp_by_(&other.fields, AmadeusOrd::amadeus_cmp),
117 (Some(_), None) => Ordering::Less,
118 (None, Some(_)) => Ordering::Greater,
119 }
120 }
121}
122
123impl Debug for Group {
124 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125 if let Some(field_names) = self.field_names.as_ref() {
126 let mut printer = f.debug_struct("Group");
127 for (name, field) in field_names
128 .iter()
129 .map(|(name, _index)| name)
130 .zip(self.fields.iter())
131 {
132 let _ = printer.field(name, field);
133 }
134 printer.finish()
135 } else {
136 let mut printer = f.debug_tuple("Group");
137 for field in &self.fields {
138 let _ = printer.field(field);
139 }
140 printer.finish()
141 }
142 }
143}
144
145impl From<LinkedHashMap<String, Value, FxBuildHasher>> for Group {
146 fn from(hashmap: LinkedHashMap<String, Value, FxBuildHasher>) -> Self {
147 let mut keys = LinkedHashMap::with_capacity_and_hasher(hashmap.len(), Default::default());
148 Self::new(
149 hashmap
150 .into_iter()
151 .map(|(key, value)| {
152 if keys.insert(key, keys.len()).is_some() {
153 panic!("duplicate key");
154 }
155 value
156 })
157 .collect(),
158 Some(Arc::new(keys)),
159 )
160 }
161}
162
163macro_rules! tuple_downcast {
164 ($len:tt $($t:ident $i:tt)*) => (
165 impl<$($t,)*> DowncastFrom<Group> for ($($t,)*) where $($t: DowncastFrom<Value>,)* {
166 fn downcast_from(self_: Group) -> Result<Self, DowncastError> {
167 #[allow(unused_mut, unused_variables)]
168 let mut fields = self_.into_fields().into_iter();
169 if fields.len() != $len {
170 return Err(DowncastError{from:"",to:""});
171 }
172 Ok(($({let _ = $i;fields.next().unwrap().downcast()?},)*))
173 }
174 }
175 );
176}
177tuple!(tuple_downcast);
178
179macro_rules! tuple_from {
180 ($len:tt $($t:ident $i:tt)*) => (
181 impl<$($t,)*> From<($($t,)*)> for Group where $($t: Into<Value>,)* {
182 #[allow(unused_variables)]
183 fn from(value: ($($t,)*)) -> Self {
184 Group::new(vec![$(value.$i.into(),)*], None)
185 }
186 }
187 );
188}
189tuple!(tuple_from);
190
191