#Flattening an Iterator of Cow<[u8]>.
15 messages · Page 1 of 1 (latest)
?eval ```rust
use std::borrow::Cow;
fn main() {
let cows: &[Cow<'static, [u8]>] = &[
Cow::Borrowed([0_u8].as_slice()),
Cow::Borrowed([1_u8, 2, 3].as_slice()),
Cow::Owned(vec![4_u8, 5, 6]),
];
for n in cows.iter().flat_map(AsRef::as_ref).copied() {
let n: u8 = n;
println!("{n}");
}
}
0
1
2
3
4
5
6```
@undone roost You basically do .flat_map(AsRef::as_ref).copied(). That turns the Cows into &[u8]s and flattens them into a bunch of &u8s followed by copying the value out of each &u8 to give you u8s.
The let n: u8 = n; is just there to prove that the loop's n has the type u8.
Thanks a lot!
BTW, this only works for an iterator of &Cow, not an iterator of Cow
Yeah I've got an iterator of Cow. Currently this is my solution and it's fast enough: rust self.tlvs.iter().map(TLV::to_bytes).collect::<Vec<Cow<[u8]>>>().concat()
You can make a custom iterator to do this, but usually you'd actually want to make a custom Read implementer.
What are you doing with the bytes?
They get chained to a header and then returned as a Cow<[u8]>.
Like Read::chain?
Well, I made a thing you can use as Read or Iterator.
#[derive(Debug, Clone)]
struct FlattenedCow<'a, I, T>
where
T: Clone,
{
current: Option<Cow<'a, [T]>>,
index: usize,
inner: I,
}
impl<I, T> FlattenedCow<'_, I, T>
where
T: Clone,
{
fn new<J: IntoIterator<IntoIter = I>>(iter: J) -> Self {
Self {
current: None,
index: 0,
inner: iter.into_iter(),
}
}
}
impl<'a, I> Read for FlattenedCow<'a, I, u8>
where
I: Iterator<Item = Cow<'a, [u8]>>,
{
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
loop {
if let Some(slice) = self.current.as_deref() {
let slice = &slice[self.index..];
if slice.is_empty() {
self.current = None;
continue;
}
use std::cmp::Ordering;
match buf.len().cmp(&slice.len()) {
Ordering::Less => {
buf.copy_from_slice(&slice[..buf.len()]);
self.index += buf.len();
break Ok(buf.len());
}
Ordering::Equal => {
buf.copy_from_slice(slice);
self.current = None;
break Ok(buf.len());
}
Ordering::Greater => {
let len = slice.len();
buf[..len].copy_from_slice(slice);
self.current = None;
break Ok(len);
}
}
} else {
self.current = self.inner.next();
if self.current.is_none() {
break Ok(0);
}
}
}
}
}
impl<'a, I, T> Iterator for FlattenedCow<'a, I, T>
where
I: Iterator<Item = Cow<'a, [T]>>,
T: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
loop {
let byte = self
.current
.as_ref()
.and_then(|cow| cow.get(self.index).cloned());
if let Some(byte) = byte {
self.index += 1;
break Some(byte);
} else {
self.current = self.inner.next();
if self.current.is_none() {
break None;
}
self.index = 0;
}
}
}
}