Skip to content

Commit 37a545d

Browse files
author
bors-servo
committed
Auto merge of #15 - chris-morgan:impl-fromiterator-for-tendril, r=SimonSapin
Add FromIterator and Extend implementations `FromIterator<T>` and `Extend<T>` are implemented for the following values of `T`: - `char` for `StrTendril`; - `u8` for `ByteTendril`; - `&u8` for `ByteTendril`, for reasons of ergonomics (see also rust-lang/rfcs#839 for justification); - `&str` for `StrTendril`; - `&[u8]` for `ByteTendril`; - `&Tendril<F>` for `Tendril<F>` (the `Extend` implementation already existed; the `FromIterator` is added). <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/tendril/15) <!-- Reviewable:end -->
2 parents faf97de + 0788b2b commit 37a545d

File tree

1 file changed

+169
-21
lines changed

1 file changed

+169
-21
lines changed

src/tendril.rs

Lines changed: 169 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::borrow::{Borrow, Cow};
99
use std::marker::PhantomData;
1010
use std::cell::Cell;
1111
use std::ops::{Deref, DerefMut};
12-
use std::iter::IntoIterator;
12+
use std::iter::FromIterator;
1313
use std::io::Write;
1414
use std::default::Default;
1515
use std::cmp::Ordering;
@@ -147,8 +147,118 @@ impl<F> Drop for Tendril<F>
147147
}
148148
}
149149

