Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DONTMERGE] Use iterator for keys #57

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

gballet
Copy link
Owner

@gballet gballet commented Jan 24, 2020

This PR needs to be rebased, only applies iterators to Extension nodes and is only here for discussing the following points:

  • Index's index -> &[u8] makes it impossible to make bit keys and nibble keys as simple Vec<u8>: the data needs to be expanded in another Vec<u8> in which each byte represents one bit/nibble
  • the need for rewind
  • the general API and code of chop_common


if rewind {
self.rewind();
other.rewind();
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Schaeff because the calling code expects the next call to one iterator to return the first differing byte in the key, I find myself having to rewind the iterator by one byte. I have tried to use Peekable but it will also advance the iterator underneath. Any suggestion here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the comment at line 67 is incorrect as you're leaving them at their last common element?

From Peekable it seems that your implementation of the trait was incorrect as it's not supposed to advance the iterator, maybe an issue there?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is indeed too vague. The thing is: Peekable is an iterator, that doesn't advance on peek. But the iterator that it consumes does advance. It's not a problem with just this iterator, it's the problem for all of them:

fn main() {
    let v = vec![1, 2, 3];
    let mut pit = v.iter().peekable();
    println!("before peek {:?}", pit);
    pit.peek();
    println!("after peek {:?}", pit);
}

output:

before peek Peekable { iter: Iter([1, 2, 3]), peeked: None }
after peek Peekable { iter: Iter([2, 3]), peeked: Some(Some(1)) }

Copy link
Owner Author

@gballet gballet Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, using Peekable isn't great for another reason: since it's not defined in the same package as KeyIterator, I wouldn't be able to perform the trick that saves me a copy 😞

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay my bad it looks more complicated than that.

@@ -152,6 +135,7 @@ impl std::ops::Index<std::ops::RangeFrom<usize>> for NibbleKey {
impl std::ops::Index<std::ops::RangeTo<usize>> for NibbleKey {
type Output = [u8];

// Problem here
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Scaeff this is the second major problem: I would like to implement the iterator as just going over the key's bytes and extracting either the nibble or bit. But since I have to return &Self::Output, I find myself returning the whole byte instead of just the bit/nibble. Any idea?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't want [u8], what happens if you set Self::Output to something else?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to pass a reference to something, and that means I would have to create it on the fly, which isn't possible as it would go out of scope. I could somehow try to create a temporary element in a Vec and return a ref to it as a slice, however I'm not sure exactly how it would work and also I would not returning a reference to the underlying structure, so I would require some form of allocation. Not a show stopper, but not great either.

Copy link
Collaborator

@Schaeff Schaeff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe easier to go through this together 🤷‍♂

fn is_empty(&self) -> bool;

/// Returns an iterator over the key components (bit, byte, etc...)
fn iter(&self) -> KeyIterator<T, Self>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using IntoIterator as a supertrait (just heard the term to be honest..)

Copy link
Owner Author

@gballet gballet Jan 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it moves the values out of the container, but maybe I can fiddle so that it doesn't... 🤔

nibbles.push((address.0[nibble / 2] >> nibble_shift) & 0xF);
}
NibbleKey(nibbles)
impl<'a> From<KeyIterator<'a, u8, NibbleKey>> for NibbleKey {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using FromIterator here? Then we can use the more specific collect method when consuming the iterator, instead of the generic into

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that sounds like a good idea

@@ -152,6 +135,7 @@ impl std::ops::Index<std::ops::RangeFrom<usize>> for NibbleKey {
impl std::ops::Index<std::ops::RangeTo<usize>> for NibbleKey {
type Output = [u8];

// Problem here
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't want [u8], what happens if you set Self::Output to something else?


if rewind {
self.rewind();
other.rewind();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the comment at line 67 is incorrect as you're leaving them at their last common element?

From Peekable it seems that your implementation of the trait was incorrect as it's not supposed to advance the iterator, maybe an issue there?

@gballet
Copy link
Owner Author

gballet commented Jan 24, 2020

Maybe easier to go through this together man_shrugging

yup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants