Add docs to SSZ
This commit is contained in:
		
							parent
							
								
									16a8cdb714
								
							
						
					
					
						commit
						94ab2479fe
					
				| @ -2,6 +2,7 @@ use super::*; | ||||
| 
 | ||||
| pub mod impls; | ||||
| 
 | ||||
| /// Returned when SSZ decoding fails.
 | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum DecodeError { | ||||
|     /// The bytes supplied were too short to be decoded into the specified type.
 | ||||
| @ -21,7 +22,14 @@ pub enum DecodeError { | ||||
|     BytesInvalid(String), | ||||
| } | ||||
| 
 | ||||
| /// Provides SSZ decoding (de-serialization) via the `from_ssz_bytes(&bytes)` method.
 | ||||
| ///
 | ||||
| /// See `examples/` for manual implementations or the crate root for implementations using
 | ||||
| /// `#[derive(Decode)]`.
 | ||||
| pub trait Decodable: Sized { | ||||
|     /// Returns `true` if this object has a fixed-length.
 | ||||
|     ///
 | ||||
|     /// I.e., there are no variable length items in this object or any of it's contained objects.
 | ||||
|     fn is_ssz_fixed_len() -> bool; | ||||
| 
 | ||||
|     /// The number of bytes this object occupies in the fixed-length portion of the SSZ bytes.
 | ||||
| @ -33,6 +41,10 @@ pub trait Decodable: Sized { | ||||
|         BYTES_PER_LENGTH_OFFSET | ||||
|     } | ||||
| 
 | ||||
|     /// Attempts to decode `Self` from `bytes`, returning a `DecodeError` on failure.
 | ||||
|     ///
 | ||||
|     /// The supplied bytes must be the exact length required to decode `Self`, excess bytes will
 | ||||
|     /// result in an error.
 | ||||
|     fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError>; | ||||
| } | ||||
| 
 | ||||
| @ -42,6 +54,12 @@ pub struct Offset { | ||||
|     offset: usize, | ||||
| } | ||||
| 
 | ||||
| /// Builds an `SszDecoder`.
 | ||||
| ///
 | ||||
| /// The purpose of this struct is to split some SSZ bytes into individual slices. The builder is
 | ||||
| /// then converted into a `SszDecoder` which decodes those values into object instances.
 | ||||
| ///
 | ||||
| /// See [`SszDecoder`](struct.SszDecoder.html) for usage examples.
 | ||||
| pub struct SszDecoderBuilder<'a> { | ||||
|     bytes: &'a [u8], | ||||
|     items: Vec<&'a [u8]>, | ||||
| @ -50,6 +68,8 @@ pub struct SszDecoderBuilder<'a> { | ||||
| } | ||||
| 
 | ||||
