Skip to content

Commit

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

This commit also bumps the crate version to 0.1.2

Signed-off-by: Ioana Chirca <[email protected]>
  • Loading branch information
ioanachirca committed Jun 26, 2020
1 parent af4d79f commit 003a83d
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 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/enums/unions.

# v0.1.1

- Removed "versionize" dependency.
Expand Down
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
14 changes: 13 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,18 @@ pub fn is_array(ty: &syn::Type) -> bool {
}
}

// Enforce that the latest VersionMap version is up-to-date with the latest
// struct/enum/union 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 003a83d

Please sign in to comment.