I seem to be having issues, with Rust, and would certainly appreciate some help.
I've a custom struct
that implements the Iterator trait, and a separate struct
(also an Iterator) that I'd like to be able to wrap anything that presents itself as an iterable. Some of this seems achievable via generics, however, when getting specific within the wrapper struct
things seem to go sideways.
My main goal is to accept any iterable that returns Option<char>
, and preform some parsing/collection of characters.
Here's a toy example that demonstrates the core features I'm trying to implement...
src/main.rs
#!/usr/bin/env rust
struct IteratorHolder<I, T>
where
I: Iterator<Item = T>
{
iter: I,
}
impl<I, T> Iterator for IteratorHolder<I, T>
where
I: Iterator<Item = T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<I, T> IteratorHolder<I, T>
where
I: Iterator<Item = T>
{
#[allow(dead_code)]
fn new(iter: I) -> Self {
Self { iter }
}
}
impl<I, T> From<I> for IteratorHolder<I, T>
where
I: Iterator<Item = T>,
{
fn from(iter: I) -> Self {
Self { iter }
}
}
// ============================================================================
struct CustomIterator {
data: Option<(usize, String)>
}
impl CustomIterator {
#[allow(dead_code)]
fn new<S>(string: S) -> Self
where
S: Into<String>
{
let string: String = string.into();
let data = Some((0, string));
Self { data }
}
}
impl Iterator for CustomIterator {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
if let Some((index, string)) = self.data.take() {
let mut iter = string.get(index..).unwrap().char_indices();
if let Some((_, c)) = iter.next() {
self.data = iter.next().map(|(i, _)| (index + i, string));
return Some(c);
}
}
None
}
}
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn map() {
let v = vec![1, 2, 3];
let m = v.into_iter().map(|n| n * 2);
let mut i = IteratorHolder::new(m);
assert_eq!(i.next(), Some(2));
}
#[test]
fn chars() {
let s = String::from("abc");
let c = s.chars();
let mut i = IteratorHolder::new(c);
assert_eq!(i.next(), Some('a'));
}
#[test]
fn custom_iterator() {
let c = CustomIterator::new("zxc");
let mut i = IteratorHolder::new(c);
assert_eq!(i.next(), Some('z'));
}
#[test]
fn from_iter() {
let c = CustomIterator::new("zxc");
let mut i = IteratorHolder::from(c);
assert_eq!(i.next(), Some('z'));
}
}
Above all seems to function without errors
What I'm finding strange is when getting specific with From
implementations there be various type errors appearing.
For example where I to implement FromStr
on IteratorHolder
a E0053
error is generated...
method
from_str
has an incompatible type for trait expected fn pointerfn(&str) -> std::result::Result<IteratorHolder<I, T>, _>
found fn pointerfn(&str) -> std::result::Result<IteratorHolder<CustomIterator, char>, _>
[E0053]
src/main.rs
(snip)
use std::str::FromStr;
use std::num::ParseIntError;
impl<I, T> FromStr for IteratorHolder<I, T>
where
I: Iterator<Item = T>,
{
type Err = ParseIntError;
fn from_str(s: &str) -> Result<IteratorHolder<CustomIterator, char>, Self::Err> {
let iter = CustomIterator::new(s);
let hold = IteratorHolder { iter };
Ok(hold)
}
}
... And being more generic generates E0308
errors...
mismatched types expected type parameter
I
found structCustomIterator
[E0308]
impl<I, T> FromStr for IteratorHolder<I, T>
where
I: Iterator<Item = T>,
{
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let iter = CustomIterator::new(s);
let hold = Self { iter };
Ok(hold)
}
}
Essentially I'm face-planting on how to make IteratorHolder
more self sufficient, with regards to From
implementations. My main goal is to have a parser, similar to IteratorHolder
, that can read characters from iterators regardless of where those characters are sourced from; eg. file, stream, string. etc.
impl<I, T> FromStr for IteratorHolder<I, T> where I: Iterator<Item = T>
you're saying "for everyIteratorHolder
I will implementFromStr
." Yet, your implementation returns only anIteratorHolder
forCustomIterator
, which is clearly not what your type declaration said. – Aplet123