Hi,
I'm trying to port some existing code to parse obj files to Rust (mostly as a learning exercise!) I've got this working, but it currently represents the data being parsed as a &[u8]
slice and usize
'pointer' into that slice. However, this doesn't feel very idiomatic, and suspect I would be better using iterators somehow, but I'm really struggling to even get anything to compile, let alone work, so could just some pointers!
To take a concrete example, here's a small function that parses the sign in front of a number - it might be +, -, or not present at all. The function returns the sign (either +1 or -1) and consumes the symbol if it's there:
fn parse_sign(data: &[u8], ptr: usize) -> (isize, usize) {
match data[ptr] {
b'+' => (1, ptr + 1),
b'-' => (-1, ptr + 1),
_ => (1, ptr),
}
}
fn test_sign() {
let (val, ptr) = parse_sign(b"-1234", 0);
assert!(val == -1);
assert!(ptr == 1);
}
Works great. Here's my initial stab at converting it to something using an iterator.
fn iterate_sign<I>(iter: &mut std::iter::Peekable<I>) -> isize
where
I: std::iter::Iterator<Item = u8>,
{
match iter.peek() {
Some(b'+') => {
iter.next();
1
}
Some(b'-') => {
iter.next();
-1
}
_ => 1,
}
}
fn test_sign() {
let data: &[u8] = b"-1234 ";
let mut iter = data.iter().peekable();
let val = iterate_sign(&mut iter);
assert!(val == -1);
assert!(iter.peek() == Some(b'1'));
}
However, this doesn't even compile, complaining
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, u8> as std::iter::Iterator>::Item == u8`
I can't for the life of me figure out how to even create a function that takes an iterator...not sure if I'm not passing the right thing in, or if I should be defining the iterate_sign
function differently. Suspect I'm confusing u8
, &u8
(and possibly even &&u8
!) in the iterator somehow, but how I'm not sure.
More generally, iterators seem designed for nice self contained things like iterating over a loop, or calling other functions like map
on them. More explicit use like this seems very difficult. Am I barking up the wrong tree - the slice/offset approach works fine - is that actually the best way to do it?
Thanks!