-
Notifications
You must be signed in to change notification settings - Fork 31
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
add versionize support for more data structures #37
base: main
Are you sure you want to change the base?
add versionize support for more data structures #37
Conversation
b884fa8
to
1802fcb
Compare
Hi @sandreim @berciuliviu @jiangliu This is the continue work of #25 |
503521d
to
398dbd1
Compare
7064e6b
to
1275b64
Compare
Hi @roypat @luminitavoicu @aghecenco Could you please take a look at this PR :) |
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.
Hi,
Sorry for the late response, we've all been pretty busy with a release the last few weeks. This look good to me, and I think @andreeaflorescu's concern regarding VecDequeue/Vec compatibility is addressed by Vec and VecDequeue having the same serialized format (e.g. the serializer "forgets" about the ring buffer structure of VecDequeue and just lays out the queue sequentially - which I think is what should happen, anyway).
Just a few instances where you forgot to replace T
with $GenericParam
when converting the Vec impl into a macro, can you fix those and rebase?
ce133f5
to
8c514c6
Compare
Thanks, I fixed these problems. But I think the CI envirnoment may broken @roypat : |
oh my, thanks for letting me know, I'll have a look later today! |
fixed the CI, it seems that after rebasing some of your tests started failing (when you wrote this PR, the project was using rust 1.54, we've since updated to having the CI run in 1.64, and some Display impls in the standard library changed along the way) |
8c514c6
to
53a2069
Compare
Thank you, and I have fixed the error code in test cases, but the CI still failed due to timeout, how can I trigger CI's retry logic? @roypat |
Ugh, I think that might be related to rust-vmm/community#137 I increased the timeouts (I think? The tests all passed in under 5 minutes this time), so it seems the only thing left to address is the coverage. I had a look at the report and it seems the only thing uncovered are |
add versionize support for VecDeque/HashMap/HashSet. Signed-off-by: Zizheng Bian <[email protected]>
53a2069
to
29bfa55
Compare
Hi @andreeaflorescu @luminitavoicu @aghecenco Could you please look at this PR :) |
Hi @roypat , could you help me to find others who have permission to merge review this pr? |
fn serialize<W: std::io::Write>( | ||
&self, | ||
mut writer: &mut W, | ||
version_map: &VersionMap, | ||
app_version: u16, | ||
) -> VersionizeResult<()> { | ||
if self.len() > MAX_VEC_SIZE / std::mem::size_of::<$GenericParam>() { | ||
return Err(VersionizeError::VecLength(self.len())); | ||
} | ||
|
||
// Serialize in the same fashion as bincode: | ||
// Write len. | ||
bincode::serialize_into(&mut writer, &self.len()) | ||
.map_err(|ref err| VersionizeError::Serialize(format!("{:?}", err)))?; |
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.
Does writer
needs to be marked as mut
?
I see it is used for bincode::serialize_into(&mut writer, ...
, but shouldn't just writer
also work, because it is already a &mut W
?
bincode::serialize_into(&mut writer, &self.len()) | ||
.map_err(|ref err| VersionizeError::Serialize(format!("{:?}", err)))?; |
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.
bincode::serialize_into(&mut writer, &self.len()) | |
.map_err(|ref err| VersionizeError::Serialize(format!("{:?}", err)))?; | |
bincode::serialize_into(&mut writer, &self.len()) | |
.map_err(|err| VersionizeError::Serialize(format!("{err:?}")))?; |
let len: usize = bincode::deserialize_from(&mut reader) | ||
.map_err(|ref err| VersionizeError::Deserialize(format!("{:?}", err)))?; |
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.
let len: usize = bincode::deserialize_from(&mut reader) | |
.map_err(|ref err| VersionizeError::Deserialize(format!("{:?}", err)))?; | |
let len: usize = bincode::deserialize_from(&mut reader) | |
.map_err(|err| VersionizeError::Deserialize(format!("{err:?}")))?; |
let mut v = Vec::with_capacity(len); | ||
|
||
for _ in 0..len { | ||
let element: $GenericParam = | ||
$GenericParam::deserialize(reader, version_map, app_version).map_err( | ||
|ref err| VersionizeError::Deserialize(format!("{:?}", err)), | ||
)?; | ||
v.push(element); | ||
} | ||
Ok(v.into()) |
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.
let mut v = Vec::with_capacity(len); | |
for _ in 0..len { | |
let element: $GenericParam = | |
$GenericParam::deserialize(reader, version_map, app_version).map_err( | |
|ref err| VersionizeError::Deserialize(format!("{:?}", err)), | |
)?; | |
v.push(element); | |
} | |
Ok(v.into()) | |
let vec = (0..len).map(|_| | |
$GenericParam::deserialize(reader, version_map, app_version).map_err( | |
|err| VersionizeError::Deserialize(format!("{err:?}")), | |
) | |
).collect::<Result<Vec<_>,_>>()?; | |
vec.map($VecType::from) |
@@ -281,9 +288,75 @@ where | |||
} | |||
} | |||
|
|||
impl<T> Versionize for Vec<T> | |||
macro_rules! impl_versionize_vec_like_type { | |||
($VecType:ident <$GenericParam:ident>) => { |
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.
Given the invocations are with Vec<T>
and VecDeque<T>
we can remove the generic parameter from the macro just using T
within it.
($VecType:ident <$GenericParam:ident>) => { | |
($VecType:ident) => { |
and changing the invocations to:
impl_versionize_vec_like_type!(Vec);
impl_versionize_vec_like_type!(VecDeque);
impl<T: Default + FamStruct + Versionize> Versionize for FamStructWrapper<T> | ||
where | ||
T: Versionize, | ||
<T as FamStruct>::Entry: Versionize, | ||
T: std::fmt::Debug, |
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.
We should define traits on T
either entirely within impl<T: ...>
or within where T: ...,
.
impl<T: Default + FamStruct + Versionize> Versionize for FamStructWrapper<T> | |
where | |
T: Versionize, | |
<T as FamStruct>::Entry: Versionize, | |
T: std::fmt::Debug, | |
impl<T> Versionize for FamStructWrapper<T> | |
where | |
<T as FamStruct>::Entry: Versionize, | |
T: std::fmt::Debug + Default + FamStruct + Versionize, |
assert_eq!( | ||
format!("{}", err), | ||
"HashMap of length exceeded 20971536 > 20971520 bytes" | ||
); |
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.
assert_eq!( | |
format!("{}", err), | |
"HashMap of length exceeded 20971536 > 20971520 bytes" | |
); | |
assert_eq!( | |
err.to_string(), | |
"HashMap of length exceeded 20971536 > 20971520 bytes" | |
) |
let mut store = HashSet::new(); | ||
store.insert("test 1".to_owned()); | ||
store.insert("test 2".to_owned()); | ||
store.insert("test 3".to_owned()); |
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.
let mut store = HashSet::new(); | |
store.insert("test 1".to_owned()); | |
store.insert("test 2".to_owned()); | |
store.insert("test 3".to_owned()); | |
let store = HashSet::from([ | |
String::from("test 1"), | |
String::from("test 2"), | |
String::from("test 3") | |
]); |
let mut hash_set: HashSet<u32> = HashSet::new(); | ||
hash_set.insert(1); | ||
hash_set.insert(2); | ||
hash_set.insert(3); |
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.
let mut hash_set: HashSet<u32> = HashSet::new(); | |
hash_set.insert(1); | |
hash_set.insert(2); | |
hash_set.insert(3); | |
let hash_set = HashSet::from([1,2,3]); |
assert_eq!( | ||
format!("{}", err), | ||
"HashSet of length exceeded 10485768 > 10485760 bytes" | ||
); |
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.
assert_eq!( | |
format!("{}", err), | |
"HashSet of length exceeded 10485768 > 10485760 bytes" | |
); | |
assert_eq!( | |
err.to_string(), | |
"HashSet of length exceeded 10485768 > 10485760 bytes" | |
); |
let mut err = HashSet::with_capacity(MAX_HASH_SET_LEN / 8 + 1); | ||
for i in 0..(MAX_HASH_SET_LEN / 8 + 1) { | ||
err.insert(i); | ||
} |
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.
let mut err = HashSet::with_capacity(MAX_HASH_SET_LEN / 8 + 1); | |
for i in 0..(MAX_HASH_SET_LEN / 8 + 1) { | |
err.insert(i); | |
} | |
let err = (0..(MAX_HASH_SET_LEN / 8 + 1)).collect::<HashSet<_>>(); |
add versionize support for VecDeque/HashMap/HashSet.
Signed-off-by: Zizheng Bian [email protected]
Reason for This PR
Added support for some of the commonly used data structures: VecDeque, HashMap, and HashSet
Description of Changes
License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.
PR Checklist
[Author TODO: Meet these criteria.]
[Reviewer TODO: Verify that these criteria are met. Request changes if not]
git commit -s
).unsafe
code is properly documented.CHANGELOG.md
.