From 81034af00d32ab24d39cc7a7b4ee3d3f46729cd8 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Thu, 25 Jan 2018 22:37:24 +0100 Subject: [PATCH 01/13] clean up commented code --- src/lib.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fb4f36d..5148f28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,20 +42,8 @@ use std::io::Write; // for bytes.write_all; push_all is unstable and extend is s use std::io::Result as IOResult; use std::marker::PhantomData; -// pub mod size; pub mod abomonated; -// pub use size::AbomonationSize; - -// const EMPTY: *mut () = 0x1 as *mut (); - -// macro_rules! try_option { -// ($expr:expr) => (match $expr { -// Some(val) => val, -// None => { return None } -// }) -// } - /// Encodes a typed reference into a binary buffer. /// /// `encode` will transmute `typed` to binary and write its contents to `bytes`. It then offers the @@ -579,9 +567,4 @@ impl Abomonation for Box { // currently enables UB, by exposing padding bytes #[inline] unsafe fn typed_to_bytes(slice: &[T]) -> &[u8] { std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::()) -} - -// // takes a len to make working with zero-size types easier -// #[inline] unsafe fn bytes_to_typed(slice: &mut [u8], len: usize) -> &mut [T] { -// std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut T, len) -// } +} \ No newline at end of file From 8724e7e359faf8374c8c83d289e9b81f77b417af Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Mon, 28 May 2018 13:05:58 +0200 Subject: [PATCH 02/13] removed constraints, added comments --- src/abomonated.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/abomonated.rs b/src/abomonated.rs index 9d87e33..328b195 100644 --- a/src/abomonated.rs +++ b/src/abomonated.rs @@ -12,13 +12,17 @@ use super::{Abomonation, decode}; /// /// #Safety /// -/// The safety of this type, and in particular its `transute` implementation of -/// the `Deref` trait, relies on the owned bytes not being externally mutated +/// The safety of this type, and in particular its `transute` implementation of +/// the `Deref` trait, relies on the owned bytes not being externally mutated /// once provided. You could imagine a new type implementing `DerefMut` as required, /// but which also retains the ability (e.g. through `RefCell`) to mutate the bytes. -/// This would be very bad, but seems hard to prevent in the type system. Please +/// This would be very bad, but seems hard to prevent in the type system. Please /// don't do this. /// +/// You must also use a type `S` whose bytes have a fixed location in memory. +/// Otherwise moving an instance of `Abomonated` may invalidate decoded +/// pointers, and everything goes badly. +/// /// #Examples /// /// ``` @@ -45,7 +49,7 @@ use super::{Abomonation, decode}; /// panic!("failed to decode"); /// } /// ``` -pub struct Abomonated> { +pub struct Abomonated> { phantom: PhantomData, decoded: S, } @@ -83,6 +87,12 @@ impl> Abomonated { /// panic!("failed to decode"); /// } /// ``` + /// + /// #Safety + /// + /// The type `S` must have its bytes at a fixed location, which will + /// not change if the `bytes: S` instance is moved. Good examples are + /// `Vec` whereas bad examples are `[u8; 16]`. pub unsafe fn new(mut bytes: S) -> Option { // performs the underlying pointer correction, indicates success. @@ -100,7 +110,14 @@ impl> Abomonated { } } -impl> Deref for Abomonated { +impl> Abomonated { + pub fn as_bytes(&self) -> &[u8] { + &self.decoded + } +} + + +impl> Deref for Abomonated { type Target = T; #[inline] fn deref(&self) -> &T { From 63328fff6407b41ec609dcabbea23d91724bf723 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Wed, 5 Sep 2018 18:55:38 +0200 Subject: [PATCH 03/13] Duration added; comment tidied --- src/lib.rs | 102 ++++++++--------------------------------------------- 1 file changed, 14 insertions(+), 88 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5148f28..352fac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ //! the deserialization results in invalid typed data. Please do not do this. //! //! -//! #Examples +//! # Examples //! ``` //! use abomonation::{encode, decode}; //! @@ -51,7 +51,7 @@ pub mod abomonated; /// it offers the element the opportunity to "tidy up", in which the element can erasing things /// like local memory addresses that it would be impolite to share. /// -/// #Examples +/// # Examples /// ``` /// use abomonation::{encode, decode}; /// @@ -93,7 +93,7 @@ pub unsafe fn encode(typed: &T, write: &mut W) -> IORe /// and while it should only write to its `&mut [u8]` argument, invalid utf8 and enums are undefined /// behavior. Please do not decode data that was not encoded by the corresponding implementation. /// -/// #Examples +/// # Examples /// ``` /// use abomonation::{encode, decode}; /// @@ -159,18 +159,20 @@ pub trait Abomonation { #[inline(always)] unsafe fn exhume<'a,'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { Some(bytes) } /// Reports the number of further bytes required to entomb `self`. - #[inline(always)] fn extent(&self) -> usize { 0 } + #[inline(always)] fn extent(&self) -> usize { 0 } } /// The `unsafe_abomonate!` macro takes a type name with an optional list of fields, and implements /// `Abomonation` for the type, following the pattern of the tuple implementations: each method /// calls the equivalent method on each of its fields. /// -/// #Safety +/// It is strongly recommended that you use the `abomonation_derive` crate instead of this macro. +/// +/// # Safety /// `unsafe_abomonate` is unsafe because if you fail to specify a field it will not be properly /// re-initialized from binary data. This can leave you with a dangling pointer, or worse. /// -/// #Examples +/// # Examples /// ``` /// #[macro_use] /// extern crate abomonation; @@ -202,8 +204,9 @@ pub trait Abomonation { /// } /// ``` #[macro_export] +#[deprecated(since="0.5", note="please use the abomonation_derive crate")] macro_rules! unsafe_abomonate { - ($t:ty) => { + ($t:ty) => { impl Abomonation for $t { } }; ($t:ty : $($field:ident),*) => { @@ -272,6 +275,8 @@ impl Abomonation for () { } impl Abomonation for char { } +impl Abomonation for ::std::time::Duration { } + impl Abomonation for PhantomData {} impl Abomonation for Option { @@ -358,7 +363,7 @@ macro_rules! array_abomonate { } #[inline(always)] unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut[u8]) -> Option<&'b mut [u8]> { - for element in self { + for element in self { let tmp = bytes; bytes = element.exhume(tmp)?; } Some(bytes) @@ -428,40 +433,6 @@ impl Abomonation for String { } } -// TODO: Code deactivated because 'c unbound; would not be safe for e.g. 'static. -// -// impl<'c> Abomonation for &'c str { -// #[inline] -// unsafe fn embalm(&mut self) { -// *self = std::str::from_utf8_unchecked(std::slice::from_raw_parts(EMPTY as *mut u8, self.len())); -// } -// #[inline] -// unsafe fn entomb(&self, bytes: &mut Vec) { -// -// // TODO : At the moment, this does not compile to a memcpy, -// // due to Rust working around LLVM soundness bugs. -// -// // bytes.write_all(self.as_bytes()).unwrap(); -// -// // TODO : Instead, we use the following hunk of code: -// let position = bytes.len(); -// bytes.reserve(self.as_bytes().len()); -// ::std::ptr::copy_nonoverlapping(self.as_bytes().as_ptr(), bytes.as_mut_ptr().offset(position as isize), self.as_bytes().len()); -// bytes.set_len(position + self.as_bytes().len()); -// // TODO : End hunk of replacement code -// -// } -// #[inline] -// unsafe fn exhume<'a,'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { -// if self.len() > bytes.len() { None } -// else { -// let (mine, mut rest) = bytes.split_at_mut(self.len()); -// *self = std::str::from_utf8_unchecked(std::slice::from_raw_parts_mut(mine.as_mut_ptr() as *mut u8, self.len())); -// Some(rest) -// } -// } -// } - impl Abomonation for Vec { #[inline] unsafe fn entomb(&self, write: &mut W) -> IOResult<()> { @@ -486,7 +457,7 @@ impl Abomonation for Vec { Some(rest) } } - #[inline] + #[inline] fn extent(&self) -> usize { let mut sum = mem::size_of::() * self.len(); for element in self.iter() { @@ -496,51 +467,6 @@ impl Abomonation for Vec { } } -// TODO: Code deactivated because 'c unbound; would not be safe for e.g. 'static. -// -// impl<'c, T: Abomonation> Abomonation for &'c [T] { -// #[inline] -// unsafe fn embalm(&mut self) { -// std::ptr::write(self, std::slice::from_raw_parts(EMPTY as *mut T, self.len())); -// } -// #[inline] -// unsafe fn entomb(&self, bytes: &mut Vec) { -// let position = bytes.len(); -// -// // TODO : At the moment, this does not compile to a memcpy, -// // due to Rust working around LLVM soundness bugs. -// -// // bytes.write_all(typed_to_bytes(self)).unwrap(); -// -// // TODO : Instead, we use the following hunk of code: -// let typed_bytes = typed_to_bytes(&self[..]); -// bytes.reserve(typed_bytes.len()); -// ::std::ptr::copy_nonoverlapping(typed_bytes.as_ptr(), bytes.as_mut_ptr().offset(position as isize), typed_bytes.len()); -// bytes.set_len(position + typed_bytes.len()); -// // TODO : End hunk of replacement code -// -// for element in bytes_to_typed::(&mut bytes[position..], self.len()) { element.embalm(); } -// for element in self.iter() { element.entomb(bytes); } -// } -// #[inline] -// unsafe fn exhume<'a,'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { -// -// // extract memory from bytes to back our slice -// let binary_len = self.len() * mem::size_of::(); -// if binary_len > bytes.len() { None } -// else { -// let (mine, mut rest) = bytes.split_at_mut(binary_len); -// let slice = std::slice::from_raw_parts_mut(mine.as_mut_ptr() as *mut T, self.len()); -// for element in slice.iter_mut() { -// let temp = rest; -// rest = try_option!(element.exhume(temp)); -// } -// *self = slice; -// Some(rest) -// } -// } -// } - impl Abomonation for Box { #[inline] unsafe fn entomb(&self, bytes: &mut W) -> IOResult<()> { From 1db147118d882deee03196fb6dcd658de34c3bb7 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Wed, 5 Sep 2018 19:09:48 +0200 Subject: [PATCH 04/13] comments tidied further --- src/lib.rs | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 352fac8..61f7d86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,16 +3,14 @@ //! Abomonation takes typed elements and simply writes their contents as binary. //! It then gives the element the opportunity to serialize more data, which is //! useful for types with owned memory such as `String` and `Vec`. -//! The result is effectively a copy of reachable memory, where pointers are zero-ed out and vector -//! capacities are set to the vector length. +//! The result is effectively a copy of reachable memory. //! Deserialization results in a shared reference to the type, pointing at the binary data itself. //! //! Abomonation does several unsafe things, and should ideally be used only through the methods //! `encode` and `decode` on types implementing the `Abomonation` trait. Implementing the -//! `Abomonation` trait is highly discouraged, unless you use the `unsafe_abomonate!` macro, which -//! is only mostly discouraged. +//! `Abomonation` trait is highly discouraged; instead, you can use the [`abomonation_derive` crate](https://crates.io/crates/abomonation_derive). //! -//! **Very important**: Abomonation reproduces the memory as laid out by the serializer, which can +//! **Very important**: Abomonation reproduces the memory as laid out by the serializer, which will //! reveal architectural variations. Data encoded on a 32bit big-endian machine will not decode //! properly on a 64bit little-endian machine. Moreover, it could result in undefined behavior if //! the deserialization results in invalid typed data. Please do not do this. @@ -46,10 +44,11 @@ pub mod abomonated; /// Encodes a typed reference into a binary buffer. /// -/// `encode` will transmute `typed` to binary and write its contents to `bytes`. It then offers the -/// element the opportunity to serialize more data. Having done that, -/// it offers the element the opportunity to "tidy up", in which the element can erasing things -/// like local memory addresses that it would be impolite to share. +/// # Safety +/// +/// This method is unsafe because it is unsafe to transmute typed allocations to binary. +/// Furthermore, Rust currently indicates that it is undefined behavior to observe padding +/// bytes, which will happen when we `memmcpy` structs which contain padding bytes. /// /// # Examples /// ``` @@ -85,13 +84,21 @@ pub unsafe fn encode(typed: &T, write: &mut W) -> IORe /// The return value is either a pair of the typed reference `&T` and the remaining `&mut [u8]` /// binary data, or `None` if decoding failed due to lack of data. /// -/// #Safety +/// # Safety /// -/// `decode` is unsafe due to a number of unchecked invariants. Decoding arbitrary `&[u8]` data can -/// result in invalid utf8 strings, enums with invalid discriminants, etc. `decode` does presently +/// The `decode` method is unsafe due to a number of unchecked invariants. +/// +/// Decoding arbitrary `&[u8]` data can +/// result in invalid utf8 strings, enums with invalid discriminants, etc. `decode` *does* /// perform bounds checks, as part of determining if enough data are present to completely decode, -/// and while it should only write to its `&mut [u8]` argument, invalid utf8 and enums are undefined -/// behavior. Please do not decode data that was not encoded by the corresponding implementation. +/// and while it should only write within the bounds of its `&mut [u8]` argument, the use of invalid +/// utf8 and enums are undefined behavior. +/// +/// Please do not decode data that was not encoded by the corresponding implementation. +/// +/// In addition, `decode` does not ensure that the bytes representing types will be correctly aligned. +/// On several platforms unaligned reads are undefined behavior, but on several other platforms they +/// are only a performance penalty. /// /// # Examples /// ``` @@ -127,6 +134,10 @@ pub unsafe fn decode(bytes: &mut [u8]) -> Option<(&T, &mut [u8]) } /// Reports the number of bytes required to encode `self`. +/// +/// # Safety +/// +/// The `measure` method is safe. It neither produces nor consults serialized representations. #[inline] pub fn measure(typed: &T) -> usize { mem::size_of::() + typed.extent() @@ -137,7 +148,7 @@ pub fn measure(typed: &T) -> usize { /// The default implementations for Abomonation's methods are all empty. Many types have no owned /// data to transcribe. Some do, however, and need to carefully implement these unsafe methods. /// -/// #Safety +/// # Safety /// /// Abomonation has no safe methods. Please do not call them. They should be called only by /// `encode` and `decode`, each of which impose restrictions on ownership and lifetime of the data @@ -490,7 +501,7 @@ impl Abomonation for Box { } } -// currently enables UB, by exposing padding bytes +// This method currently enables undefined behavior, by exposing padding bytes. #[inline] unsafe fn typed_to_bytes(slice: &[T]) -> &[u8] { std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::()) } \ No newline at end of file From e3ec3bd9aafe9373d0537e16021a39997d7e9932 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Mon, 17 Sep 2018 11:21:39 +0200 Subject: [PATCH 05/13] version bump --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1f7bf1f..2f64bb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "abomonation" -version = "0.5.0" +version = "0.7.0" authors = ["Frank McSherry "] description = "A high performance and very unsafe serialization library" From c141762a96afd3c5765ce4216e6e1cf6a4c7a7c1 Mon Sep 17 00:00:00 2001 From: Moritz Hoffmann Date: Thu, 11 Apr 2019 22:32:56 +0200 Subject: [PATCH 06/13] Add support for ::std::net types like sockets and IP addresses Signed-off-by: Moritz Hoffmann --- src/lib.rs | 15 ++++++++++++++- tests/tests.rs | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 61f7d86..9d990b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -504,4 +504,17 @@ impl Abomonation for Box { // This method currently enables undefined behavior, by exposing padding bytes. #[inline] unsafe fn typed_to_bytes(slice: &[T]) -> &[u8] { std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::()) -} \ No newline at end of file +} + +mod network { + use Abomonation; + use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr}; + + impl Abomonation for IpAddr { } + impl Abomonation for Ipv4Addr { } + impl Abomonation for Ipv6Addr { } + + impl Abomonation for SocketAddr { } + impl Abomonation for SocketAddrV4 { } + impl Abomonation for SocketAddrV6 { } +} diff --git a/tests/tests.rs b/tests/tests.rs index b61835c..8ad07cb 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -132,4 +132,21 @@ fn test_multiple_encode_decode() { let (t, r) = unsafe { decode::(r) }.unwrap(); assert!(*t == 7); let (t, r) = unsafe { decode::>(r) }.unwrap(); assert!(*t == vec![1,2,3]); let (t, _r) = unsafe { decode::(r) }.unwrap(); assert!(*t == "grawwwwrr".to_owned()); -} \ No newline at end of file +} + +#[test] +fn test_net_types() { + + use std::net::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; + + let socket_addr4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(128, 0, 0, 1)), 1234); + let socket_addr6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 1234); + + let mut bytes = Vec::new(); + + unsafe { encode(&socket_addr4, &mut bytes).unwrap(); } + unsafe { encode(&socket_addr6, &mut bytes).unwrap(); } + + let (t, r) = unsafe { decode::(&mut bytes) }.unwrap(); assert!(*t == socket_addr4); + let (t, _r) = unsafe { decode::(r) }.unwrap(); assert!(*t == socket_addr6); +} From 39f484a54cf7b27ea75b879ed5833108527ac975 Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Fri, 24 May 2019 20:58:20 -0400 Subject: [PATCH 07/13] Implement Abomonation for the rest of the primitive data types --- src/lib.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 61f7d86..8090e82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ use std::mem; // yup, used pretty much everywhere. use std::io::Write; // for bytes.write_all; push_all is unstable and extend is slow. use std::io::Result as IOResult; use std::marker::PhantomData; +use std::num::*; pub mod abomonated; @@ -270,14 +271,30 @@ impl Abomonation for u8 { } impl Abomonation for u16 { } impl Abomonation for u32 { } impl Abomonation for u64 { } +impl Abomonation for u128 { } impl Abomonation for usize { } impl Abomonation for i8 { } impl Abomonation for i16 { } impl Abomonation for i32 { } impl Abomonation for i64 { } +impl Abomonation for i128 { } impl Abomonation for isize { } +impl Abomonation for NonZeroU8 { } +impl Abomonation for NonZeroU16 { } +impl Abomonation for NonZeroU32 { } +impl Abomonation for NonZeroU64 { } +impl Abomonation for NonZeroU128 { } +impl Abomonation for NonZeroUsize { } + +impl Abomonation for NonZeroI8 { } +impl Abomonation for NonZeroI16 { } +impl Abomonation for NonZeroI32 { } +impl Abomonation for NonZeroI64 { } +impl Abomonation for NonZeroI128 { } +impl Abomonation for NonZeroIsize { } + impl Abomonation for f32 { } impl Abomonation for f64 { } @@ -504,4 +521,4 @@ impl Abomonation for Box { // This method currently enables undefined behavior, by exposing padding bytes. #[inline] unsafe fn typed_to_bytes(slice: &[T]) -> &[u8] { std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::()) -} \ No newline at end of file +} From a25861418de8b241a84fd6174660597a1810d991 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Mon, 27 May 2019 15:10:24 -0400 Subject: [PATCH 08/13] update tests --- tests/tests.rs | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 8ad07cb..d7908b4 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -5,9 +5,8 @@ use abomonation::*; #[test] fn test_array() { _test_pass(vec![[0, 1, 2]; 1024]); } #[test] fn test_opt_vec() { _test_pass(vec![Some(vec![0,1,2]), None]); } -// #[test] fn test_result_vec_str() { _test_pass(vec![Ok(vec![0, 1, 2]), Err("grawwwwrr!"), Ok(vec![])]); } -// #[test] fn test_str_ref() { _test_pass(vec!["hi there"; 245]); } #[test] fn test_alignment() { _test_pass(vec![(format!("x"), vec![1,2,3]); 1024]); } +#[test] fn test_alignment_128() { _test_pass(vec![(format!("x"), vec![1u128,2,3]); 1024]); } #[test] fn test_option_box_u64() { _test_pass(vec![Some(Box::new(0u64))]); } #[test] fn test_option_vec() { _test_pass(vec![Some(vec![0, 1, 2])]); } #[test] fn test_u32x4_pass() { _test_pass(vec![((1,2,3),vec![(0u32, 0u32, 0u32, 0u32); 1024])]); } @@ -96,30 +95,6 @@ fn test_macro_size() { assert_eq!(bytes.len(), measure(&record)); } -// #[derive(Eq, PartialEq)] -// struct MyGenericStruct { -// item: T -// } - -// unsafe_abomonate!(T:Ord+Abomonation; MyStruct : item); - -// #[test] -// fn test_generic_macro() { -// // create some test data out of abomonation-approved types -// let record = MyGenericStruct{ item: "hello".to_owned() }; - -// // encode vector into a Vec -// let mut bytes = Vec::new(); -// unsafe { encode(&record, &mut bytes); } - -// // decode a &Vec<(u64, String)> from binary data -// if let Some((result, rest)) = unsafe { decode::(&mut bytes) } { -// assert!(result == &record); -// assert!(rest.len() == 0); -// } -// } - - #[test] fn test_multiple_encode_decode() { let mut bytes = Vec::new(); From fe437396503117213261f8ee75dd1834ffc74a11 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Mon, 27 May 2019 15:12:20 -0400 Subject: [PATCH 09/13] Update Cargo.toml --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2f64bb8..d0c52dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "abomonation" -version = "0.7.0" +version = "0.7.1" authors = ["Frank McSherry "] description = "A high performance and very unsafe serialization library" # These URLs point to more information about the repository -documentation = "https://frankmcsherry.github.com/abomonation" -homepage = "https://github.com/frankmcsherry/abomonation" -repository = "https://github.com/frankmcsherry/abomonation.git" +documentation = "https://docs.rs/abomonation/" +homepage = "https://github.com/TimelyDataflow/abomonation" +repository = "https://github.com/TimelyDataflow/abomonation.git" keywords = ["abomonation"] license = "MIT" From edc05b984886e59b3bc8bf305a7a51a16e5402e4 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Thu, 6 Jun 2019 16:16:31 -0400 Subject: [PATCH 10/13] use feature flag --- Cargo.toml | 2 +- src/lib.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0c52dd..2b5eb48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "abomonation" -version = "0.7.1" +version = "0.7.2" authors = ["Frank McSherry "] description = "A high performance and very unsafe serialization library" diff --git a/src/lib.rs b/src/lib.rs index 2e617dc..2419ed1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,12 +288,12 @@ impl Abomonation for NonZeroU64 { } impl Abomonation for NonZeroU128 { } impl Abomonation for NonZeroUsize { } -impl Abomonation for NonZeroI8 { } -impl Abomonation for NonZeroI16 { } -impl Abomonation for NonZeroI32 { } -impl Abomonation for NonZeroI64 { } -impl Abomonation for NonZeroI128 { } -impl Abomonation for NonZeroIsize { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI8 { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI16 { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI32 { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI64 { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI128 { } +#[cfg(feature = "nonzero")] impl Abomonation for NonZeroIsize { } impl Abomonation for f32 { } impl Abomonation for f64 { } From ca7a85e894143ec7bbe97202f93b3a6cc4dbf111 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Thu, 11 Jul 2019 08:59:53 -0400 Subject: [PATCH 11/13] reintroduce nonzero --- Cargo.toml | 2 +- src/lib.rs | 12 ++++++------ tests/tests.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b5eb48..7c2f62d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "abomonation" -version = "0.7.2" +version = "0.7.3" authors = ["Frank McSherry "] description = "A high performance and very unsafe serialization library" diff --git a/src/lib.rs b/src/lib.rs index 2419ed1..2e617dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,12 +288,12 @@ impl Abomonation for NonZeroU64 { } impl Abomonation for NonZeroU128 { } impl Abomonation for NonZeroUsize { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI8 { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI16 { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI32 { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI64 { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroI128 { } -#[cfg(feature = "nonzero")] impl Abomonation for NonZeroIsize { } +impl Abomonation for NonZeroI8 { } +impl Abomonation for NonZeroI16 { } +impl Abomonation for NonZeroI32 { } +impl Abomonation for NonZeroI64 { } +impl Abomonation for NonZeroI128 { } +impl Abomonation for NonZeroIsize { } impl Abomonation for f32 { } impl Abomonation for f64 { } diff --git a/tests/tests.rs b/tests/tests.rs index d7908b4..764fba8 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,9 +1,9 @@ -#[macro_use] extern crate abomonation; use abomonation::*; #[test] fn test_array() { _test_pass(vec![[0, 1, 2]; 1024]); } +#[test] fn test_nonzero() { _test_pass(vec![[std::num::NonZeroI32::new(1)]; 1024]); } #[test] fn test_opt_vec() { _test_pass(vec![Some(vec![0,1,2]), None]); } #[test] fn test_alignment() { _test_pass(vec![(format!("x"), vec![1,2,3]); 1024]); } #[test] fn test_alignment_128() { _test_pass(vec![(format!("x"), vec![1u128,2,3]); 1024]); } From 9294cd202f134b9d4b023c22f37f0e63baf9c857 Mon Sep 17 00:00:00 2001 From: Frank McSherry Date: Thu, 11 Jul 2019 09:05:35 -0400 Subject: [PATCH 12/13] add @antiguru tests --- tests/tests.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/tests.rs b/tests/tests.rs index 764fba8..340e776 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -11,10 +11,12 @@ use abomonation::*; #[test] fn test_option_vec() { _test_pass(vec![Some(vec![0, 1, 2])]); } #[test] fn test_u32x4_pass() { _test_pass(vec![((1,2,3),vec![(0u32, 0u32, 0u32, 0u32); 1024])]); } #[test] fn test_u64_pass() { _test_pass(vec![0u64; 1024]); } +#[test] fn test_u128_pass() { _test_pass(vec![0u128; 1024]); } #[test] fn test_string_pass() { _test_pass(vec![format!("grawwwwrr!"); 1024]); } #[test] fn test_vec_u_s_pass() { _test_pass(vec![vec![(0u64, format!("grawwwwrr!")); 32]; 32]); } #[test] fn test_u64_fail() { _test_fail(vec![0u64; 1024]); } +#[test] fn test_u128_fail() { _test_fail(vec![0u128; 1024]); } #[test] fn test_string_fail() { _test_fail(vec![format!("grawwwwrr!"); 1024]); } #[test] fn test_vec_u_s_fail() { _test_fail(vec![vec![(0u64, format!("grawwwwrr!")); 32]; 32]); } @@ -25,6 +27,7 @@ use abomonation::*; #[test] fn test_option_vec_size() { _test_size(vec![Some(vec![0, 1, 2])]); } #[test] fn test_u32x4_size() { _test_size(vec![((1,2,3),vec![(0u32, 0u32, 0u32, 0u32); 1024])]); } #[test] fn test_u64_size() { _test_size(vec![0u64; 1024]); } +#[test] fn test_u128_size() { _test_size(vec![0u128; 1024]); } #[test] fn test_string_size() { _test_size(vec![format!("grawwwwrr!"); 1024]); } #[test] fn test_vec_u_s_size() { _test_size(vec![vec![(0u64, format!("grawwwwrr!")); 32]; 32]); } From a75d45356383b107be68cdd61135f3f328488f55 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Sat, 15 Aug 2020 18:16:38 +0200 Subject: [PATCH 13/13] Make `Range` abomonable --- src/lib.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2e617dc..016bcc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -307,6 +307,22 @@ impl Abomonation for ::std::time::Duration { } impl Abomonation for PhantomData {} +impl Abomonation for std::ops::Range { + #[inline(always)] unsafe fn entomb(&self, write: &mut W) -> IOResult<()> { + self.start.entomb(write)?; + self.end.entomb(write)?; + Ok(()) + } + #[inline(always)] unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut[u8]) -> Option<&'b mut [u8]> { + let tmp = bytes; bytes = self.start.exhume(tmp)?; + let tmp = bytes; bytes = self.end.exhume(tmp)?; + Some(bytes) + } + #[inline] fn extent(&self) -> usize { + self.start.extent() << 1 + } +} + impl Abomonation for Option { #[inline(always)] unsafe fn entomb(&self, write: &mut W) -> IOResult<()> { if let &Some(ref inner) = self { @@ -534,4 +550,4 @@ mod network { impl Abomonation for SocketAddr { } impl Abomonation for SocketAddrV4 { } impl Abomonation for SocketAddrV6 { } -} \ No newline at end of file +}