kutil_std/foster/
string_vector.rs

1use super::{
2    super::{borrow::*, iter::*},
3    foster::*,
4    has_length::*,
5    iterator::*,
6};
7
8use std::{cmp::*, hash::*, slice::*};
9
10/// [Foster] for [Vec]\<[String]\>.
11///
12/// Supports [IntoOwned], [HasLength], [Eq]/[PartialEq], [Ord]/[PartialOrd], [Hash], and
13/// [IntoIterator].
14pub type FosterStringVector = Foster<Vec<String>, &'static [&'static str]>;
15
16impl IntoOwned for FosterStringVector {
17    fn into_owned(self) -> Self {
18        match self {
19            Self::Owned(_) => self,
20            Self::Fostered(strings) => Self::new_owned(strings.iter().map(|string| (*string).into()).collect()),
21        }
22    }
23}
24
25impl HasLength for FosterStringVector {
26    fn len(&self) -> usize {
27        match self {
28            Self::Owned(strings) => strings.len(),
29            Self::Fostered(strings) => strings.len(),
30        }
31    }
32}
33
34impl PartialEq for FosterStringVector {
35    fn eq(&self, other: &Self) -> bool {
36        match self {
37            Self::Owned(strings) => match other {
38                Self::Owned(other_strings) => strings.eq(other_strings),
39
40                Self::Fostered(other_strings) => {
41                    if strings.len() == other_strings.len() {
42                        let mut equal = true;
43                        for (index, string) in strings.iter().enumerate() {
44                            if string.ne(other_strings[index]) {
45                                equal = false;
46                                break;
47                            }
48                        }
49                        equal
50                    } else {
51                        false
52                    }
53                }
54            },
55
56            Self::Fostered(strings) => match other {
57                Self::Owned(other_strings) => {
58                    if strings.len() == other_strings.len() {
59                        let mut equal = true;
60                        for (index, string) in strings.iter().enumerate() {
61                            if string.ne(&other_strings[index]) {
62                                equal = false;
63                                break;
64                            }
65                        }
66                        equal
67                    } else {
68                        false
69                    }
70                }
71
72                Self::Fostered(other_strings) => strings.eq(other_strings),
73            },
74        }
75    }
76}
77
78impl Eq for FosterStringVector {}
79
80impl Hash for FosterStringVector {
81    fn hash<HasherT>(&self, state: &mut HasherT)
82    where
83        HasherT: Hasher,
84    {
85        match self {
86            Self::Owned(strings) => {
87                for string in strings {
88                    state.write(string.as_bytes());
89                }
90            }
91
92            Self::Fostered(strings) => {
93                for string in strings.iter() {
94                    state.write(string.as_bytes());
95                }
96            }
97        }
98    }
99}
100
101impl<'own> IntoIterator for &'own FosterStringVector {
102    type Item = &'own str;
103    type IntoIter =
104        FosterIterator<&'own str, &'own String, &'own &'static str, Iter<'own, String>, Iter<'own, &'static str>>;
105
106    fn into_iter(self) -> Self::IntoIter {
107        match self {
108            Foster::Owned(strings) => Foster::new_owned(ConvertingIterator::new(strings.iter(), |string| &string)),
109            Foster::Fostered(strings) => Foster::new_static(ConvertingIterator::new(strings.iter(), |string| string)),
110        }
111    }
112}
113
114/// Delegates traits to a [FosterStringVector] newtype.
115///
116/// Example:
117///
118/// ```
119/// #[derive(Clone, Debug)]
120/// pub struct MyType(FosterStringVector);
121///
122/// delegate_newtype_of_foster_string_vector!(MyType);
123/// ```
124///
125#[macro_export]
126macro_rules! delegate_newtype_of_foster_string_vector {
127    ( $type:ty ) => {
128        impl $type {
129            /// Constructor.
130            pub fn new_owned(strings: ::std::vec::Vec<::std::string::String>) -> Self {
131                Self(::kutil_std::foster::Foster::new_owned(strings))
132            }
133
134            /// Constructor.
135            pub const fn new_static(strings: &'static [&'static str]) -> Self {
136                Self(::kutil_std::foster::Foster::new_static(strings))
137            }
138        }
139
140        impl ::kutil_std::borrow::IntoOwned for $type {
141            fn into_owned(self) -> Self {
142                match self.0 {
143                    ::kutil_std::foster::Foster::Owned(_) => self,
144                    ::kutil_std::foster::Foster::Fostered(_) => Self(self.0.into_owned()),
145                }
146            }
147        }
148
149        impl ::kutil_std::foster::HasLength for $type {
150            fn len(&self) -> usize {
151                self.0.len()
152            }
153        }
154
155        impl From<::std::vec::Vec<::std::string::String>> for $type {
156            fn from(strings: Vec<::std::string::String>) -> Self {
157                strings.into()
158            }
159        }
160
161        impl ::std::cmp::PartialEq for $type {
162            fn eq(&self, other: &Self) -> bool {
163                self.0.eq(&other.0)
164            }
165        }
166
167        impl ::std::cmp::Eq for $type {}
168
169        impl ::std::hash::Hash for $type {
170            fn hash<HasherT>(&self, state: &mut HasherT)
171            where
172                HasherT: ::std::hash::Hasher,
173            {
174                self.0.hash(state)
175            }
176        }
177
178        impl<'own> ::std::iter::IntoIterator for &'own $type {
179            type Item = &'own str;
180            type IntoIter = ::kutil_std::foster::FosterIterator<
181                &'own str,
182                &'own ::std::string::String,
183                &'own &'static str,
184                ::std::slice::Iter<'own, ::std::string::String>,
185                ::std::slice::Iter<'own, &'static str>,
186            >;
187
188            fn into_iter(self) -> Self::IntoIter {
189                self.0.into_iter()
190            }
191        }
192    };
193}