Skip to content

Commit

Permalink
Ensure latest version from VersionMap contains...
Browse files Browse the repository at this point in the history
...all structures at their current versions.

This commit also bumps the crate verion to 0.1.2

Signed-off-by: Ioana Chirca <[email protected]>
  • Loading branch information
ioanachirca committed Jun 25, 2020
1 parent f74d248 commit 767d0b3
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 15 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# v0.1.2

- Added a safety check for enforcing that the VersionMaps provided for
(de)serialization are up-to-date with the latest versions of the structs.

# v0.1.1

- Removed "versionize" dependency.

# v0.1.0

- "versionize_derive" v0.1.0 first release.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "versionize_derive"
version = "0.1.1"
version = "0.1.2"
license = "Apache-2.0"
authors = ["Amazon Firecracker team <[email protected]>"]
description = "Implements the Versionize derive proc macro."
Expand Down
11 changes: 7 additions & 4 deletions src/descriptors/struct_desc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use common::{Descriptor, GenericDescriptor};
use fields::struct_field::*;
use helpers::compute_version;
use helpers::{compute_version, latest_version_check};
use quote::{format_ident, quote};

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

// Generate code to map the app version to struct version and wrap the
// deserializers with the `version` match.
quote! {
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());
let mut deserializer = proc_macro2::TokenStream::new();
deserializer.extend(latest_version_check(self.version()));
deserializer.extend(quote! {
match version {
#versioned_deserializers
_ => panic!("Unknown {:?} version {}.", <Self as Versionize>::type_id(), version)
}
}
});

deserializer
}

fn version(&self) -> u16 {
Expand Down
13 changes: 8 additions & 5 deletions src/descriptors/union_desc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use common::{Descriptor, Exists, FieldType, GenericDescriptor};
use fields::union_field::*;
use helpers::compute_version;
use helpers::{compute_version, latest_version_check};
use quote::quote;

pub(crate) type UnionDescriptor = GenericDescriptor<UnionField>;
Expand Down Expand Up @@ -40,13 +40,16 @@ impl Descriptor for UnionDescriptor {
});
}

quote! {
let version = version_map.get_type_version(app_version, Self::type_id());
let mut deserializer = proc_macro2::TokenStream::new();
deserializer.extend(latest_version_check(self.version()));
deserializer.extend(quote! {
match version {
#versioned_deserializers
_ => panic!("Unknown {:?} version {}.", Self::type_id(), version)
_ => panic!("Unknown {:?} version {}.", <Self as Versionize>::type_id(), version)
}
}
});

deserializer
}

fn version(&self) -> u16 {
Expand Down
13 changes: 12 additions & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use super::{ATTRIBUTE_NAME, END_VERSION, START_VERSION};
use common::Exists;
use quote::format_ident;
use quote::{format_ident, quote};
use std::cmp::max;
use std::collections::hash_map::HashMap;

Expand Down Expand Up @@ -79,6 +79,17 @@ pub fn is_array(ty: &syn::Type) -> bool {
}
}

// Enforce that the latest VersionMap version is up-to-date with the latest struct version.
pub(crate) fn latest_version_check(current_version: u16) -> proc_macro2::TokenStream {
quote! {
// Get the struct version for the input app_version.
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());
if app_version == version_map.latest_version() && version != #current_version {
return Err(VersionizeError::VersionMapNotUpdated);
}
}
}

// Compute current struct version by finding the latest field change version.
pub(crate) fn compute_version<T>(fields: &[T]) -> u16
where
Expand Down
11 changes: 7 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use common::Descriptor;
use descriptors::{
enum_desc::EnumDescriptor, struct_desc::StructDescriptor, union_desc::UnionDescriptor,
};
use helpers::latest_version_check;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
Expand Down Expand Up @@ -50,16 +51,18 @@ pub fn impl_versionize(input: TokenStream) -> proc_macro::TokenStream {
let version = descriptor.version();
let versioned_serializer = descriptor.generate_serializer();
let deserializer = descriptor.generate_deserializer();
let serializer = quote! {
// Get the struct version for the input app_version.
let version = version_map.get_type_version(app_version, <Self as Versionize>::type_id());

let mut serializer = proc_macro2::TokenStream::new();
serializer.extend(latest_version_check(version));
serializer.extend(quote! {
// We will use this copy to perform semantic serialization.
let mut copy_of_self = self.clone();
match version {
#versioned_serializer
_ => panic!("Unknown {:?} version {}.", &<Self as Versionize>::type_id(), version)
}
};
});

(quote! {
impl Versionize for #ident #generics {
fn serialize<W: std::io::Write>(&self, writer: &mut W, version_map: &VersionMap, app_version: u16) -> VersionizeResult<()> {
Expand Down

0 comments on commit 767d0b3

Please sign in to comment.