diff --git a/docs/migration_guide.md b/docs/migration_guide.md index 04c49c7..35a50b4 100644 --- a/docs/migration_guide.md +++ b/docs/migration_guide.md @@ -18,15 +18,16 @@ bincode_2::config::legacy().with_variable_int_encoding() If you want to be compatible with bincode 1, use the following table: -|Bincode 1|Bincode 2| -|---|---| -|version 1.0 - 1.2 with `bincode_1::DefaultOptions::new().serialize(T)`|`config::legacy()`| -|version 1.3+ with `bincode_1::DefaultOptions::new().serialize(T)`|`config::legacy().with_variable_int_encoding()`| -|No explicit `Options`, e.g. `bincode::serialize(T)`|`config::legacy()`| +| Bincode 1 | Bincode 2 | +| ---------------------------------------------------------------------- | ----------------------------------------------- | +| version 1.0 - 1.2 with `bincode_1::DefaultOptions::new().serialize(T)` | `config::legacy()` | +| version 1.3+ with `bincode_1::DefaultOptions::new().serialize(T)` | `config::legacy().with_variable_int_encoding()` | +| No explicit `Options`, e.g. `bincode::serialize(T)` | `config::legacy()` | If you do not care about compatibility with bincode 1, we recommend using `config::standard()` The following changes have been made: + - `.with_limit(n)` has been changed to `.with_limit::()`. - `.with_native_endian()` has been removed. Use `.with_big_endian()` or `with_little_endian()` instead. - `.with_varint_encoding()` has been renamed to `.with_variable_int_encoding()`. @@ -49,18 +50,17 @@ bincode = { version = "2.0.0-rc", features = ["serde"] } # bincode = { version = "2.0.0-rc", default-features = false, features = ["std", "serde"] } ``` - Then replace the following functions: (`Configuration` is `bincode::config::legacy()` by default) -|Bincode 1|Bincode 2| -|--|--| -|`bincode::deserialize(&[u8])`|`bincode::serde::decode_from_slice(&[u8], Configuration)`
`bincode::serde::decode_borrowed_from_slice(&[u8], Configuration)`| -|`bincode::deserialize_from(std::io::Read)`|`bincode::serde::decode_from_std_read(std::io::Read, Configuration)`| -|`bincode::deserialize_from_custom(BincodeRead)`|`bincode::serde::decode_from_reader(Reader, Configuration)`| -||| -|`bincode::serialize(T)`|`bincode::serde::encode_to_vec(T, Configuration)`
`bincode::serde::encode_into_slice(T, &mut [u8], Configuration)`| -|`bincode::serialize_into(std::io::Write, T)`|`bincode::serde::encode_into_std_write(T, std::io::Write, Configuration)`| -|`bincode::serialized_size(T)`|Currently not implemented| +| Bincode 1 | Bincode 2 | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `bincode::deserialize(&[u8])` | `bincode::serde::decode_from_slice(&[u8], Configuration)`
`bincode::serde::borrow_decode_from_slice(&[u8], Configuration)` | +| `bincode::deserialize_from(std::io::Read)` | `bincode::serde::decode_from_std_read(std::io::Read, Configuration)` | +| `bincode::deserialize_from_custom(BincodeRead)` | `bincode::serde::decode_from_reader(Reader, Configuration)` | +| | | +| `bincode::serialize(T)` | `bincode::serde::encode_to_vec(T, Configuration)`
`bincode::serde::encode_into_slice(T, &mut [u8], Configuration)` | +| `bincode::serialize_into(std::io::Write, T)` | `bincode::serde::encode_into_std_write(T, std::io::Write, Configuration)` | +| `bincode::serialized_size(T)` | Currently not implemented | ## Migrating to `bincode-derive` @@ -79,10 +79,10 @@ bincode = "2.0.0-rc" Replace or add the following attributes. You are able to use both `serde-derive` and `bincode-derive` side-by-side. -|serde-derive|bincode-derive| -|---|---| -|`#[derive(serde::Serialize)]`|`#[derive(bincode::Encode)]`| -|`#[derive(serde::Deserialize)]`|`#[derive(bincode::Decode)]`| +| serde-derive | bincode-derive | +| ------------------------------- | ---------------------------- | +| `#[derive(serde::Serialize)]` | `#[derive(bincode::Encode)]` | +| `#[derive(serde::Deserialize)]` | `#[derive(bincode::Decode)]` | **note:** To implement these traits manually, see the documentation of [Encode](https://docs.rs/bincode/2.0.0-rc/bincode/enc/trait.Encode.html) and [Decode](https://docs.rs/bincode/2.0.0-rc/bincode/de/trait.Decode.html). @@ -90,20 +90,20 @@ Replace or add the following attributes. You are able to use both `serde-derive` Then replace the following functions: (`Configuration` is `bincode::config::legacy()` by default) -|Bincode 1|Bincode 2| -|--|--| -|`bincode::deserialize(&[u8])`|`bincode::decode_from_slice(&bytes, Configuration)`
`bincode::decode_borrowed_from_slice(&[u8], Configuration)`| -|`bincode::deserialize_from(std::io::Read)`|`bincode::decode_from_std_read(std::io::Read, Configuration)`| -|`bincode::deserialize_from_custom(BincodeRead)`|`bincode::decode_from_reader(Reader, Configuration)`| -||| -|`bincode::serialize(T)`|`bincode::encode_to_vec(T, Configuration)`
`bincode::encode_into_slice(t: T, &mut [u8], Configuration)`| -|`bincode::serialize_into(std::io::Write, T)`|`bincode::encode_into_std_write(T, std::io::Write, Configuration)`| -|`bincode::serialized_size(T)`|Currently not implemented| - +| Bincode 1 | Bincode 2 | +| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| `bincode::deserialize(&[u8])` | `bincode::decode_from_slice(&bytes, Configuration)`
`bincode::borrow_decode_from_slice(&[u8], Configuration)` | +| `bincode::deserialize_from(std::io::Read)` | `bincode::decode_from_std_read(std::io::Read, Configuration)` | +| `bincode::deserialize_from_custom(BincodeRead)` | `bincode::decode_from_reader(Reader, Configuration)` | +| | | +| `bincode::serialize(T)` | `bincode::encode_to_vec(T, Configuration)`
`bincode::encode_into_slice(t: T, &mut [u8], Configuration)` | +| `bincode::serialize_into(std::io::Write, T)` | `bincode::encode_into_std_write(T, std::io::Write, Configuration)` | +| `bincode::serialized_size(T)` | Currently not implemented | ### Bincode derive and libraries Currently not many libraries support the traits `Encode` and `Decode`. There are a couple of options if you want to use `#[derive(bincode::Encode, bincode::Decode)]`: + - Enable the `serde` feature and add a `#[bincode(with_serde)]` above each field that implements `serde::Serialize/Deserialize` but not `Encode/Decode` - Enable the `serde` feature and wrap your field in [bincode::serde::Compat](https://docs.rs/bincode/2.0.0-rc/bincode/serde/struct.Compat.html) or [bincode::serde::BorrowCompat](https://docs.rs/bincode/2.0.0-rc/bincode/serde/struct.BorrowCompat.html) - Make a pull request to the library: diff --git a/src/error.rs b/src/error.rs index 9ef363b..8c6ece4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,7 +7,7 @@ pub enum EncodeError { /// The writer ran out of storage. UnexpectedEnd, - /// The RefCell is already borrowed + /// The `RefCell` is already borrowed RefCellAlreadyBorrowed { /// The inner borrow error inner: core::cell::BorrowError, diff --git a/src/features/impl_alloc.rs b/src/features/impl_alloc.rs index 03cfc8c..f5186a7 100644 --- a/src/features/impl_alloc.rs +++ b/src/features/impl_alloc.rs @@ -258,8 +258,7 @@ where if unty::type_equal::() { decoder.claim_container_read::(len)?; // optimize for reading u8 vecs - let mut vec = Vec::new(); - vec.resize(len, 0u8); + let mut vec = alloc::vec![0u8; len]; decoder.reader().read(&mut vec)?; // Safety: Vec is Vec Ok(unsafe { core::mem::transmute(vec) }) @@ -288,8 +287,7 @@ where if unty::type_equal::() { decoder.claim_container_read::(len)?; // optimize for reading u8 vecs - let mut vec = Vec::new(); - vec.resize(len, 0u8); + let mut vec = alloc::vec![0u8; len]; decoder.reader().read(&mut vec)?; // Safety: Vec is Vec Ok(unsafe { core::mem::transmute(vec) }) diff --git a/src/features/serde/de_borrowed.rs b/src/features/serde/de_borrowed.rs index 45495f1..093a198 100644 --- a/src/features/serde/de_borrowed.rs +++ b/src/features/serde/de_borrowed.rs @@ -7,6 +7,29 @@ use crate::{ use core::marker::PhantomData; use serde::de::*; +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. +/// +/// See the [config](../config/index.html) module for more information on configurations. +pub fn borrow_decode_from_slice<'de, D, C>( + slice: &'de [u8], + config: C, +) -> Result<(D, usize), DecodeError> +where + D: Deserialize<'de>, + C: Config, +{ + let reader = crate::de::read::SliceReader::new(slice); + let mut decoder = crate::de::DecoderImpl::new(reader, config); + let serde_decoder = SerdeDecoder { + de: &mut decoder, + pd: PhantomData, + }; + let result = D::deserialize(serde_decoder)?; + let bytes_read = slice.len() - decoder.borrow_reader().slice.len(); + Ok((result, bytes_read)) +} + +#[deprecated(note = "Use borrow_decode_from_slice instead")] /// Decode a borrowed type from the given slice. Some parts of the decoded type are expected to be referring to the given slice pub fn decode_borrowed_from_slice<'de, T, C>(slice: &'de [u8], config: C) -> Result where diff --git a/src/features/serde/de_owned.rs b/src/features/serde/de_owned.rs index 8728771..502a92a 100644 --- a/src/features/serde/de_owned.rs +++ b/src/features/serde/de_owned.rs @@ -6,25 +6,32 @@ use crate::{ }; use serde::de::*; -/// Decode an owned type from the given slice. Will return the decoded type `T` as well as the amount of bytes that were read. +/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. /// -/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [decode_borrowed_from_slice]. +/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice]. /// -/// [decode_borrowed_from_slice]: fn.decode_borrowed_from_slice.html -pub fn decode_from_slice(slice: &[u8], config: C) -> Result<(T, usize), DecodeError> +/// See the [config] module for more information on configurations. +/// +/// [borrow_decode_from_slice]: fn.borrow_decode_from_slice.html +/// [config]: ../config/index.html +pub fn decode_from_slice(slice: &[u8], config: C) -> Result<(D, usize), DecodeError> where - T: DeserializeOwned, + D: DeserializeOwned, C: Config, { let reader = crate::de::read::SliceReader::new(slice); let mut decoder = crate::de::DecoderImpl::new(reader, config); let serde_decoder = SerdeDecoder { de: &mut decoder }; - let result = T::deserialize(serde_decoder)?; + let result = D::deserialize(serde_decoder)?; let bytes_read = slice.len() - decoder.reader().slice.len(); Ok((result, bytes_read)) } -/// Decode an owned type from the given `std::io::Read`. +/// Decode type `D` from the given reader with the given `Config`. The reader can be any type that implements `std::io::Read`, e.g. `std::fs::File`. +/// +/// See the [config] module for more information about config options. +/// +/// [config]: ../config/index.html #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn decode_from_std_read( @@ -41,7 +48,7 @@ pub fn decode_from_std_read( /// /// See the [config] module for more information on configurations. /// -/// [config]: config/index.html +/// [config]: ../config/index.html pub fn decode_from_reader( reader: R, config: C, diff --git a/src/features/serde/mod.rs b/src/features/serde/mod.rs index 6becfcf..5777c8f 100644 --- a/src/features/serde/mod.rs +++ b/src/features/serde/mod.rs @@ -1,7 +1,7 @@ //! Support for serde integration. Enable this with the `serde` feature. //! //! To encode/decode type that implement serde's trait, you can use: -//! - [decode_borrowed_from_slice] +//! - [borrow_decode_from_slice] //! - [decode_from_slice] //! - [encode_into_slice] //! - [encode_to_vec] diff --git a/src/features/serde/ser.rs b/src/features/serde/ser.rs index d368660..edb122d 100644 --- a/src/features/serde/ser.rs +++ b/src/features/serde/ser.rs @@ -8,30 +8,36 @@ use crate::{ use alloc::vec::Vec; use serde::ser::*; +/// Encode the given value into a `Vec` with the given `Config`. See the [config] module for more information. +/// +/// [config]: ../config/index.html #[cfg(feature = "alloc")] -/// Encode a `serde` `Serialize` type into a `Vec` with the bincode algorithm #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] -pub fn encode_to_vec(t: T, config: C) -> Result, EncodeError> +pub fn encode_to_vec(val: E, config: C) -> Result, EncodeError> where - T: Serialize, + E: Serialize, C: Config, { let mut encoder = crate::enc::EncoderImpl::new(crate::VecWriter::default(), config); let serializer = SerdeEncoder { enc: &mut encoder }; - t.serialize(serializer)?; + val.serialize(serializer)?; Ok(encoder.into_writer().collect()) } -/// Encode a `serde` `Serialize` type into a given byte slice with the bincode algorithm -pub fn encode_into_slice(t: T, slice: &mut [u8], config: C) -> Result +/// Encode the given value into the given slice. Returns the amount of bytes that have been written. +/// +/// See the [config] module for more information on configurations. +/// +/// [config]: ../config/index.html +pub fn encode_into_slice(val: E, dst: &mut [u8], config: C) -> Result where - T: Serialize, + E: Serialize, C: Config, { let mut encoder = - crate::enc::EncoderImpl::new(crate::enc::write::SliceWriter::new(slice), config); + crate::enc::EncoderImpl::new(crate::enc::write::SliceWriter::new(dst), config); let serializer = SerdeEncoder { enc: &mut encoder }; - t.serialize(serializer)?; + val.serialize(serializer)?; Ok(encoder.into_writer().bytes_written()) } @@ -39,7 +45,7 @@ where /// /// See the [config] module for more information on configurations. /// -/// [config]: config/index.html +/// [config]: ../config/index.html pub fn encode_into_writer( val: E, writer: W, @@ -54,7 +60,7 @@ pub fn encode_into_writer( /// Encode the given value into any type that implements `std::io::Write`, e.g. `std::fs::File`, with the given `Config`. /// See the [config] module for more information. /// -/// [config]: config/index.html +/// [config]: ../config/index.html #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg(feature = "std")] pub fn encode_into_std_write( diff --git a/src/lib.rs b/src/lib.rs index de3beea..3c225ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ //! |---|---|--- //! |You're working with [`fs::File`] or [`net::TcpStream`]|[`encode_into_std_write`]|[`decode_from_std_read`]| //! |you're working with in-memory buffers|[`encode_to_vec`]|[`decode_from_slice`]| -//! |You want to use a custom [Reader](de::read::Reader) and [writer](enc::write::Writer)|[`encode_into_writer`]|[`decode_from_reader`]| +//! |You want to use a custom [Reader] and [Writer]|[`encode_into_writer`]|[`decode_from_reader`]| //! |You're working with pre-allocated buffers or on embedded targets|[`encode_into_slice`]|[`decode_from_slice`]| //! //! **Note:** If you're using `serde`, use `bincode::serde::...` instead of `bincode::...` @@ -134,6 +134,8 @@ pub fn encode_into_writer( /// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read. /// +/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [borrow_decode_from_slice]. +/// /// See the [config] module for more information on configurations. /// /// [config]: config/index.html diff --git a/tests/serde.rs b/tests/serde.rs index 2adfcc4..db6744c 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -84,8 +84,8 @@ fn test_serialize_deserialize_borrowed_data() { assert_eq!(result, expected); - let output: SerdeWithBorrowedData = - bincode::serde::decode_borrowed_from_slice(&result, bincode::config::standard()).unwrap(); + let (output, len): (SerdeWithBorrowedData, usize) = + bincode::serde::borrow_decode_from_slice(&result, bincode::config::standard()).unwrap(); assert_eq!( SerdeWithBorrowedData { b: 0, // remember: b is skipped @@ -93,6 +93,7 @@ fn test_serialize_deserialize_borrowed_data() { }, output ); + assert_eq!(len, 13); } #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]