| impl<'a> SszDecoderBuilder<'a> { | ||||
|     /// Instantiate a new builder that should build a `SszDecoder` over the given `bytes` which
 | ||||
|     /// are assumed to be the SSZ encoding of some object.
 | ||||
|     pub fn new(bytes: &'a [u8]) -> Self { | ||||
|         Self { | ||||
|             bytes, | ||||
| @ -59,6 +79,7 @@ impl<'a> SszDecoderBuilder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Declares that some type `T` is the next item in `bytes`.
 | ||||
|     pub fn register_type<T: Decodable>(&mut self) -> Result<(), DecodeError> { | ||||
|         if T::is_ssz_fixed_len() { | ||||
|             let start = self.items_index; | ||||
| @ -137,6 +158,7 @@ impl<'a> SszDecoderBuilder<'a> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Finalizes the builder, returning a `SszDecoder` that may be used to instantiate objects.
 | ||||
|     pub fn build(mut self) -> Result<SszDecoder<'a>, DecodeError> { | ||||
|         self.finalize()?; | ||||
| 
 | ||||
| @ -144,6 +166,45 @@ impl<'a> SszDecoderBuilder<'a> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Decodes some slices of SSZ into object instances. Should be instantiated using
 | ||||
| /// [`SszDecoderBuilder`](struct.SszDecoderBuilder.html).
 | ||||
| ///
 | ||||
| /// ## Example
 | ||||
| ///
 | ||||
| /// ```rust
 | ||||
| /// use ssz_derive::{Encode, Decode};
 | ||||
| /// use ssz::{Decodable, Encodable, SszDecoder, SszDecoderBuilder};
 | ||||
| ///
 | ||||
| /// #[derive(PartialEq, Debug, Encode, Decode)]
 | ||||
| /// struct Foo {
 | ||||
| ///     a: u64,
 | ||||
| ///     b: Vec<u16>,
 | ||||
| /// }
 | ||||
| ///
 | ||||
| /// fn main() {
 | ||||
| ///     let foo = Foo {
 | ||||
| ///         a: 42,
 | ||||
| ///         b: vec![1, 3, 3, 7]
 | ||||
| ///     };
 | ||||
| ///
 | ||||
| ///     let bytes = foo.as_ssz_bytes();
 | ||||
| ///
 | ||||
| ///     let mut builder = SszDecoderBuilder::new(&bytes);
 | ||||
| ///
 | ||||
| ///     builder.register_type::<u64>().unwrap();
 | ||||
| ///     builder.register_type::<Vec<u16>>().unwrap();
 | ||||
| ///
 | ||||
| ///     let mut decoder = builder.build().unwrap();
 | ||||
| ///
 | ||||
| ///     let decoded_foo = Foo {
 | ||||
| ///         a: decoder.decode_next().unwrap(),
 | ||||
| ///         b: decoder.decode_next().unwrap(),
 | ||||
| ///     };
 | ||||
| ///
 | ||||
| ///     assert_eq!(foo, decoded_foo);
 | ||||
| /// }
 | ||||
| ///
 | ||||
| /// ```
 | ||||
| pub struct SszDecoder<'a> { | ||||
|     items: Vec<&'a [u8]>, | ||||
| } | ||||
|  | ||||
| @ -2,9 +2,20 @@ use super::*; | ||||
| 
 | ||||
| mod impls; | ||||
| 
 | ||||
| /// Provides SSZ encoding (serialization) via the `as_ssz_bytes(&self)` method.
 | ||||
| ///
 | ||||
| /// See `examples/` for manual implementations or the crate root for implementations using
 | ||||
| /// `#[derive(Encode)]`.
 | ||||
| pub trait Encodable { | ||||
|     /// Returns `true` if this object has a fixed-length.
 | ||||
|     ///
 | ||||
|     /// I.e., there are no variable length items in this object or any of it's contained objects.
 | ||||
|     fn is_ssz_fixed_len() -> bool; | ||||
| 
 | ||||
|     /// Append the encoding `self` to `buf`.
 | ||||
|     ///
 | ||||
|     /// Note, variable length objects need only to append their "variable length" portion, they do
 | ||||
|     /// not need to provide their offset.
 | ||||
|     fn ssz_append(&self, buf: &mut Vec<u8>); | ||||
| 
 | ||||
|     /// The number of bytes this object occupies in the fixed-length portion of the SSZ bytes.
 | ||||
| @ -16,6 +27,9 @@ pub trait Encodable { | ||||
|         BYTES_PER_LENGTH_OFFSET | ||||
|     } | ||||
| 
 | ||||
|     /// Returns the full-form encoding of this object.
 | ||||
|     ///
 | ||||
|     /// The default implementation of this method should suffice for most cases.
 | ||||
|     fn as_ssz_bytes(&self) -> Vec<u8> { | ||||
|         let mut buf = vec![]; | ||||
| 
 | ||||
| @ -29,6 +43,41 @@ pub trait Encodable { | ||||
| ///
 | ||||
| /// **You must call `finalize(..)` after the final `append(..)` call** to ensure the bytes are
 | ||||
| /// written to `buf`.
 | ||||
| ///
 | ||||
| /// ## Example
 | ||||
| ///
 | ||||
| /// Use `SszEncoder` to produce identical output to `foo.as_ssz_bytes()`:
 | ||||
| ///
 | ||||
| /// ```rust
 | ||||
| /// use ssz_derive::{Encode, Decode};
 | ||||
| /// use ssz::{Decodable, Encodable, SszEncoder};
 | ||||
| ///
 | ||||
| /// #[derive(PartialEq, Debug, Encode, Decode)]
 | ||||
| /// struct Foo {
 | ||||
| ///     a: u64,
 | ||||
| ///     b: Vec<u16>,
 | ||||
| /// }
 | ||||
| ///
 | ||||
| /// fn main() {
 | ||||
| ///     let foo = Foo {
 | ||||
| ///         a: 42,
 | ||||
| ///         b: vec![1, 3, 3, 7]
 | ||||
| ///     };
 | ||||
| ///
 | ||||
| ///     let mut buf: Vec<u8> = vec![];
 | ||||
| ///     let offset = <u64 as Encodable>::ssz_fixed_len() + <Vec<u16> as Encodable>::ssz_fixed_len();
 | ||||
| ///
 | ||||
| ///     let mut encoder = SszEncoder::container(&mut buf, offset);
 | ||||
| ///
 | ||||
| ///     encoder.append(&foo.a);
 | ||||
| ///     encoder.append(&foo.b);
 | ||||
| ///
 | ||||
| ///     encoder.finalize();
 | ||||
| ///
 | ||||
| ///     assert_eq!(foo.as_ssz_bytes(), buf);
 | ||||
| /// }
 | ||||
| ///
 | ||||
| /// ```
 | ||||
| pub struct SszEncoder<'a> { | ||||
|     offset: usize, | ||||
|     buf: &'a mut Vec<u8>, | ||||
| @ -36,10 +85,14 @@ pub struct SszEncoder<'a> { | ||||
| } | ||||
| 
 | ||||
| impl<'a> SszEncoder<'a> { | ||||
|     /// Instantiate a new encoder for encoding a SSZ list.
 | ||||
|     ///
 | ||||
|     /// Identical to `Self::container`.
 | ||||
|     pub fn list(buf: &'a mut Vec<u8>, num_fixed_bytes: usize) -> Self { | ||||
|         Self::container(buf, num_fixed_bytes) | ||||
|     } | ||||
| 
 | ||||
|     /// Instantiate a new encoder for encoding a SSZ container.
 | ||||
|     pub fn container(buf: &'a mut Vec<u8>, num_fixed_bytes: usize) -> Self { | ||||
|         buf.reserve(num_fixed_bytes); | ||||
| 
 | ||||
| @ -50,6 +103,7 @@ impl<'a> SszEncoder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Append some `item` to the SSZ bytes.
 | ||||
|     pub fn append<T: Encodable>(&mut self, item: &T) { | ||||
|         if T::is_ssz_fixed_len() { | ||||
|             item.ssz_append(&mut self.buf); | ||||
| @ -61,6 +115,10 @@ impl<'a> SszEncoder<'a> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Write the variable bytes to `self.bytes`.
 | ||||
|     ///
 | ||||
|     /// This method must be called after the final `append(..)` call when serializing
 | ||||
|     /// variable-length items.
 | ||||
|     pub fn finalize(&mut self) -> &mut Vec<u8> { | ||||
|         self.buf.append(&mut self.variable_bytes); | ||||
| 
 | ||||
|  | ||||
| @ -1,13 +1,52 @@ | ||||
| //! Provides encoding (serialization) and decoding (deserialization) in the SimpleSerialize (SSZ)
 | ||||
| //! format designed for use in Ethereum 2.0.
 | ||||
| //!
 | ||||
| //! Conforms to
 | ||||
| //! [v0.6.1](https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/simple-serialize.md) of the
 | ||||
| //! Ethereum 2.0 specification.
 | ||||
| //!
 | ||||
| //! ## Example
 | ||||
| //!
 | ||||
| //! ```rust
 | ||||
| //! use ssz_derive::{Encode, Decode};
 | ||||
| //! use ssz::{Decodable, Encodable};
 | ||||
| //!
 | ||||
| //! #[derive(PartialEq, Debug, Encode, Decode)]
 | ||||
| //! struct Foo {
 | ||||
| //!     a: u64,
 | ||||
| //!     b: Vec<u16>,
 | ||||
| //! }
 | ||||
| //!
 | ||||
| //! fn main() {
 | ||||
| //!     let foo = Foo {
 | ||||
| //!         a: 42,
 | ||||
| //!         b: vec![1, 3, 3, 7]
 | ||||
| //!     };
 | ||||
| //!
 | ||||
| //!     let ssz_bytes: Vec<u8> = foo.as_ssz_bytes();
 | ||||
| //!
 | ||||
| //!     let decoded_foo = Foo::from_ssz_bytes(&ssz_bytes).unwrap();
 | ||||
| //!
 | ||||
| //!     assert_eq!(foo, decoded_foo);
 | ||||
| //! }
 | ||||
| //!
 | ||||
| //! ```
 | ||||
| //!
 | ||||
| //! See `examples/` for manual implementations of the `Encodable` and `Decodable` traits.
 | ||||
| 
 | ||||
| mod decode; | ||||
| mod encode; | ||||
| mod macros; | ||||
| 
 | ||||
| pub use decode::{ | ||||
|     impls::decode_list_of_variable_length_items, Decodable, DecodeError, SszDecoderBuilder, | ||||
|     impls::decode_list_of_variable_length_items, Decodable, DecodeError, SszDecoder, | ||||
|     SszDecoderBuilder, | ||||
| }; | ||||
| pub use encode::{Encodable, SszEncoder}; | ||||
| 
 | ||||
| /// The number of bytes used to represent an offset.
 | ||||
| pub const BYTES_PER_LENGTH_OFFSET: usize = 4; | ||||
| /// The maximum value that can be represented using `BYTES_PER_LENGTH_OFFSET`.
 | ||||
| pub const MAX_LENGTH_VALUE: usize = (1 << (BYTES_PER_LENGTH_OFFSET * 8)) - 1; | ||||
| 
 | ||||
| /// Convenience function to SSZ encode an object supporting ssz::Encode.
 | ||||
|  | ||||
| @ -1,3 +1,8 @@ | ||||
| /// Implements `Encodable` for `$impl_type` using an implementation of `From<$impl_type> for
 | ||||
| /// $from_type`.
 | ||||
| ///
 | ||||
| /// In effect, this allows for easy implementation of `Encodable` for some type that implements a
 | ||||
| /// `From` conversion into another type that already has `Encodable` implemented.
 | ||||
| #[macro_export] | ||||
| macro_rules! impl_encode_via_from { | ||||
|     ($impl_type: ty, $from_type: ty) => { | ||||
| @ -19,6 +24,11 @@ macro_rules! impl_encode_via_from { | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| /// Implements `Decodable` for `$impl_type` using an implementation of `From<$impl_type> for
 | ||||
| /// $from_type`.
 | ||||
| ///
 | ||||
| /// In effect, this allows for easy implementation of `Decodable` for some type that implements a
 | ||||
| /// `From` conversion into another type that already has `Decodable` implemented.
 | ||||
| #[macro_export] | ||||
| macro_rules! impl_decode_via_from { | ||||
|     ($impl_type: ty, $from_type: tt) => { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user