Skip to content

Commit 767d0b3

Browse files
committed
Ensure latest version from VersionMap contains...
...all structures at their current versions. This commit also bumps the crate verion to 0.1.2 Signed-off-by: Ioana Chirca <[email protected]>
1 parent f74d248 commit 767d0b3

File tree

6 files changed

+44
-15
lines changed

6 files changed

+44
-15
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# v0.1.2
2+
3+
- Added a safety check for enforcing that the VersionMaps provided for
4+
(de)serialization are up-to-date with the latest versions of the structs.
5+
6+
# v0.1.1
7+
8+
- Removed "versionize" dependency.
9+
110
# v0.1.0
211

312
- "versionize_derive" v0.1.0 first release.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "versionize_derive"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
license = "Apache-2.0"
55
authors = ["Amazon Firecracker team <[email protected]>"]
66
description = "Implements the Versionize derive proc macro."

src/descriptors/struct_desc.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use common::{Descriptor, GenericDescriptor};
55
use fields::struct_field::*;
6-
use helpers::compute_version;
6+
use helpers::{compute_version, latest_version_check};
77
use quote::{format_ident, quote};
88

99
pub(crate) type StructDescriptor = GenericDescriptor<StructField>;
@@ -71,13 +71,16 @@ impl Descriptor for StructDescriptor {
7171

7272
// Generate code to map the app version to struct version and wrap the
7373
// deserializers with the `version` match.
74-
quote! {
75-
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());
74+
let mut deserializer = proc_macro2::TokenStream::new();
75+
deserializer.extend(latest_version_check(self.version()));
76+
deserializer.extend(quote! {
7677
match version {
7778
#versioned_deserializers
7879
_ => panic!("Unknown {:?} version {}.", <Self as Versionize>::type_id(), version)
7980
}
80-
}
81+
});
82+
83+
deserializer
8184
}
8285

8386
fn version(&self) -> u16 {

src/descriptors/union_desc.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use common::{Descriptor, Exists, FieldType, GenericDescriptor};
55
use fields::union_field::*;
6-
use helpers::compute_version;
6+
use helpers::{compute_version, latest_version_check};
77
use quote::quote;
88

99
pub(crate) type UnionDescriptor = GenericDescriptor<UnionField>;
@@ -40,13 +40,16 @@ impl Descriptor for UnionDescriptor {
4040
});
4141
}
4242

43-
quote! {
44-
let version = version_map.get_type_version(app_version, Self::type_id());
43+
let mut deserializer = proc_macro2::TokenStream::new();
44+
deserializer.extend(latest_version_check(self.version()));
45+
deserializer.extend(quote! {
4546
match version {
4647
#versioned_deserializers
47-
_ => panic!("Unknown {:?} version {}.", Self::type_id(), version)
48+
_ => panic!("Unknown {:?} version {}.", <Self as Versionize>::type_id(), version)
4849
}
49-
}
50+
});
51+
52+
deserializer
5053
}
5154

5255
fn version(&self) -> u16 {

src/helpers.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use super::{ATTRIBUTE_NAME, END_VERSION, START_VERSION};
55
use common::Exists;
6-
use quote::format_ident;
6+
use quote::{format_ident, quote};
77
use std::cmp::max;
88
use std::collections::hash_map::HashMap;
99

@@ -79,6 +79,17 @@ pub fn is_array(ty: &syn::Type) -> bool {
7979
}
8080
}
8181

82+
// Enforce that the latest VersionMap version is up-to-date with the latest struct version.
83+
pub(crate) fn latest_version_check(current_version: u16) -> proc_macro2::TokenStream {
84+
quote! {
85+
// Get the struct version for the input app_version.
86+
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());
87+
if app_version == version_map.latest_version() && version != #current_version {
88+
return Err(VersionizeError::VersionMapNotUpdated);
89+
}
90+
}
91+
}
92+
8293
// Compute current struct version by finding the latest field change version.
8394
pub(crate) fn compute_version<T>(fields: &[T]) -> u16
8495
where

src/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use common::Descriptor;
1919
use descriptors::{
2020
enum_desc::EnumDescriptor, struct_desc::StructDescriptor, union_desc::UnionDescriptor,
2121
};
22+
use helpers::latest_version_check;
2223
use proc_macro::TokenStream;
2324
use quote::quote;
2425
use syn::{parse_macro_input, DeriveInput};
@@ -50,16 +51,18 @@ pub fn impl_versionize(input: TokenStream) -> proc_macro::TokenStream {
5051
let version = descriptor.version();
5152
let versioned_serializer = descriptor.generate_serializer();
5253
let deserializer = descriptor.generate_deserializer();
53-
let serializer = quote! {
54-
// Get the struct version for the input app_version.
55-
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());
54+
55+
let mut serializer = proc_macro2::TokenStream::new();
56+
serializer.extend(latest_version_check(version));
57+
serializer.extend(quote! {
5658
// We will use this copy to perform semantic serialization.
5759
let mut copy_of_self = self.clone();
5860
match version {
5961
#versioned_serializer
6062
_ => panic!("Unknown {:?} version {}.", &<Self as Versionize>::type_id(), version)
6163
}
62-
};
64+
});
65+
6366
(quote! {
6467
impl Versionize for #ident #generics {
6568
fn serialize<W: std::io::Write>(&self, writer: &mut W, version_map: &VersionMap, app_version: u16) -> VersionizeResult<()> {

0 commit comments

Comments
 (0)