1use std::{iter::FusedIterator, ops::RangeBounds};
3
4use crate::{ShellError, Span, Value};
5
6use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};
7
8#[derive(Debug, Clone, Default)]
9pub struct Record {
10 inner: Vec<(String, Value)>,
11}
12
13impl Record {
14 pub fn new() -> Self {
15 Self::default()
16 }
17
18 pub fn with_capacity(capacity: usize) -> Self {
19 Self {
20 inner: Vec::with_capacity(capacity),
21 }
22 }
23
24 pub fn from_raw_cols_vals(
31 cols: Vec<String>,
32 vals: Vec<Value>,
33 input_span: Span,
34 creation_site_span: Span,
35 ) -> Result<Self, ShellError> {
36 if cols.len() == vals.len() {
37 let inner = cols.into_iter().zip(vals).collect();
38 Ok(Self { inner })
39 } else {
40 Err(ShellError::RecordColsValsMismatch {
41 bad_value: input_span,
42 creation_site: creation_site_span,
43 })
44 }
45 }
46
47 pub fn iter(&self) -> Iter {
48 self.into_iter()
49 }
50
51 pub fn iter_mut(&mut self) -> IterMut {
52 self.into_iter()
53 }
54
55 pub fn is_empty(&self) -> bool {
56 self.inner.is_empty()
57 }
58
59 pub fn len(&self) -> usize {
60 self.inner.len()
61 }
62
63 pub fn push(&mut self, col: impl Into<String>, val: Value) {
69 self.inner.push((col.into(), val));
70 }
71
72 pub fn insert<K>(&mut self, col: K, val: Value) -> Option<Value>
76 where
77 K: AsRef<str> + Into<String>,
78 {
79 if let Some(curr_val) = self.get_mut(&col) {
80 Some(std::mem::replace(curr_val, val))
81 } else {
82 self.push(col, val);
83 None
84 }
85 }
86
87 pub fn contains(&self, col: impl AsRef<str>) -> bool {
88 self.columns().any(|k| k == col.as_ref())
89 }
90
91 pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
92 self.columns().position(|k| k == col.as_ref())
93 }
94
95 pub fn get(&self, col: impl AsRef<str>) -> Option<&Value> {
96 self.inner
97 .iter()
98 .find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
99 }
100
101 pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
102 self.inner
103 .iter_mut()
104 .find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
105 }
106
107 pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
108 self.inner.get(idx).map(|(col, val): &(_, _)| (col, val))
109 }
110
111 pub fn remove(&mut self, col: impl AsRef<str>) -> Option<Value> {
117 let idx = self.index_of(col)?;
118 let (_, val) = self.inner.remove(idx);
119 Some(val)
120 }
121
122 pub fn retain<F>(&mut self, mut keep: F)
140 where
141 F: FnMut(&str, &Value) -> bool,
142 {
143 self.retain_mut(|k, v| keep(k, v));
144 }
145
146 pub fn retain_mut<F>(&mut self, mut keep: F)
184 where
185 F: FnMut(&str, &mut Value) -> bool,
186 {
187 self.inner.retain_mut(|(col, val)| keep(col, val));
188 }
189
190 pub fn truncate(&mut self, len: usize) {
211 self.inner.truncate(len);
212 }
213
214 pub fn columns(&self) -> Columns {
215 Columns {
216 iter: self.inner.iter(),
217 }
218 }
219
220 pub fn into_columns(self) -> IntoColumns {
221 IntoColumns {
222 iter: self.inner.into_iter(),
223 }
224 }
225
226 pub fn values(&self) -> Values {
227 Values {
228 iter: self.inner.iter(),
229 }
230 }
231
232 pub fn into_values(self) -> IntoValues {
233 IntoValues {
234 iter: self.inner.into_iter(),
235 }
236 }
237
238 pub fn drain<R>(&mut self, range: R) -> Drain
260 where
261 R: RangeBounds<usize> + Clone,
262 {
263 Drain {
264 iter: self.inner.drain(range),
265 }
266 }
267
268 pub fn sort_cols(&mut self) {
291 self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
292 }
293}
294
295impl Serialize for Record {
296 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297 where
298 S: serde::Serializer,
299 {
300 let mut map = serializer.serialize_map(Some(self.len()))?;
301 for (k, v) in self {
302 map.serialize_entry(k, v)?;
303 }
304 map.end()
305 }
306}
307
308impl<'de> Deserialize<'de> for Record {
309 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
333 where
334 D: serde::Deserializer<'de>,
335 {
336 deserializer.deserialize_map(RecordVisitor)
337 }
338}
339
340struct RecordVisitor;
341
342impl<'de> Visitor<'de> for RecordVisitor {
343 type Value = Record;
344
345 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
346 formatter.write_str("a nushell `Record` mapping string keys/columns to nushell `Value`")
347 }
348
349 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
350 where
351 A: serde::de::MapAccess<'de>,
352 {
353 let mut record = Record::with_capacity(map.size_hint().unwrap_or(0));
354
355 while let Some((key, value)) = map.next_entry::<String, Value>()? {
356 if record.insert(key, value).is_some() {
357 return Err(serde::de::Error::custom(
358 "invalid entry, duplicate keys are not allowed for `Record`",
359 ));
360 }
361 }
362
363 Ok(record)
364 }
365}
366
367impl FromIterator<(String, Value)> for Record {
368 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
369 Self {
371 inner: iter.into_iter().collect(),
372 }
373 }
374}
375
376impl Extend<(String, Value)> for Record {
377 fn extend<T: IntoIterator<Item = (String, Value)>>(&mut self, iter: T) {
378 for (k, v) in iter {
379 self.push(k, v)
381 }
382 }
383}
384
385pub struct IntoIter {
386 iter: std::vec::IntoIter<(String, Value)>,
387}
388
389impl Iterator for IntoIter {
390 type Item = (String, Value);
391
392 fn next(&mut self) -> Option<Self::Item> {
393 self.iter.next()
394 }
395
396 fn size_hint(&self) -> (usize, Option<usize>) {
397 self.iter.size_hint()
398 }
399}
400
401impl DoubleEndedIterator for IntoIter {
402 fn next_back(&mut self) -> Option<Self::Item> {
403 self.iter.next_back()
404 }
405}
406
407impl ExactSizeIterator for IntoIter {
408 fn len(&self) -> usize {
409 self.iter.len()
410 }
411}
412
413impl FusedIterator for IntoIter {}
414
415impl IntoIterator for Record {
416 type Item = (String, Value);
417
418 type IntoIter = IntoIter;
419
420 fn into_iter(self) -> Self::IntoIter {
421 IntoIter {
422 iter: self.inner.into_iter(),
423 }
424 }
425}
426
427pub struct Iter<'a> {
428 iter: std::slice::Iter<'a, (String, Value)>,
429}
430
431impl<'a> Iterator for Iter<'a> {
432 type Item = (&'a String, &'a Value);
433
434 fn next(&mut self) -> Option<Self::Item> {
435 self.iter.next().map(|(col, val): &(_, _)| (col, val))
436 }
437
438 fn size_hint(&self) -> (usize, Option<usize>) {
439 self.iter.size_hint()
440 }
441}
442
443impl DoubleEndedIterator for Iter<'_> {
444 fn next_back(&mut self) -> Option<Self::Item> {
445 self.iter.next_back().map(|(col, val): &(_, _)| (col, val))
446 }
447}
448
449impl ExactSizeIterator for Iter<'_> {
450 fn len(&self) -> usize {
451 self.iter.len()
452 }
453}
454
455impl FusedIterator for Iter<'_> {}
456
457impl<'a> IntoIterator for &'a Record {
458 type Item = (&'a String, &'a Value);
459
460 type IntoIter = Iter<'a>;
461
462 fn into_iter(self) -> Self::IntoIter {
463 Iter {
464 iter: self.inner.iter(),
465 }
466 }
467}
468
469pub struct IterMut<'a> {
470 iter: std::slice::IterMut<'a, (String, Value)>,
471}
472
473impl<'a> Iterator for IterMut<'a> {
474 type Item = (&'a String, &'a mut Value);
475
476 fn next(&mut self) -> Option<Self::Item> {
477 self.iter.next().map(|(col, val)| (&*col, val))
478 }
479
480 fn size_hint(&self) -> (usize, Option<usize>) {
481 self.iter.size_hint()
482 }
483}
484
485impl DoubleEndedIterator for IterMut<'_> {
486 fn next_back(&mut self) -> Option<Self::Item> {
487 self.iter.next_back().map(|(col, val)| (&*col, val))
488 }
489}
490
491impl ExactSizeIterator for IterMut<'_> {
492 fn len(&self) -> usize {
493 self.iter.len()
494 }
495}
496
497impl FusedIterator for IterMut<'_> {}
498
499impl<'a> IntoIterator for &'a mut Record {
500 type Item = (&'a String, &'a mut Value);
501
502 type IntoIter = IterMut<'a>;
503
504 fn into_iter(self) -> Self::IntoIter {
505 IterMut {
506 iter: self.inner.iter_mut(),
507 }
508 }
509}
510
511pub struct Columns<'a> {
512 iter: std::slice::Iter<'a, (String, Value)>,
513}
514
515impl<'a> Iterator for Columns<'a> {
516 type Item = &'a String;
517
518 fn next(&mut self) -> Option<Self::Item> {
519 self.iter.next().map(|(col, _)| col)
520 }
521
522 fn size_hint(&self) -> (usize, Option<usize>) {
523 self.iter.size_hint()
524 }
525}
526
527impl DoubleEndedIterator for Columns<'_> {
528 fn next_back(&mut self) -> Option<Self::Item> {
529 self.iter.next_back().map(|(col, _)| col)
530 }
531}
532
533impl ExactSizeIterator for Columns<'_> {
534 fn len(&self) -> usize {
535 self.iter.len()
536 }
537}
538
539impl FusedIterator for Columns<'_> {}
540
541pub struct IntoColumns {
542 iter: std::vec::IntoIter<(String, Value)>,
543}
544
545impl Iterator for IntoColumns {
546 type Item = String;
547
548 fn next(&mut self) -> Option<Self::Item> {
549 self.iter.next().map(|(col, _)| col)
550 }
551
552 fn size_hint(&self) -> (usize, Option<usize>) {
553 self.iter.size_hint()
554 }
555}
556
557impl DoubleEndedIterator for IntoColumns {
558 fn next_back(&mut self) -> Option<Self::Item> {
559 self.iter.next_back().map(|(col, _)| col)
560 }
561}
562
563impl ExactSizeIterator for IntoColumns {
564 fn len(&self) -> usize {
565 self.iter.len()
566 }
567}
568
569impl FusedIterator for IntoColumns {}
570
571pub struct Values<'a> {
572 iter: std::slice::Iter<'a, (String, Value)>,
573}
574
575impl<'a> Iterator for Values<'a> {
576 type Item = &'a Value;
577
578 fn next(&mut self) -> Option<Self::Item> {
579 self.iter.next().map(|(_, val)| val)
580 }
581
582 fn size_hint(&self) -> (usize, Option<usize>) {
583 self.iter.size_hint()
584 }
585}
586
587impl DoubleEndedIterator for Values<'_> {
588 fn next_back(&mut self) -> Option<Self::Item> {
589 self.iter.next_back().map(|(_, val)| val)
590 }
591}
592
593impl ExactSizeIterator for Values<'_> {
594 fn len(&self) -> usize {
595 self.iter.len()
596 }
597}
598
599impl FusedIterator for Values<'_> {}
600
601pub struct IntoValues {
602 iter: std::vec::IntoIter<(String, Value)>,
603}
604
605impl Iterator for IntoValues {
606 type Item = Value;
607
608 fn next(&mut self) -> Option<Self::Item> {
609 self.iter.next().map(|(_, val)| val)
610 }
611
612 fn size_hint(&self) -> (usize, Option<usize>) {
613 self.iter.size_hint()
614 }
615}
616
617impl DoubleEndedIterator for IntoValues {
618 fn next_back(&mut self) -> Option<Self::Item> {
619 self.iter.next_back().map(|(_, val)| val)
620 }
621}
622
623impl ExactSizeIterator for IntoValues {
624 fn len(&self) -> usize {
625 self.iter.len()
626 }
627}
628
629impl FusedIterator for IntoValues {}
630
631pub struct Drain<'a> {
632 iter: std::vec::Drain<'a, (String, Value)>,
633}
634
635impl Iterator for Drain<'_> {
636 type Item = (String, Value);
637
638 fn next(&mut self) -> Option<Self::Item> {
639 self.iter.next()
640 }
641
642 fn size_hint(&self) -> (usize, Option<usize>) {
643 self.iter.size_hint()
644 }
645}
646
647impl DoubleEndedIterator for Drain<'_> {
648 fn next_back(&mut self) -> Option<Self::Item> {
649 self.iter.next_back()
650 }
651}
652
653impl ExactSizeIterator for Drain<'_> {
654 fn len(&self) -> usize {
655 self.iter.len()
656 }
657}
658
659impl FusedIterator for Drain<'_> {}
660
661#[macro_export]
662macro_rules! record {
663 {$($col:expr => $val:expr),+ $(,)?} => {
666 $crate::Record::from_raw_cols_vals(
667 ::std::vec![$($col.into(),)+],
668 ::std::vec![$($val,)+],
669 $crate::Span::unknown(),
670 $crate::Span::unknown(),
671 ).unwrap()
672 };
673 {} => {
674 $crate::Record::new()
675 };
676}