Skip to content

Commit efe6ea4

Browse files
committed
Add iter and iter_mut to LanguageRange
1 parent e361b11 commit efe6ea4

File tree

2 files changed

+125
-6
lines changed

2 files changed

+125
-6
lines changed

src/language/mod.rs

+121-2
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,35 @@ use crate::headers::HeaderValue;
88
use std::{
99
borrow::Cow,
1010
fmt::{self, Display},
11+
slice,
1112
str::FromStr,
1213
};
1314

1415
/// An RFC 4647 language range.
1516
#[derive(Debug, Clone, PartialEq)]
1617
pub struct LanguageRange {
17-
pub(crate) tags: Vec<Cow<'static, str>>,
18+
pub(crate) subtags: Vec<Cow<'static, str>>,
19+
}
20+
21+
impl LanguageRange {
22+
/// An iterator visiting all entries.
23+
pub fn iter(&self) -> Iter<'_> {
24+
Iter {
25+
inner: self.subtags.iter(),
26+
}
27+
}
28+
29+
/// An iterator visiting all entries.
30+
pub fn iter_mut(&mut self) -> IterMut<'_> {
31+
IterMut {
32+
inner: self.subtags.iter_mut(),
33+
}
34+
}
1835
}
1936

2037
impl Display for LanguageRange {
2138
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22-
let mut tags = self.tags.iter();
39+
let mut tags = self.subtags.iter();
2340
if let Some(tag) = tags.next() {
2441
write!(f, "{}", tag)?;
2542

@@ -31,6 +48,95 @@ impl Display for LanguageRange {
3148
}
3249
}
3350

51+
/// A borrowing iterator over entries in `LanguageRange`.
52+
#[derive(Debug)]
53+
pub struct IntoIter {
54+
inner: std::vec::IntoIter<Cow<'static, str>>,
55+
}
56+
57+
impl Iterator for IntoIter {
58+
type Item = Cow<'static, str>;
59+
60+
fn next(&mut self) -> Option<Self::Item> {
61+
self.inner.next()
62+
}
63+
64+
#[inline]
65+
fn size_hint(&self) -> (usize, Option<usize>) {
66+
self.inner.size_hint()
67+
}
68+
}
69+
70+
/// A lending iterator over entries in `LanguageRange`.
71+
#[derive(Debug)]
72+
pub struct Iter<'a> {
73+
inner: slice::Iter<'a, Cow<'static, str>>,
74+
}
75+
76+
impl<'a> Iterator for Iter<'a> {
77+
type Item = &'a Cow<'static, str>;
78+
79+
fn next(&mut self) -> Option<Self::Item> {
80+
self.inner.next()
81+
}
82+
83+
#[inline]
84+
fn size_hint(&self) -> (usize, Option<usize>) {
85+
self.inner.size_hint()
86+
}
87+
}
88+
89+
/// A mutable iterator over entries in `LanguageRange`.
90+
#[derive(Debug)]
91+
pub struct IterMut<'a> {
92+
inner: slice::IterMut<'a, Cow<'static, str>>,
93+
}
94+
95+
impl<'a> Iterator for IterMut<'a> {
96+
type Item = &'a mut Cow<'static, str>;
97+
98+
fn next(&mut self) -> Option<Self::Item> {
99+
self.inner.next()
100+
}
101+
102+
#[inline]
103+
fn size_hint(&self) -> (usize, Option<usize>) {
104+
self.inner.size_hint()
105+
}
106+
}
107+
108+
impl IntoIterator for LanguageRange {
109+
type Item = Cow<'static, str>;
110+
type IntoIter = IntoIter;
111+
112+
#[inline]
113+
fn into_iter(self) -> Self::IntoIter {
114+
IntoIter {
115+
inner: self.subtags.into_iter(),
116+
}
117+
}
118+
}
119+
120+
impl<'a> IntoIterator for &'a LanguageRange {
121+
type Item = &'a Cow<'static, str>;
122+
type IntoIter = Iter<'a>;
123+
124+
#[inline]
125+
fn into_iter(self) -> Self::IntoIter {
126+
self.iter()
127+
}
128+
}
129+
130+
impl<'a> IntoIterator for &'a mut LanguageRange {
131+
type Item = &'a mut Cow<'static, str>;
132+
type IntoIter = IterMut<'a>;
133+
134+
#[inline]
135+
fn into_iter(self) -> Self::IntoIter {
136+
self.iter_mut()
137+
}
138+
}
139+
34140
impl From<LanguageRange> for HeaderValue {
35141
fn from(language: LanguageRange) -> Self {
36142
let s = language.to_string();
@@ -51,3 +157,16 @@ impl<'a> From<&'a str> for LanguageRange {
51157
Self::from_str(value).unwrap()
52158
}
53159
}
160+
161+
#[cfg(test)]
162+
mod test {
163+
use super::*;
164+
165+
#[test]
166+
fn test_iter() -> crate::Result<()> {
167+
let range: LanguageRange = "en-CA".parse().unwrap();
168+
let subtags: Vec<_> = range.iter().collect();
169+
assert_eq!(&subtags, &["en", "CA"]);
170+
Ok(())
171+
}
172+
}

src/language/parse.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,20 @@ pub(crate) fn parse(input: &str) -> crate::Result<LanguageRange> {
4040
input = rest;
4141
}
4242

43-
Ok(LanguageRange { tags })
43+
Ok(LanguageRange { subtags: tags })
4444
}
4545

4646
#[test]
4747
fn test() {
4848
let range = parse("en").unwrap();
49-
assert_eq!(&range.tags, &["en"]);
49+
assert_eq!(&range.subtags, &["en"]);
5050

5151
let range = parse("en-CA").unwrap();
52-
assert_eq!(&range.tags, &["en", "CA"]);
52+
assert_eq!(&range.subtags, &["en", "CA"]);
5353

5454
let range = parse("zh-Hant-CN-x-private1-private2").unwrap();
5555
assert_eq!(
56-
&range.tags,
56+
&range.subtags,
5757
&["zh", "Hant", "CN", "x", "private1", "private2"]
5858
);
5959
}

0 commit comments

Comments
 (0)