Skip to content

Commit 874db7e

Browse files
committed
Update documentation.
Signed-off-by: Andrei Sandu <[email protected]>
1 parent 8539966 commit 874db7e

File tree

5 files changed

+250
-47
lines changed

5 files changed

+250
-47
lines changed

README.md

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,78 @@
1-
# versionize
1+
**Versionize is a framework for version tolerant serializion/deserialization of
2+
Rust data structures, designed for usecases that need fast deserialization
3+
times and minimal size overhead. It does not aim to be a generic serialization
4+
framework and only the [bincode](https://crates.io/crates/bincode) backend is
5+
supported.**
26

37
## Important note
48

5-
This crate is currently used for cross-version serialization with the [Firecracker snapshot-restore dev preview](https://github.com/firecracker-microvm/firecracker/tree/v0.23.0), but has not been tested for other use cases. It should be considered **experimental software** outside the Firecracker context. It’s likely that this crate will see both interface and implementation changes in the future.
9+
This crate is currently used for cross-version serialization with the
10+
[Firecracker snapshot-restore dev preview][1], but has not been tested for
11+
other use cases. It should be considered **experimental software** outside the
12+
Firecracker context. It’s likely that this crate will see both interface and
13+
implementation changes in the future.
614

7-
## Description
15+
## Versionize in action
816

9-
Provides version tolerant serialization and deserialization facilities and implements a persistent storage format for state snapshots.
17+
```rust
18+
extern crate versionize;
19+
extern crate versionize_derive;
20+
21+
use versionize::{VersionMap, Versionize, VersionizeResult};
22+
use versionize_derive::Versionize;
23+
24+
// The test structure is at version 3.
25+
#[derive(Debug, PartialEq, Versionize)]
26+
pub struct Test {
27+
a: u32,
28+
#[version(start = 2, end = 3)]
29+
b: u8,
30+
#[version(start = 3, default_fn = "default_c")]
31+
c: String,
32+
}
33+
34+
impl Test {
35+
// Default value for field `c`.
36+
// The callback is invoked when deserializing an older version
37+
// where the field did not exist.
38+
fn default_c(_source_version: u16) -> String {
39+
"test_string".to_owned()
40+
}
41+
}
42+
43+
// Memory to hold the serialization output.
44+
let mut mem = vec![0u8; 512];
45+
// Create a new version map - it will start at app version 1.
46+
let mut version_map = VersionMap::new();
47+
// Map structure versions to app version.
48+
version_map
49+
.new_version() // App version 2.
50+
.set_type_version(Test::type_id(), 2) // Struct(2) -> App(2).
51+
.new_version() // App version 3.
52+
.set_type_version(Test::type_id(), 3); // Struct(3) -> App(3).
53+
54+
let test_struct = Test {
55+
a: 1337,
56+
b: 0xFF,
57+
c: "c_value".to_owned(),
58+
};
59+
60+
// Serialize to app version 2 - field c will not be serialized.
61+
test_struct
62+
.serialize(&mut mem.as_mut_slice(), &version_map, 2)
63+
.unwrap();
64+
65+
// Deserialize from app version 2 - c should contain the default_fn() return value.
66+
let restored_test_struct = Test::deserialize(&mut mem.as_slice(), &version_map, 2).unwrap();
67+
68+
assert_eq!(
69+
restored_test_struct,
70+
Test {
71+
a: 1337,
72+
b: 255,
73+
c: "test_string".to_owned()
74+
}
75+
);
76+
```
77+
78+
[1]: https://github.com/firecracker-microvm/firecracker/tree/v0.24.0

src/crc.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
//! Implements readers and writers that compute a CRC64 checksum on the bytes
4+
//! Implements readers and writers that compute the CRC64 checksum of the bytes
55
//! read/written.
66
77
use crc64::crc64;
88
use std::io::{Read, Write};
99

10-
/// Computes CRC64 checksums from read bytes.
10+
/// Computes the CRC64 checksum of the read bytes.
11+
///
12+
/// ```
13+
/// use std::io::Read;
14+
/// use versionize::crc::CRC64Reader;
15+
///
16+
/// let buf = vec![1, 2, 3, 4, 5];
17+
/// let mut read_buf = Vec::new();
18+
/// let mut slice = buf.as_slice();
19+
///
20+
/// // Create a reader from a slice.
21+
/// let mut crc_reader = CRC64Reader::new(&mut slice);
22+
///
23+
/// let count = crc_reader.read_to_end(&mut read_buf).unwrap();
24+
/// assert_eq!(crc_reader.checksum(), 0xFB04_60DE_0638_3654);
25+
/// assert_eq!(read_buf, buf);
26+
/// ```
1127
pub struct CRC64Reader<T> {
1228
reader: T,
1329
crc64: u64,
@@ -38,7 +54,23 @@ where
3854
}
3955
}
4056

41-
/// Computes CRC64 checksums from written bytes.
57+
/// Computes the CRC64 checksum of the written bytes.
58+
///
59+
/// ```
60+
/// use std::io::Write;
61+
/// use versionize::crc::CRC64Writer;
62+
///
63+
/// let mut buf = vec![0; 16];
64+
/// let write_buf = vec![123; 16];
65+
/// let mut slice = buf.as_mut_slice();
66+
///
67+
/// // Create a new writer from slice.
68+
/// let mut crc_writer = CRC64Writer::new(&mut slice);
69+
///
70+
/// crc_writer.write_all(&write_buf.as_slice()).unwrap();
71+
/// assert_eq!(crc_writer.checksum(), 0x29D5_3572_1632_6566);
72+
/// assert_eq!(write_buf, buf);
73+
/// ```
4274
pub struct CRC64Writer<T> {
4375
writer: T,
4476
crc64: u64,

src/lib.rs

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,31 @@
22
// SPDX-License-Identifier: Apache-2.0
33
#![deny(missing_docs)]
44

5-
//! Provides version tolerant serialization and deserialization facilities and
6-
//! implements a persistent storage format for Firecracker state snapshots.
7-
//! The `Versionize` trait defines a generic interface that serializable state structures
8-
//! need to implement.
5+
//! Defines a generic interface for version tolerant serialization and
6+
//! implements it for primitive data types using `bincode` as backend.
97
//!
10-
//! `VersionMap` exposes an API that maps the individual structure versions to
11-
//! a root version. This mapping is required both when serializing or deserializing structures as
12-
//! it needs to know which version of structure to serialize for a given target data version.
8+
//! The interface has two components:
9+
//! - `Versionize` trait
10+
//! - `VersionMap` helper
1311
//!
14-
//! The Versionize proc macro supports structures and enums.
15-
//! Supported primitives: u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, char, f32, f64,
16-
//! String, Vec<T>, Arrays up to 32 elements, Box<T>, Wrapping<T>, Option<T>, FamStructWrapper<T>,
17-
//! and (T, U).
12+
//! `VersionMap` maps individual structure/enum versions to a root version
13+
//! (app version). This mapping is required both when serializing or
14+
//! deserializing structures as it needs to know which version of structure
15+
//! to serialize for a given target app version.
16+
//!
17+
//! `Versionize` trait is implemented for the following primitives:
18+
//! u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, char, f32, f64,
19+
//! String, Vec<T>, Arrays up to 32 elements, Box<T>, Wrapping<T>, Option<T>,
20+
//! FamStructWrapper<T>, and (T, U).
1821
//!
1922
//! Known issues and limitations:
2023
//! - Union serialization is not supported via the `Versionize` proc macro.
21-
//! - Implementing Versionize for non-repr(C) unions can result in undefined behaviour
22-
//! and MUST be avoided.
23-
//! - Versionize trait implementations for repr(C) unions must be backed by extensive testing.
24-
//! - Semantic serialization and deserialization is available only for structures.
24+
//! - Implementing `Versionize` for non-repr(C) unions can result in undefined
25+
//! behaviour and MUST be avoided.
26+
//! - Versionize trait implementations for repr(C) unions must be backed by
27+
//! extensive testing.
28+
//! - Semantic serialization and deserialization is available only for
29+
//! structures.
2530
//!
2631
extern crate bincode;
2732
extern crate crc64;
@@ -39,16 +44,16 @@ use std::io::{Read, Write};
3944
pub use version_map::VersionMap;
4045
use versionize_derive::Versionize;
4146

42-
/// Versioned serialization error definitions.
47+
/// Versioned serialization/deserialization error definitions.
4348
#[derive(Debug, PartialEq)]
4449
pub enum VersionizeError {
4550
/// An IO error occured.
4651
Io(i32),
47-
/// A serialization error.
52+
/// Generic serialization error.
4853
Serialize(String),
49-
/// A deserialization error.
54+
/// Generic deserialization error.
5055
Deserialize(String),
51-
/// A user generated semantic error.
56+
/// Semantic translation/validation error.
5257
Semantic(String),
5358
/// String length exceeded.
5459
StringLength(usize),
@@ -84,18 +89,62 @@ impl std::fmt::Display for VersionizeError {
8489
/// Versioned serialization/deserialization result.
8590
pub type VersionizeResult<T> = std::result::Result<T, VersionizeError>;
8691

87-
/// Trait that provides an interface for version aware serialization and deserialization.
92+
/// Trait that provides an interface for version aware serialization and
93+
/// deserialization.
94+
/// The [Versionize proc macro][1] can generate an implementation for a given
95+
/// type if generics are not used, otherwise a manual implementation is
96+
/// required.
97+
///
98+
/// Example implementation
99+
/// ```
100+
/// extern crate versionize;
101+
/// extern crate versionize_derive;
102+
/// use versionize::{VersionMap, Versionize, VersionizeResult};
103+
/// use versionize_derive::Versionize;
104+
///
105+
/// struct MyType<T>(T);
106+
///
107+
/// impl<T> Versionize for MyType<T>
108+
/// where
109+
/// T: Versionize,
110+
/// {
111+
/// #[inline]
112+
/// fn serialize<W: std::io::Write>(
113+
/// &self,
114+
/// writer: &mut W,
115+
/// version_map: &VersionMap,
116+
/// app_version: u16,
117+
/// ) -> VersionizeResult<()> {
118+
/// self.0.serialize(writer, version_map, app_version)
119+
/// }
120+
///
121+
/// #[inline]
122+
/// fn deserialize<R: std::io::Read>(
123+
/// reader: &mut R,
124+
/// version_map: &VersionMap,
125+
/// app_version: u16,
126+
/// ) -> VersionizeResult<Self> {
127+
/// Ok(MyType(T::deserialize(reader, version_map, app_version)?))
128+
/// }
129+
///
130+
/// fn version() -> u16 {
131+
/// 1
132+
/// }
133+
/// }
134+
/// ```
135+
/// [1]: https://docs.rs/versionize_derive/latest/versionize_derive/derive.Versionize.html
88136
pub trait Versionize {
89-
/// Serializes `self` to `target_verion` using the specficifed `writer` and `version_map`.
137+
/// Serializes `self` to `target_verion` using the specficifed `writer` and
138+
/// `version_map`.
90139
fn serialize<W: Write>(
91140
&self,
92141
writer: &mut W,
93142
version_map: &VersionMap,
94143
target_version: u16,
95144
) -> VersionizeResult<()>;
96145

97-
/// Returns a new instance of `Self` by deserialzing from `source_version` using the
98-
/// specficifed `reader` and `version_map`.
146+
/// Returns a new instance of `Self` by deserializing from `source_version`
147+
/// using the specficifed `reader` and `version_map`.
99148
fn deserialize<R: Read>(
100149
reader: &mut R,
101150
version_map: &VersionMap,
@@ -105,6 +154,8 @@ pub trait Versionize {
105154
Self: Sized;
106155

107156
/// Returns the `Self` type id.
157+
/// The returned ID represents a globally unique identifier for a type.
158+
/// It is required by the `VersionMap` implementation.
108159
fn type_id() -> std::any::TypeId
109160
where
110161
Self: 'static,

src/primitives.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@
66
use self::super::{VersionMap, Versionize, VersionizeError, VersionizeResult};
77
use vmm_sys_util::fam::{FamStruct, FamStructWrapper};
88

9-
/// Maximum string len in bytes (16KB).
9+
/// Maximum allowed string len in bytes (16KB).
10+
/// Calling `serialize()` or `deserialiaze()` will fail beyond this limit.
1011
pub const MAX_STRING_LEN: usize = 16384;
11-
/// Maximum vec size in bytes (10MB).
12+
/// Maximum allowed vec size in bytes (10MB).
13+
/// Calling `serialize()` or `deserialiaze()` will fail beyond this limit.
1214
pub const MAX_VEC_SIZE: usize = 10_485_760;
1315

14-
/// Implements the Versionize trait for primitive types that also implement
15-
/// serde's Serialize/Deserialize: use serde_bincode as a backend for
16-
/// serialization.
17-
///
18-
/// !TODO: Implement a backend abstraction layer so we can easily plug in different backends.
16+
/// A macro that implements the Versionize trait for primitive types using the
17+
/// serde bincode backed.
1918
macro_rules! impl_versionize {
2019
($ty:ident) => {
2120
impl Versionize for $ty {

0 commit comments

Comments
 (0)