1use std::{
3 fmt::Debug,
4 iter::FusedIterator,
5 marker::PhantomData,
6 ops::{Deref, DerefMut, RangeBounds},
7};
8
9use crate::{
10 CollectionColumns, CompareTypes, ShellError, Span, Type, TypeRelation, Value,
11 casing::{CaseInsensitive, CaseSensitive, CaseSensitivity, Casing, WrapCased},
12};
13
14use serde::{Deserialize, Serialize, de::Visitor, ser::SerializeMap};
15
16#[derive(Clone, Default, PartialEq)]
17pub struct Record {
18 inner: Vec<(String, Value)>,
19}
20
21impl Debug for Record {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 f.debug_map()
24 .entries(self.inner.iter().map(|(k, v)| (k, v)))
25 .finish()
26 }
27}
28
29#[repr(transparent)]
34pub struct CasedRecord<Sensitivity: CaseSensitivity>(Record, PhantomData<Sensitivity>);
35
36impl<Sensitivity: CaseSensitivity> CasedRecord<Sensitivity> {
37 #[inline]
38 const fn from_record(record: &Record) -> &Self {
39 unsafe { &*(record as *const Record as *const Self) }
41 }
42
43 #[inline]
44 const fn from_record_mut(record: &mut Record) -> &mut Self {
45 unsafe { &mut *(record as *mut Record as *mut Self) }
47 }
48
49 pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
50 let col = col.as_ref();
51 self.0.columns().rposition(|k| Sensitivity::eq(k, col))
52 }
53
54 pub fn contains(&self, col: impl AsRef<str>) -> bool {
55 self.index_of(col.as_ref()).is_some()
56 }
57
58 pub fn get(&self, col: impl AsRef<str>) -> Option<&Value> {
59 let index = self.index_of(col.as_ref())?;
60 Some(self.0.get_index(index)?.1)
61 }
62
63 pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
64 let index = self.index_of(col.as_ref())?;
65 Some(self.0.get_index_mut(index)?.1)
66 }
67
68 pub fn remove(&mut self, col: impl AsRef<str>) -> Option<Value> {
70 let index = self.index_of(col.as_ref())?;
71 Some(self.0.remove_index(index))
72 }
73
74 pub fn insert<K>(&mut self, col: K, val: Value) -> Option<Value>
78 where
79 K: AsRef<str> + Into<String>,
80 {
81 if let Some(curr_val) = self.get_mut(col.as_ref()) {
82 Some(std::mem::replace(curr_val, val))
83 } else {
84 self.0.push(col, val);
85 None
86 }
87 }
88}
89
90impl<'a> WrapCased for &'a Record {
91 type Wrapper<S: CaseSensitivity> = &'a CasedRecord<S>;
92
93 #[inline]
94 fn case_sensitive(self) -> Self::Wrapper<CaseSensitive> {
95 CasedRecord::<CaseSensitive>::from_record(self)
96 }
97
98 #[inline]
99 fn case_insensitive(self) -> Self::Wrapper<CaseInsensitive> {
100 CasedRecord::<CaseInsensitive>::from_record(self)
101 }
102}
103
104impl<'a> WrapCased for &'a mut Record {
105 type Wrapper<S: CaseSensitivity> = &'a mut CasedRecord<S>;
106
107 #[inline]
108 fn case_sensitive(self) -> Self::Wrapper<CaseSensitive> {
109 CasedRecord::<CaseSensitive>::from_record_mut(self)
110 }
111
112 #[inline]
113 fn case_insensitive(self) -> Self::Wrapper<CaseInsensitive> {
114 CasedRecord::<CaseInsensitive>::from_record_mut(self)
115 }
116}
117
118impl AsRef<Record> for Record {
119 fn as_ref(&self) -> &Record {
120 self
121 }
122}
123
124impl AsMut<Record> for Record {
125 fn as_mut(&mut self) -> &mut Record {
126 self
127 }
128}
129
130impl Deref for Record {
131 type Target = CasedRecord<CaseSensitive>;
132
133 fn deref(&self) -> &Self::Target {
134 self.case_sensitive()
135 }
136}
137
138impl DerefMut for Record {
139 fn deref_mut(&mut self) -> &mut Self::Target {
140 self.case_sensitive()
141 }
142}
143
144pub struct DynCasedRecord<R> {
148 record: R,
149 casing: Casing,
150}
151
152impl Clone for DynCasedRecord<&Record> {
153 fn clone(&self) -> Self {
154 *self
155 }
156}
157
158impl Copy for DynCasedRecord<&Record> {}
159
160impl<'a> DynCasedRecord<&'a Record> {
161 pub fn index_of(self, col: impl AsRef<str>) -> Option<usize> {
162 match self.casing {
163 Casing::Sensitive => self.record.case_sensitive().index_of(col.as_ref()),
164 Casing::Insensitive => self.record.case_insensitive().index_of(col.as_ref()),
165 }
166 }
167
168 pub fn contains(self, col: impl AsRef<str>) -> bool {
169 self.get(col.as_ref()).is_some()
170 }
171
172 pub fn get(self, col: impl AsRef<str>) -> Option<&'a Value> {
173 match self.casing {
174 Casing::Sensitive => self.record.case_sensitive().get(col.as_ref()),
175 Casing::Insensitive => self.record.case_insensitive().get(col.as_ref()),
176 }
177 }
178}
179
180impl<'a> DynCasedRecord<&'a mut Record> {
181 pub fn reborrow(&self) -> DynCasedRecord<&Record> {
183 DynCasedRecord {
184 record: &*self.record,
185 casing: self.casing,
186 }
187 }
188
189 pub fn reborrow_mut(&mut self) -> DynCasedRecord<&mut Record> {
238 DynCasedRecord {
239 record: &mut *self.record,
240 casing: self.casing,
241 }
242 }
243
244 pub fn get_mut(self, col: impl AsRef<str>) -> Option<&'a mut Value> {
245 match self.casing {
246 Casing::Sensitive => self.record.case_sensitive().get_mut(col.as_ref()),
247 Casing::Insensitive => self.record.case_insensitive().get_mut(col.as_ref()),
248 }
249 }
250
251 pub fn remove(self, col: impl AsRef<str>) -> Option<Value> {
252 match self.casing {
253 Casing::Sensitive => self.record.case_sensitive().remove(col.as_ref()),
254 Casing::Insensitive => self.record.case_insensitive().remove(col.as_ref()),
255 }
256 }
257
258 pub fn insert<K>(self, col: K, val: Value) -> Option<Value>
262 where
263 K: AsRef<str> + Into<String>,
264 {
265 match self.casing {
266 Casing::Sensitive => self.record.case_sensitive().insert(col.as_ref(), val),
267 Casing::Insensitive => self.record.case_insensitive().insert(col.as_ref(), val),
268 }
269 }
270}
271
272impl Record {
273 pub fn new() -> Self {
274 Self::default()
275 }
276
277 pub fn with_capacity(capacity: usize) -> Self {
278 Self {
279 inner: Vec::with_capacity(capacity),
280 }
281 }
282
283 pub fn memory_size(&self) -> usize {
285 std::mem::size_of::<Self>()
286 + self
287 .inner
288 .iter()
289 .map(|(k, v)| k.capacity() + v.memory_size())
290 .sum::<usize>()
291 }
292
293 pub fn cased(&self, casing: Casing) -> DynCasedRecord<&Record> {
294 DynCasedRecord {
295 record: self,
296 casing,
297 }
298 }
299
300 pub fn cased_mut(&mut self, casing: Casing) -> DynCasedRecord<&mut Record> {
301 DynCasedRecord {
302 record: self,
303 casing,
304 }
305 }
306
307 pub fn from_raw_cols_vals(
314 cols: Vec<String>,
315 vals: Vec<Value>,
316 input_span: Span,
317 creation_site_span: Span,
318 ) -> Result<Self, ShellError> {
319 if cols.len() == vals.len() {
320 let inner = cols.into_iter().zip(vals).collect();
321 Ok(Self { inner })
322 } else {
323 Err(ShellError::RecordColsValsMismatch {
324 bad_value: input_span,
325 creation_site: creation_site_span,
326 })
327 }
328 }
329
330 pub fn iter(&self) -> Iter<'_> {
331 self.into_iter()
332 }
333
334 pub fn iter_mut(&mut self) -> IterMut<'_> {
335 self.into_iter()
336 }
337
338 pub fn is_empty(&self) -> bool {
339 self.inner.is_empty()
340 }
341
342 pub fn len(&self) -> usize {
343 self.inner.len()
344 }
345
346 pub fn push(&mut self, col: impl Into<String>, val: Value) {
354 self.inner.push((col.into(), val));
355 }
356
357 pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
358 self.inner.get(idx).map(|(col, val): &(_, _)| (col, val))
359 }
360
361 pub fn get_index_mut(&mut self, idx: usize) -> Option<(&mut String, &mut Value)> {
362 self.inner.get_mut(idx).map(|(col, val)| (col, val))
363 }
364
365 fn remove_index(&mut self, index: usize) -> Value {
367 self.inner.remove(index).1
368 }
369
370 pub fn retain<F>(&mut self, mut keep: F)
388 where
389 F: FnMut(&str, &Value) -> bool,
390 {
391 self.retain_mut(|k, v| keep(k, v));
392 }
393
394 pub fn retain_mut<F>(&mut self, mut keep: F)
432 where
433 F: FnMut(&str, &mut Value) -> bool,
434 {
435 self.inner.retain_mut(|(col, val)| keep(col, val));
436 }
437
438 pub fn truncate(&mut self, len: usize) {
459 self.inner.truncate(len);
460 }
461
462 pub fn truncate_front(&mut self, len: usize) {
463 if self.len() < len {
464 return;
465 }
466 let drop = self.len() - len;
467 self.inner.drain(..drop);
468 }
469
470 pub fn columns(&self) -> Columns<'_> {
471 Columns {
472 iter: self.inner.iter(),
473 }
474 }
475
476 pub fn into_columns(self) -> IntoColumns {
477 IntoColumns {
478 iter: self.inner.into_iter(),
479 }
480 }
481
482 pub fn values(&self) -> Values<'_> {
483 Values {
484 iter: self.inner.iter(),
485 }
486 }
487
488 pub fn into_values(self) -> IntoValues {
489 IntoValues {
490 iter: self.inner.into_iter(),
491 }
492 }
493
494 pub fn drain<R>(&mut self, range: R) -> Drain<'_>
516 where
517 R: RangeBounds<usize> + Clone,
518 {
519 Drain {
520 iter: self.inner.drain(range),
521 }
522 }
523
524 pub fn sort_cols(&mut self) {
547 self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
548 }
549}
550
551impl CompareTypes<CollectionColumns<Type>> for Record {
552 fn compare_types(&self, other: &CollectionColumns<Type>) -> Option<TypeRelation> {
553 match (self.is_empty(), other.is_empty()) {
554 (true, true) => return Some(TypeRelation::Equal),
555 (true, false) => return Some(TypeRelation::Supertype),
556 (false, true) => return Some(TypeRelation::Subtype),
557 (false, false) => {}
558 }
559
560 let (flipped, eq) = match self.len().cmp(&other.len()) {
561 std::cmp::Ordering::Less => (false, false),
562 std::cmp::Ordering::Equal => (false, true),
563 std::cmp::Ordering::Greater => (true, false),
564 };
565
566 let start = match eq {
567 true => TypeRelation::Equal,
568 false => TypeRelation::Supertype,
569 };
570
571 if flipped {
572 let lhs = other;
573 let rhs = self;
574 lhs.iter()
575 .map(|(lhs_key, lhs_ty)| {
576 match rhs.get(lhs_key) {
577 Some(rhs_val) => {
578 if CompareTypes::<Type>::is_any(lhs_ty) || rhs_val.is_any() {
579 Some(TypeRelation::Equal)
581 } else {
582 rhs_val.compare_types(lhs_ty).map(TypeRelation::reverse)
585 }
586 }
587 None => None,
588 }
589 })
590 .try_fold(start, |acc, e| acc.combine(e?))
591 .map(TypeRelation::reverse)
592 } else {
593 let lhs = self;
594 let rhs = other;
595 lhs.iter()
596 .map(|(lhs_key, lhs_val)| {
597 match rhs.get(lhs_key) {
598 Some(rhs_ty) => {
599 if lhs_val.is_any() || CompareTypes::<Type>::is_any(rhs_ty) {
600 Some(TypeRelation::Equal)
602 } else {
603 lhs_val.compare_types(rhs_ty)
604 }
605 }
606 None => None,
607 }
608 })
609 .try_fold(start, |acc, e| acc.combine(e?))
610 }
611 }
612}
613
614impl Serialize for Record {
615 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
616 where
617 S: serde::Serializer,
618 {
619 let mut map = serializer.serialize_map(Some(self.len()))?;
620 for (k, v) in self {
621 map.serialize_entry(k, v)?;
622 }
623 map.end()
624 }
625}
626
627impl<'de> Deserialize<'de> for Record {
628 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
652 where
653 D: serde::Deserializer<'de>,
654 {
655 deserializer.deserialize_map(RecordVisitor)
656 }
657}
658
659struct RecordVisitor;
660
661impl<'de> Visitor<'de> for RecordVisitor {
662 type Value = Record;
663
664 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
665 formatter.write_str("a nushell `Record` mapping string keys/columns to nushell `Value`")
666 }
667
668 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
669 where
670 A: serde::de::MapAccess<'de>,
671 {
672 let mut record = Record::with_capacity(map.size_hint().unwrap_or(0));
673
674 while let Some((key, value)) = map.next_entry::<String, Value>()? {
675 if record.insert(key, value).is_some() {
676 return Err(serde::de::Error::custom(
677 "invalid entry, duplicate keys are not allowed for `Record`",
678 ));
679 }
680 }
681
682 Ok(record)
683 }
684}
685
686impl FromIterator<(String, Value)> for Record {
687 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
688 Self {
690 inner: iter.into_iter().collect(),
691 }
692 }
693}
694
695impl Extend<(String, Value)> for Record {
696 fn extend<T: IntoIterator<Item = (String, Value)>>(&mut self, iter: T) {
697 for (k, v) in iter {
698 self.push(k, v)
700 }
701 }
702}
703
704pub struct IntoIter {
705 iter: std::vec::IntoIter<(String, Value)>,
706}
707
708impl Iterator for IntoIter {
709 type Item = (String, Value);
710
711 fn next(&mut self) -> Option<Self::Item> {
712 self.iter.next()
713 }
714
715 fn size_hint(&self) -> (usize, Option<usize>) {
716 self.iter.size_hint()
717 }
718}
719
720impl DoubleEndedIterator for IntoIter {
721 fn next_back(&mut self) -> Option<Self::Item> {
722 self.iter.next_back()
723 }
724}
725
726impl ExactSizeIterator for IntoIter {
727 fn len(&self) -> usize {
728 self.iter.len()
729 }
730}
731
732impl FusedIterator for IntoIter {}
733
734impl IntoIterator for Record {
735 type Item = (String, Value);
736
737 type IntoIter = IntoIter;
738
739 fn into_iter(self) -> Self::IntoIter {
740 IntoIter {
741 iter: self.inner.into_iter(),
742 }
743 }
744}
745
746pub struct Iter<'a> {
747 iter: std::slice::Iter<'a, (String, Value)>,
748}
749
750impl<'a> Iterator for Iter<'a> {
751 type Item = (&'a String, &'a Value);
752
753 fn next(&mut self) -> Option<Self::Item> {
754 self.iter.next().map(|(col, val): &(_, _)| (col, val))
755 }
756
757 fn size_hint(&self) -> (usize, Option<usize>) {
758 self.iter.size_hint()
759 }
760}
761
762impl DoubleEndedIterator for Iter<'_> {
763 fn next_back(&mut self) -> Option<Self::Item> {
764 self.iter.next_back().map(|(col, val): &(_, _)| (col, val))
765 }
766}
767
768impl ExactSizeIterator for Iter<'_> {
769 fn len(&self) -> usize {
770 self.iter.len()
771 }
772}
773
774impl FusedIterator for Iter<'_> {}
775
776impl<'a> IntoIterator for &'a Record {
777 type Item = (&'a String, &'a Value);
778
779 type IntoIter = Iter<'a>;
780
781 fn into_iter(self) -> Self::IntoIter {
782 Iter {
783 iter: self.inner.iter(),
784 }
785 }
786}
787
788pub struct IterMut<'a> {
789 iter: std::slice::IterMut<'a, (String, Value)>,
790}
791
792impl<'a> Iterator for IterMut<'a> {
793 type Item = (&'a String, &'a mut Value);
794
795 fn next(&mut self) -> Option<Self::Item> {
796 self.iter.next().map(|(col, val)| (&*col, val))
797 }
798
799 fn size_hint(&self) -> (usize, Option<usize>) {
800 self.iter.size_hint()
801 }
802}
803
804impl DoubleEndedIterator for IterMut<'_> {
805 fn next_back(&mut self) -> Option<Self::Item> {
806 self.iter.next_back().map(|(col, val)| (&*col, val))
807 }
808}
809
810impl ExactSizeIterator for IterMut<'_> {
811 fn len(&self) -> usize {
812 self.iter.len()
813 }
814}
815
816impl FusedIterator for IterMut<'_> {}
817
818impl<'a> IntoIterator for &'a mut Record {
819 type Item = (&'a String, &'a mut Value);
820
821 type IntoIter = IterMut<'a>;
822
823 fn into_iter(self) -> Self::IntoIter {
824 IterMut {
825 iter: self.inner.iter_mut(),
826 }
827 }
828}
829
830pub struct Columns<'a> {
831 iter: std::slice::Iter<'a, (String, Value)>,
832}
833
834impl<'a> Iterator for Columns<'a> {
835 type Item = &'a String;
836
837 fn next(&mut self) -> Option<Self::Item> {
838 self.iter.next().map(|(col, _)| col)
839 }
840
841 fn size_hint(&self) -> (usize, Option<usize>) {
842 self.iter.size_hint()
843 }
844}
845
846impl DoubleEndedIterator for Columns<'_> {
847 fn next_back(&mut self) -> Option<Self::Item> {
848 self.iter.next_back().map(|(col, _)| col)
849 }
850}
851
852impl ExactSizeIterator for Columns<'_> {
853 fn len(&self) -> usize {
854 self.iter.len()
855 }
856}
857
858impl FusedIterator for Columns<'_> {}
859
860pub struct IntoColumns {
861 iter: std::vec::IntoIter<(String, Value)>,
862}
863
864impl Iterator for IntoColumns {
865 type Item = String;
866
867 fn next(&mut self) -> Option<Self::Item> {
868 self.iter.next().map(|(col, _)| col)
869 }
870
871 fn size_hint(&self) -> (usize, Option<usize>) {
872 self.iter.size_hint()
873 }
874}
875
876impl DoubleEndedIterator for IntoColumns {
877 fn next_back(&mut self) -> Option<Self::Item> {
878 self.iter.next_back().map(|(col, _)| col)
879 }
880}
881
882impl ExactSizeIterator for IntoColumns {
883 fn len(&self) -> usize {
884 self.iter.len()
885 }
886}
887
888impl FusedIterator for IntoColumns {}
889
890pub struct Values<'a> {
891 iter: std::slice::Iter<'a, (String, Value)>,
892}
893
894impl<'a> Iterator for Values<'a> {
895 type Item = &'a Value;
896
897 fn next(&mut self) -> Option<Self::Item> {
898 self.iter.next().map(|(_, val)| val)
899 }
900
901 fn size_hint(&self) -> (usize, Option<usize>) {
902 self.iter.size_hint()
903 }
904}
905
906impl DoubleEndedIterator for Values<'_> {
907 fn next_back(&mut self) -> Option<Self::Item> {
908 self.iter.next_back().map(|(_, val)| val)
909 }
910}
911
912impl ExactSizeIterator for Values<'_> {
913 fn len(&self) -> usize {
914 self.iter.len()
915 }
916}
917
918impl FusedIterator for Values<'_> {}
919
920pub struct IntoValues {
921 iter: std::vec::IntoIter<(String, Value)>,
922}
923
924impl Iterator for IntoValues {
925 type Item = Value;
926
927 fn next(&mut self) -> Option<Self::Item> {
928 self.iter.next().map(|(_, val)| val)
929 }
930
931 fn size_hint(&self) -> (usize, Option<usize>) {
932 self.iter.size_hint()
933 }
934}
935
936impl DoubleEndedIterator for IntoValues {
937 fn next_back(&mut self) -> Option<Self::Item> {
938 self.iter.next_back().map(|(_, val)| val)
939 }
940}
941
942impl ExactSizeIterator for IntoValues {
943 fn len(&self) -> usize {
944 self.iter.len()
945 }
946}
947
948impl FusedIterator for IntoValues {}
949
950pub struct Drain<'a> {
951 iter: std::vec::Drain<'a, (String, Value)>,
952}
953
954impl Iterator for Drain<'_> {
955 type Item = (String, Value);
956
957 fn next(&mut self) -> Option<Self::Item> {
958 self.iter.next()
959 }
960
961 fn size_hint(&self) -> (usize, Option<usize>) {
962 self.iter.size_hint()
963 }
964}
965
966impl DoubleEndedIterator for Drain<'_> {
967 fn next_back(&mut self) -> Option<Self::Item> {
968 self.iter.next_back()
969 }
970}
971
972impl ExactSizeIterator for Drain<'_> {
973 fn len(&self) -> usize {
974 self.iter.len()
975 }
976}
977
978impl FusedIterator for Drain<'_> {}
979
980#[macro_export]
981macro_rules! record {
982 {$($col:expr => $val:expr),+ $(,)?} => {
985 $crate::Record::from_raw_cols_vals(
986 ::std::vec![$($col.into(),)+],
987 ::std::vec![$($val,)+],
988 $crate::Span::unknown(),
989 $crate::Span::unknown(),
990 ).unwrap()
991 };
992 {} => {
993 $crate::Record::new()
994 };
995}
996
997#[macro_export]
1020macro_rules! test_record {
1021 {$($col:expr => $val:expr),+ $(,)?} => {
1022 $crate::Value::test_record($crate::record! {
1023 $($col => $crate::IntoValue::into_value($val, $crate::Span::test_data())),+
1024 })
1025 };
1026 {} => {
1027 record! {}
1028 };
1029}
1030
1031#[doc(hidden)]
1032pub const fn count_helper<const N: usize>(_: [(); N]) -> usize {
1033 N
1034}
1035
1036#[macro_export]
1054macro_rules! test_table {
1055 (@replace_expr $_t:tt $sub:expr) => { $sub };
1056 (@count_tts $($smth:tt)*) => {
1057 $crate::record::count_helper([$($crate::test_table!(@replace_expr $smth ())),*])
1058 };
1059 [[$($col:expr),+ $(,)?]; $([$($val:expr),+ $(,)?]),+ $(,)?] => {{
1060 const COLUMNS: usize = $crate::test_table!(@count_tts $($col)+);
1061 let columns: ::std::vec::Vec<::std::string::String> = ::std::vec![$($col.into()),+];
1062 let rows = vec![ $(
1063 {
1064 const ROW_ITEMS: usize = $crate::test_table!(@count_tts $($val)+);
1065 const _: () = assert!(ROW_ITEMS == COLUMNS) ;
1066 $crate::Value::test_record($crate::Record::from_raw_cols_vals(
1067 columns.clone(),
1068 ::std::vec![ $(
1069 $crate::IntoValue::into_value($val, $crate::Span::test_data())
1070 ),+ ],
1071 $crate::Span::test_data(),
1072 $crate::Span::test_data(),
1073 ).expect("Number of columns and rows should be equal"))
1074 }
1075 ),+ ];
1076 $crate::Value::test_list(rows)
1077 }};
1078}