1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! This module contains Span-related definitions and common Span types.

use std::ops::{Add, AddAssign};

/// A span that is associated with values during validation.
///
/// Spans can represent a hierarchy for nested values
/// with the help of the [AddAssign](core::ops::AddAssign) trait.
///
/// This trait is automatically implemented.
pub trait Span: core::fmt::Debug + Clone + core::ops::AddAssign {}
impl<T: core::fmt::Debug + Clone + core::ops::AddAssign> Span for T {}

/// Spanned values can return an optional [Span](Span) about themselves.
pub trait Spanned {
    /// Span is information about the value.
    ///
    /// It is usually returned with validation errors so that the caller knows
    /// where the error happened in case of nested values such as arrays or maps.
    type Span: Span;

    /// Return the span for the value if any.
    ///
    /// Span hierarchy for nested values is controlled by the [Validators](crate::Validator),
    /// returning [None](Option::None) should reset the hierarchy during validation.
    fn span(&self) -> Option<Self::Span>;
}

#[cfg(feature = "smallvec")]
type KeysSmallVecArray = [String; 10];

#[cfg(feature = "smallvec")]
/// Using smallvec probably helps a bit by removing unnecessary allocations.
type KeysInner = smallvec_crate::SmallVec<KeysSmallVecArray>;

#[cfg(not(feature = "smallvec"))]
type KeysInner = Vec<String>;

/// A span consisting of consecutive string keys.
#[derive(Debug, Default, Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct Keys(KeysInner);

impl Keys {
    /// Create a new instance with no keys.
    pub fn new() -> Self {
        Keys(KeysInner::new())
    }

    /// Create a new empty instance with a capacity.
    pub fn with_capacity(cap: usize) -> Self {
        Keys(KeysInner::with_capacity(cap))
    }

    /// Iterator over the keys.
    pub fn iter(&self) -> impl Iterator<Item = &String> {
        self.0.iter()
    }

    /// Mutable Iterator over the keys.
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut String> {
        self.0.iter_mut()
    }

    /// Returns the keys joined by dots.
    pub fn dotted(&self) -> String {
        self.0.join(".")
    }

    /// Add a new key.
    pub fn push(&mut self, value: String) {
        self.0.push(value)
    }

    /// Return the inner container.
    pub fn into_inner(self) -> KeysInner {
        self.0
    }
}

impl AddAssign for Keys {
    fn add_assign(&mut self, rhs: Self) {
        self.0.extend(rhs.0.into_iter())
    }
}

impl<S: ToString> Add<S> for Keys {
    type Output = Self;
    fn add(mut self, rhs: S) -> Self::Output {
        self.push(rhs.to_string());
        self
    }
}

impl From<String> for Keys {
    fn from(s: String) -> Self {
        let mut v = Self::new();
        v.push(s);
        v
    }
}

impl IntoIterator for Keys {
    type Item = <KeysInner as IntoIterator>::Item;

    #[cfg(feature = "smallvec")]
    type IntoIter = smallvec_crate::IntoIter<KeysSmallVecArray>;

    #[cfg(not(feature = "smallvec"))]
    type IntoIter = std::vec::IntoIter<String>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}