150-
// impl FromIterator<char> for Tendril<fmt::UTF8> { }
151-
// impl FromIterator<u8> for Tendril<fmt::Bytes> { }
150+
macro_rules! from_iter_method {
151+
($ty:ty) => {
152+
#[inline]
153+
fn from_iter<I>(iterable: I) -> Self
154+
where I: IntoIterator<Item = $ty>
155+
{
156+
let mut output = Self::new();
157+
output.extend(iterable);
158+
output
159+
}
160+
}
161+
}
162+
163+
impl Extend<char> for Tendril<fmt::UTF8> {
164+
#[inline]
165+
fn extend<I>(&mut self, iterable: I)
166+
where I: IntoIterator<Item = char>,
167+
{
168+
let iterator = iterable.into_iter();
169+
self.force_reserve(iterator.size_hint().0 as u32);
170+
for c in iterator {
171+
self.push_char(c);
172+
}
173+
}
174+
}
175+
176+
impl FromIterator<char> for Tendril<fmt::UTF8> {
177+
from_iter_method!(char);
178+
}
179+
180+
impl Extend<u8> for Tendril<fmt::Bytes> {
181+
#[inline]
182+
fn extend<I>(&mut self, iterable: I)
183+
where I: IntoIterator<Item = u8>,
184+
{
185+
let iterator = iterable.into_iter();
186+
self.force_reserve(iterator.size_hint().0 as u32);
187+
for b in iterator {
188+
self.push_slice(&[b]);
189+
}
190+
}
191+
}
192+
193+
impl FromIterator<u8> for Tendril<fmt::Bytes> {
194+
from_iter_method!(u8);
195+
}
196+
197+
impl<'a> Extend<&'a u8> for Tendril<fmt::Bytes> {
198+
#[inline]
199+
fn extend<I>(&mut self, iterable: I)
200+
where I: IntoIterator<Item = &'a u8>,
201+
{
202+
let iterator = iterable.into_iter();
203+
self.force_reserve(iterator.size_hint().0 as u32);
204+
for &b in iterator {
205+
self.push_slice(&[b]);
206+
}
207+
}
208+
}
209+
210+
impl<'a> FromIterator<&'a u8> for Tendril<fmt::Bytes> {
211+
from_iter_method!(&'a u8);
212+
}
213+
214+
impl<'a> Extend<&'a str> for Tendril<fmt::UTF8> {
215+
#[inline]
216+
fn extend<I>(&mut self, iterable: I)
217+
where I: IntoIterator<Item = &'a str>,
218+
{
219+
for s in iterable {
220+
self.push_slice(s);
221+
}
222+
}
223+
}
224+
225+
impl<'a> FromIterator<&'a str> for Tendril<fmt::UTF8> {
226+
from_iter_method!(&'a str);
227+
}
228+
229+
impl<'a> Extend<&'a [u8]> for Tendril<fmt::Bytes> {
230+
#[inline]
231+
fn extend<I>(&mut self, iterable: I)
232+
where I: IntoIterator<Item = &'a [u8]>,
233+
{
234+
for s in iterable {
235+
self.push_slice(s);
236+
}
237+
}
238+
}
239+
240+
impl<'a> FromIterator<&'a [u8]> for Tendril<fmt::Bytes> {
241+
from_iter_method!(&'a [u8]);
242+
}
243+
244+
impl<'a, F> Extend<&'a Tendril<F>> for Tendril<F>
245+
where F: fmt::Format + 'a,
246+
{
247+
#[inline]
248+
fn extend<I>(&mut self, iterable: I)
249+
where I: IntoIterator<Item = &'a Tendril<F>>,
250+
{
251+
for t in iterable {
252+
self.push_tendril(t);
253+
}
254+
}
255+
}
256+
257+
impl<'a, F> FromIterator<&'a Tendril<F>> for Tendril<F>
258+
where F: fmt::Format + 'a,
259+
{
260+
from_iter_method!(&'a Tendril<F>);
261+
}
152262

153263
impl<F> Deref for Tendril<F>
154264
where F: fmt::SliceFormat,
@@ -175,20 +285,6 @@ impl<F> Borrow<[u8]> for Tendril<F>
175285
// and so a HashMap<StrTendril, _> would silently break if we indexed by str. Ick.
176286
// https://github.com/rust-lang/rust/issues/27108
177287

178-
impl<'a, F> Extend<&'a Tendril<F>> for Tendril<F>
179-
where F: fmt::Format + 'a,
180-
{
181-
#[inline]
182-
fn extend<I>(&mut self, iterable: I)
183-
where I: IntoIterator<Item = &'a Tendril<F>>,
184-
{
185-
let iterator = iterable.into_iter();
186-
for t in iterator {
187-
self.push_tendril(t);
188-
}
189-
}
190-
}
191-
192288
impl<F> PartialEq for Tendril<F>
193289
where F: fmt::Format,
194290
{
@@ -292,12 +388,16 @@ impl<F> Tendril<F>
292388
/// decline to allocate until the buffer is actually modified.
293389
#[inline]
294390
pub fn reserve(&mut self, additional: u32) {
295-
if self.is_shared() {
391+
if !self.is_shared() {
296392
// Don't grow a shared tendril because we'd have to copy
297393
// right away.
298-
return;
394+
self.force_reserve(additional);
299395
}
396+
}
300397

398+
/// Reserve space for additional bytes, even for shared buffers.
399+
#[inline]
400+
fn force_reserve(&mut self, additional: u32) {
301401
let new_len = self.len32().checked_add(additional).expect(OFLOW);
302402
if new_len > MAX_INLINE_LEN as u32 {
303403
unsafe {
@@ -1698,12 +1798,60 @@ mod test {
16981798
}
16991799

17001800
#[test]
1701-
fn extend() {
1801+
fn extend_and_from_iterator() {
1802+
// Testing Extend<T> and FromIterator<T> for the various Ts.
1803+
1804+
// Tendril<F>
17021805
let mut t = "Hello".to_tendril();
1703-
t.extend(None.into_iter());
1806+
t.extend(None::<&Tendril<_>>.into_iter());
17041807
assert_eq!("Hello", &*t);
17051808
t.extend(&[", ".to_tendril(), "world".to_tendril(), "!".to_tendril()]);
17061809
assert_eq!("Hello, world!", &*t);
1810+
assert_eq!("Hello, world!", &*["Hello".to_tendril(), ", ".to_tendril(),
1811+
"world".to_tendril(), "!".to_tendril()]
1812+
.iter().collect::<StrTendril>());
1813+
1814+
// &str
1815+
let mut t = "Hello".to_tendril();
1816+
t.extend(None::<&str>.into_iter());
1817+
assert_eq!("Hello", &*t);
1818+
t.extend([", ", "world", "!"].iter().map(|&s| s));
1819+
assert_eq!("Hello, world!", &*t);
1820+
assert_eq!("Hello, world!", &*["Hello", ", ", "world", "!"]
1821+
.iter().map(|&s| s).collect::<StrTendril>());
1822+
1823+
// &[u8]
1824+
let mut t = b"Hello".to_tendril();
1825+
t.extend(None::<&[u8]>.into_iter());
1826+
assert_eq!(b"Hello", &*t);
1827+
t.extend([b", " as &[u8], b"world" as &[u8], b"!" as &[u8]].iter().map(|&s| s));
1828+
assert_eq!(b"Hello, world!", &*t);
1829+
assert_eq!(b"Hello, world!", &*[b"Hello" as &[u8], b", " as &[u8],
1830+
b"world" as &[u8], b"!" as &[u8]]
1831+
.iter().map(|&s| s).collect::<ByteTendril>());
1832+
1833+
let string = "the quick brown fox jumps over the lazy dog";
1834+
let string_expected = string.to_tendril();
1835+
let bytes = string.as_bytes();
1836+
let bytes_expected = bytes.to_tendril();
1837+
1838+
// char
1839+
assert_eq!(string_expected, string.chars().collect());
1840+
let mut tendril = StrTendril::new();
1841+
tendril.extend(string.chars());
1842+
assert_eq!(string_expected, tendril);
1843+
1844+
// &u8
1845+
assert_eq!(bytes_expected, bytes.iter().collect());
1846+
let mut tendril = ByteTendril::new();
1847+
tendril.extend(bytes);
1848+
assert_eq!(bytes_expected, tendril);
1849+
1850+
// u8
1851+
assert_eq!(bytes_expected, bytes.iter().map(|&b| b).collect());
1852+
let mut tendril = ByteTendril::new();
1853+
tendril.extend(bytes.iter().map(|&b| b));
1854+
assert_eq!(bytes_expected, tendril);
17071855
}
17081856

17091857
#[test]

0 commit comments

Comments
 (0)