-
Notifications
You must be signed in to change notification settings - Fork 14
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
Delegate branch-storage logic to the branch mod #373
Conversation
f5a3c51
to
2c794ea
Compare
d1650bd
to
fd6e3b1
Compare
2c794ea
to
751b7fa
Compare
fd6e3b1
to
49a0e8a
Compare
751b7fa
to
cc490cf
Compare
cc490cf
to
0dceb44
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review, will finish on the moved bits later
|
||
let offset = if raw_len == u32::MAX as u64 { | ||
let offset = if raw_len == u32::MAX { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😆
firewood/src/merkle/node/branch.rs
Outdated
enum BranchDataLength { | ||
None, | ||
Length(u32), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing; why is this not an Option<u32>
, or even better, Option<NonZeroU32>
?
If zero is a valid value, consider https://crates.io/crates/nonmax
This way you get niche optimization with None so the size is smaller and serialization is easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be less confusing if it was
enum BranchDataLength {
NoData,
/// `0` is a valid length, *empty* data and *no* data are treated separately
Length(u32),
}
Shepmaster
put this pretty nicely in a comment on SO:
I'll just have to do more profiling to see if it's truly worth it. Using less bytes seems like an obvious win; using less bytes and mandatory math everywhere is less sure-fire.
(emphasis mine)
In any case, I didn't end up using this code. I'll delete it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted 313cae7
@@ -179,3 +212,59 @@ impl BranchNode { | |||
.unwrap() | |||
} | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will have to review this later to verify it didn't change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You actually do not have to verify that it didn't change. What you have to verify is that we have tests that make sure that things that we serialize can also be deserialized since we have no burden of backward compatibility (yet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
firewood/src/shale/disk_address.rs
Outdated
@@ -30,6 +30,8 @@ impl DerefMut for DiskAddress { | |||
} | |||
|
|||
impl DiskAddress { | |||
pub const MSIZE: u64 = size_of::<Self>() as u64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why was the visibility increase needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used in (de)serialization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub(crate)
please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approved, almost all nits
} | ||
|
||
fn optional_data_len<Len, T: AsRef<[u8]>>(data: Option<T>) -> u64 { | ||
size_of::<Len>() as u64 + data.as_ref().map_or(0, |data| data.as_ref().len() as u64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unnecessary as_ref(), which is just changing Option to Option<&T>:
size_of::<Len>() as u64 + data.as_ref().map_or(0, |data| data.as_ref().len() as u64) | |
size_of::<Len>() as u64 + data.map_or(0, |data| data.as_ref().len() as u64) |
I wonder why clippy doesn't care about this.
} | ||
} | ||
|
||
fn optional_data_len<Len, T: AsRef<[u8]>>(data: Option<T>) -> u64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method needs a comment that describes what it does, and maybe better names, so if you mouse over it you can see what it does:
fn optional_data_len<Len, T: AsRef<[u8]>>(data: Option<T>) -> u64 { | |
/// Adds the size of some base object plus the length of some optional data | |
fn base_plus_optional_data_len<Base, T: AsRef<[u8]>>(data: Option<T>) -> u64 { |
I'm also not convinced this is any more readable than either (a) just inlining the size_of
part; or (b) doing both parts in the callers.
.value | ||
.as_ref() | ||
.map(|val| (val.len() as DataLen, val.deref())) | ||
.unwrap_or((DataLen::MAX, &[])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This needs a new const somewhere (with a comment) since this isn't actually MAX. Maybe DataLen::None
? Even better would be for this to be an Option<T>
where the value of None is DataLen::MAX.
let children_encoded_len = self.children_encoded.iter().fold(0, |len, child| { | ||
len + optional_data_len::<EncodedChildLen, _>(child.as_ref()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: readability:
let children_encoded_len = self.children_encoded.iter().fold(0, |len, child| { | |
len + optional_data_len::<EncodedChildLen, _>(child.as_ref()) | |
let children_encoded_len = self.children_encoded.iter().fold(0, |acc_len, child| { | |
acc_len + optional_data_len::<EncodedChildLen, _>(child.as_ref()) |
let (child_len, child) = child_encoded | ||
.as_ref() | ||
.map(|child| (child.len() as EncodedChildLen, child.as_slice())) | ||
.unwrap_or((EncodedChildLen::MIN, &[])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar comment. Using MAX and MIN is magics reduces readability
313cae7
to
9fa4827
Compare
9fa4827
to
4c9f31b
Compare
There is a code move here and well as some code changes. They are unfortunately in one commit. Breaking it up would mean re-implementing it and possibly introducing a bug.
I will be doing the same thing with both leaf and extension nodes.
Upon reviewing my own code, I see that this is actually just serialization. There's a
todo!()
that will come later for deserialization.