├── .gitignore ├── clippy.toml ├── tests ├── ubuntu-20.04.4-live-server-amd64.iso.torrent └── de.rs ├── deny.toml ├── .github ├── dependabot.yml └── workflows │ ├── audit.yml │ └── ci.yml ├── LICENSE-MIT ├── Cargo.toml ├── src ├── write.rs ├── value │ ├── index.rs │ ├── de.rs │ └── ser.rs ├── lib.rs ├── bstring.rs ├── error.rs ├── read.rs ├── value.rs ├── de.rs └── ser.rs ├── README.md ├── CHANGELOG.md └── LICENSE-APACHE /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | doc-valid-idents = ["BtBencode", "BitTorrent", ".."] -------------------------------------------------------------------------------- /tests/ubuntu-20.04.4-live-server-amd64.iso.torrent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bluk/bt_bencode/HEAD/tests/ubuntu-20.04.4-live-server-amd64.iso.torrent -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [licenses] 2 | version = 2 3 | allow = [ 4 | "MIT", 5 | "Apache-2.0", 6 | ] 7 | 8 | [bans] 9 | multiple-versions = "warn" 10 | wildcards = "allow" -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: github-actions 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 10 -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Rust Security Audit 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | paths: 9 | - '**/Cargo.toml' 10 | - '**/Cargo.lock' 11 | pull_request: 12 | 13 | jobs: 14 | audit: 15 | strategy: 16 | matrix: 17 | os: 18 | - ubuntu-latest 19 | rust: 20 | - stable 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - name: Install toolchain 24 | uses: dtolnay/rust-toolchain@master 25 | with: 26 | toolchain: ${{ matrix.rust }} 27 | components: rustfmt 28 | - name: Rust Version 29 | run: rustc --version 30 | - run: cargo install cargo-audit 31 | - name: Checkout sources 32 | uses: actions/checkout@v5 33 | with: 34 | persist-credentials: false 35 | - run: cargo generate-lockfile 36 | - run: cargo audit --deny warnings 37 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Bryant Luk "] 3 | categories = ["encoding", "no-std"] 4 | description = "A Bencode encoding/decoding implementation." 5 | documentation = "https://docs.rs/bt_bencode/" 6 | edition = "2018" 7 | include = [ 8 | "/src", 9 | "/tests", 10 | "/Cargo.toml", 11 | "/CHANGELOG.md", 12 | "/clippy.toml", 13 | "/deny.toml", 14 | "/LICENSE-APACHE", 15 | "/LICENSE-MIT", 16 | "/README.md", 17 | ] 18 | keywords = ["bencode", "bittorrent", "torrent", "serialization", "serde"] 19 | license = "MIT OR Apache-2.0" 20 | name = "bt_bencode" 21 | readme = "README.md" 22 | repository = "https://github.com/bluk/bt_bencode" 23 | rust-version = "1.36.0" 24 | version = "0.8.2" 25 | 26 | [dependencies] 27 | itoa = {version = "1.0.0", default-features = false } 28 | serde = {version = "1.0.100", default-features = false } 29 | 30 | [dev-dependencies] 31 | serde_derive = "1.0.100" 32 | sha1 = "0.10.1" 33 | 34 | [features] 35 | default = ["std"] 36 | 37 | std = ["serde/std"] 38 | 39 | alloc = ["serde/alloc"] 40 | 41 | [package.metadata.docs.rs] 42 | all-features = true 43 | rustdoc-args = ["--cfg", "docsrs"] 44 | -------------------------------------------------------------------------------- /src/write.rs: -------------------------------------------------------------------------------- 1 | //! [Write] trait and helpers to write bytes for the serializer. 2 | 3 | #[cfg(feature = "std")] 4 | use crate::{error::ErrorKind, Error}; 5 | #[cfg(feature = "std")] 6 | use std::io; 7 | 8 | #[cfg(not(feature = "std"))] 9 | use alloc::vec::Vec; 10 | 11 | use crate::error::Result; 12 | 13 | /// Trait used by the [`ser::Serializer`][crate::ser::Serializer] to write bytes. 14 | pub trait Write { 15 | /// Writes all of the bytes. 16 | /// 17 | /// # Errors 18 | /// 19 | /// If the bytes could not be written, a Bencode error is returned. 20 | fn write_all(&mut self, buf: &[u8]) -> Result<()>; 21 | } 22 | 23 | /// A wrapper to implement this crate's [Write] trait for [`std::io::Write`] trait implementations. 24 | #[cfg(feature = "std")] 25 | #[derive(Debug)] 26 | #[allow(clippy::module_name_repetitions)] 27 | pub struct IoWrite 28 | where 29 | W: io::Write, 30 | { 31 | writer: W, 32 | } 33 | 34 | #[cfg(feature = "std")] 35 | impl IoWrite 36 | where 37 | W: io::Write, 38 | { 39 | /// Instantiates a new writer. 40 | pub fn new(writer: W) -> Self { 41 | Self { writer } 42 | } 43 | } 44 | 45 | #[cfg(feature = "std")] 46 | impl Write for IoWrite 47 | where 48 | W: io::Write, 49 | { 50 | #[inline] 51 | fn write_all(&mut self, buf: &[u8]) -> Result<()> { 52 | self.writer 53 | .write_all(buf) 54 | .map_err(|error| Error::with_kind(ErrorKind::Io(error))) 55 | } 56 | } 57 | 58 | impl Write for Vec { 59 | fn write_all(&mut self, buf: &[u8]) -> Result<()> { 60 | self.extend_from_slice(buf); 61 | Ok(()) 62 | } 63 | } 64 | 65 | impl Write for &mut Vec { 66 | fn write_all(&mut self, buf: &[u8]) -> Result<()> { 67 | self.extend_from_slice(buf); 68 | Ok(()) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/value/index.rs: -------------------------------------------------------------------------------- 1 | //! Indexes into the [Value] type. 2 | 3 | use super::Value; 4 | use core::ops; 5 | 6 | #[cfg(all(feature = "alloc", not(feature = "std")))] 7 | use alloc::string::String; 8 | #[cfg(feature = "std")] 9 | use std::string::String; 10 | 11 | /// Indexes into the [Value] type. 12 | pub trait Index { 13 | /// If possible, returns a reference to the value using `&self` as an index for the [Value] parameter. 14 | fn index<'a>(&self, v: &'a Value) -> Option<&'a Value>; 15 | 16 | /// If possible, returns a mutable reference to the value using `&self` as an index for the [Value] parameter. 17 | fn index_mut<'a>(&self, v: &'a mut Value) -> Option<&'a mut Value>; 18 | } 19 | 20 | impl Index for usize { 21 | fn index<'a>(&self, v: &'a Value) -> Option<&'a Value> { 22 | match v { 23 | Value::List(ref l) => l.get(*self), 24 | _ => None, 25 | } 26 | } 27 | 28 | fn index_mut<'a>(&self, v: &'a mut Value) -> Option<&'a mut Value> { 29 | match v { 30 | Value::List(ref mut l) => l.get_mut(*self), 31 | _ => None, 32 | } 33 | } 34 | } 35 | 36 | impl Index for str { 37 | fn index<'a>(&self, v: &'a Value) -> Option<&'a Value> { 38 | match v { 39 | Value::Dict(ref d) => d.get(self.as_bytes()), 40 | _ => None, 41 | } 42 | } 43 | 44 | fn index_mut<'a>(&self, v: &'a mut Value) -> Option<&'a mut Value> { 45 | match v { 46 | Value::Dict(ref mut d) => d.get_mut(self.as_bytes()), 47 | _ => None, 48 | } 49 | } 50 | } 51 | 52 | impl Index for String { 53 | fn index<'a>(&self, v: &'a Value) -> Option<&'a Value> { 54 | self[..].index(v) 55 | } 56 | 57 | fn index_mut<'a>(&self, v: &'a mut Value) -> Option<&'a mut Value> { 58 | self[..].index_mut(v) 59 | } 60 | } 61 | 62 | impl Index for &T 63 | where 64 | T: Index + ?Sized, 65 | { 66 | fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { 67 | (*self).index(val) 68 | } 69 | 70 | fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { 71 | (*self).index_mut(val) 72 | } 73 | } 74 | 75 | impl ops::Index for Value 76 | where 77 | I: Index, 78 | { 79 | type Output = Value; 80 | 81 | fn index(&self, index: I) -> &Value { 82 | self.get(index).expect("invalid index") 83 | } 84 | } 85 | 86 | impl ops::IndexMut for Value 87 | where 88 | I: Index, 89 | { 90 | fn index_mut(&mut self, index: I) -> &mut Value { 91 | self.get_mut(index).expect("invalid index") 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BtBencode 2 | 3 | BtBencode is a library which can help with [Bencode][wikipedia_bencode] 4 | encoding/decoding. Bencode is primarily used in [BitTorrent][bep_0003] related 5 | applications. 6 | 7 | It uses the [Serde][serde] library to serialize and deserialize Bencode data. 8 | It is similar to [Serde JSON][serde_json] in terms of functionality and 9 | implementation. 10 | 11 | * [Latest API Documentation][docs_rs_bt_bencode] 12 | 13 | ## Examples 14 | 15 | An example serializing a standard Rust collection type and then deserializing 16 | into a custom type: 17 | 18 | ```rust 19 | use std::collections::BTreeMap; 20 | use serde_derive::Deserialize; 21 | 22 | let mut dict: BTreeMap = BTreeMap::new(); 23 | dict.insert(String::from("url"), String::from("https://example.com/")); 24 | 25 | let serialized_bytes = bt_bencode::to_vec(&dict)?; 26 | 27 | #[derive(Deserialize)] 28 | struct Info<'a> { 29 | url: &'a str, 30 | } 31 | 32 | let info: Info = bt_bencode::from_slice(&serialized_bytes)?; 33 | assert_eq!(info.url, "https://example.com/"); 34 | ``` 35 | 36 | An example deserializing from a slice of bytes into a general `Value` 37 | representation and then from the `Value` instance into a more strongly typed 38 | data structure. 39 | 40 | ```rust 41 | use serde_derive::{Serialize, Deserialize}; 42 | 43 | use bt_bencode::Value; 44 | 45 | #[derive(Serialize, Deserialize)] 46 | struct Info { 47 | t: String, 48 | url: String, 49 | } 50 | 51 | let serialized_bytes = bt_bencode::to_vec(&Info { 52 | t: String::from("query"), 53 | url: String::from("https://example.com/"), 54 | })?; 55 | 56 | let value: Value = bt_bencode::from_slice(&serialized_bytes)?; 57 | assert_eq!(value["t"].as_str().unwrap(), "query"); 58 | assert_eq!( 59 | value.get("url").and_then(|url| url.as_str()).unwrap(), 60 | "https://example.com/" 61 | ); 62 | 63 | let info: Info = bt_bencode::from_value(value)?; 64 | assert_eq!(info.t, "query"); 65 | assert_eq!(info.url, "https://example.com/"); 66 | ``` 67 | 68 | ## Installation 69 | 70 | ```sh 71 | cargo add bt_bencode 72 | ``` 73 | 74 | By default, the `std` feature is enabled. 75 | 76 | ### Alloc only 77 | 78 | If the host environment has an allocator but does not have access to the Rust 79 | `std` library: 80 | 81 | ```sh 82 | cargo add --no-default-features --features alloc bt_bencode 83 | ``` 84 | 85 | ## License 86 | 87 | Licensed under either of [Apache License, Version 2.0][LICENSE_APACHE] or [MIT 88 | License][LICENSE_MIT] at your option. 89 | 90 | ### Contributions 91 | 92 | Unless you explicitly state otherwise, any contribution intentionally submitted 93 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 94 | dual licensed as above, without any additional terms or conditions. 95 | 96 | [LICENSE_APACHE]: LICENSE-APACHE 97 | [LICENSE_MIT]: LICENSE-MIT 98 | [wikipedia_bencode]: https://en.wikipedia.org/wiki/Bencode 99 | [bep_0003]: http://www.bittorrent.org/beps/bep_0003.html 100 | [serde]: https://serde.rs 101 | [serde_json]: https://github.com/serde-rs/json 102 | [docs_rs_bt_bencode]: https://docs.rs/bt_bencode/latest/bt_bencode/ -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # BtBencode 2 | //! 3 | //! `BtBencode` is a library which can help with [Bencode][wikipedia_bencode] 4 | //! encoding/decoding. Bencode is primarily used in [BitTorrent][bep_0003] related 5 | //! applications. 6 | //! 7 | //! It uses the [Serde][serde] library to serialize and deserialize Bencode data. 8 | //! It is similar to [Serde JSON][serde_json] in terms of functionality and 9 | //! implementation. 10 | //! 11 | //! ## Documentation 12 | //! 13 | //! * [Latest API Docs][docs_rs_bt_bencode] 14 | //! 15 | //! ## Examples 16 | //! 17 | //! An example serializing a standard Rust collection type and then deserializing 18 | //! into a custom type: 19 | //! 20 | //! ```rust 21 | //! use std::collections::BTreeMap; 22 | //! use serde_derive::Deserialize; 23 | //! 24 | //! let mut dict: BTreeMap = BTreeMap::new(); 25 | //! dict.insert(String::from("url"), String::from("https://example.com/")); 26 | //! 27 | //! let serialized_bytes = bt_bencode::to_vec(&dict)?; 28 | //! 29 | //! #[derive(Deserialize)] 30 | //! struct Info<'a> { 31 | //! url: &'a str, 32 | //! } 33 | //! 34 | //! let info: Info = bt_bencode::from_slice(&serialized_bytes)?; 35 | //! assert_eq!(info.url, "https://example.com/"); 36 | //! # Ok::<(), bt_bencode::Error>(()) 37 | //! ``` 38 | //! 39 | //! An example deserializing from a slice of bytes into a general `Value` 40 | //! representation and then from the `Value` instance into a more strongly typed 41 | //! data structure. 42 | //! 43 | //! ```rust 44 | //! use serde_derive::{Serialize, Deserialize}; 45 | //! 46 | //! use bt_bencode::Value; 47 | //! 48 | //! #[derive(Serialize, Deserialize)] 49 | //! struct Info { 50 | //! t: String, 51 | //! url: String, 52 | //! } 53 | //! 54 | //! let serialized_bytes = bt_bencode::to_vec(&Info { 55 | //! t: String::from("query"), 56 | //! url: String::from("https://example.com/"), 57 | //! })?; 58 | //! 59 | //! let value: Value = bt_bencode::from_slice(&serialized_bytes)?; 60 | //! assert_eq!(value["t"].as_str().unwrap(), "query"); 61 | //! assert_eq!( 62 | //! value.get("url").and_then(|url| url.as_str()).unwrap(), 63 | //! "https://example.com/" 64 | //! ); 65 | //! 66 | //! let info: Info = bt_bencode::from_value(value)?; 67 | //! assert_eq!(info.t, "query"); 68 | //! assert_eq!(info.url, "https://example.com/"); 69 | //! # Ok::<(), bt_bencode::Error>(()) 70 | //! ``` 71 | //! 72 | //! ## License 73 | //! 74 | //! Licensed under either of [Apache License, Version 2.0][LICENSE_APACHE] or [MIT 75 | //! License][LICENSE_MIT] at your option. 76 | //! 77 | //! ### Contributions 78 | //! 79 | //! Unless you explicitly state otherwise, any contribution intentionally submitted 80 | //! for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 81 | //! dual licensed as above, without any additional terms or conditions. 82 | //! 83 | //! [LICENSE_APACHE]: LICENSE-APACHE 84 | //! [LICENSE_MIT]: LICENSE-MIT 85 | //! [wikipedia_bencode]: https://en.wikipedia.org/wiki/Bencode 86 | //! [bep_0003]: http://www.bittorrent.org/beps/bep_0003.html 87 | //! [serde]: https://serde.rs 88 | //! [serde_json]: https://github.com/serde-rs/json 89 | //! [docs_rs_bt_bencode]: https://docs.rs/bt_bencode/latest/bt_bencode/ 90 | 91 | #![cfg_attr(not(feature = "std"), no_std)] 92 | #![cfg_attr(docsrs, feature(doc_cfg))] 93 | #![warn( 94 | missing_copy_implementations, 95 | missing_debug_implementations, 96 | missing_docs, 97 | rust_2018_idioms, 98 | unused_lifetimes, 99 | unused_qualifications 100 | )] 101 | 102 | #[cfg(all(feature = "alloc", not(feature = "std")))] 103 | extern crate alloc; 104 | 105 | #[macro_use] 106 | extern crate serde; 107 | 108 | mod bstring; 109 | mod de; 110 | mod error; 111 | 112 | pub mod read; 113 | pub mod write; 114 | 115 | mod ser; 116 | pub mod value; 117 | 118 | #[doc(inline)] 119 | pub use bstring::ByteString; 120 | #[doc(inline)] 121 | pub use de::{from_slice, Deserializer}; 122 | #[doc(inline)] 123 | pub use error::{Error, ErrorKind, Result}; 124 | #[doc(inline)] 125 | pub use value::{from_value, to_value, Value}; 126 | 127 | #[doc(inline)] 128 | #[cfg(feature = "std")] 129 | pub use ser::to_writer; 130 | 131 | #[doc(inline)] 132 | pub use ser::{to_vec, Serializer}; 133 | 134 | #[doc(inline)] 135 | #[cfg(feature = "std")] 136 | pub use de::from_reader; 137 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ### [Unreleased] 4 | 5 | ## [0.8.2](https://github.com/bluk/bt_bencode/compare/v0.8.1...v0.8.2) - 2025-03-16 6 | 7 | ### Added 8 | 9 | - Add `Value::as_list()`, `as_list_mut()`, and `is_list()` 10 | - Add `deserialize_i128` and `deserialize_u128` support 11 | 12 | ### Updated 13 | 14 | - Remove duplicated code and forward implementations to `deserialize_any()` to 15 | reduce code size. 16 | 17 | ### Other 18 | 19 | - Add performance note when using IoRead 20 | 21 | ## [0.8.1] - 2024-05-15 22 | 23 | ### Updated 24 | 25 | - Update serde dependency to be more precise to ensure minimal versions are 26 | correct. 27 | 28 | ## [0.8.0] - 2023-12-31 29 | 30 | ### Updated 31 | 32 | - **Breaking change**: Modify `Value` variants to use `ByteString` instead of 33 | `serde_bytes::ByteBuf` for byte string values. Removed the `serde_bytes` 34 | dependency. 35 | 36 | ### Added 37 | 38 | - Add `ByteString` type as a specialized type for serialization and 39 | deserialization of bencoded strings. 40 | 41 | ## [0.7.0] - 2022-07-31 42 | 43 | ### Added 44 | 45 | * Add `Deserializer::byte_offset()` to return the byte offset in the underlying source. It may be useful if there is trailing data. 46 | * Serialize and deserialize tuples and tuple structs. 47 | * Allow deserialization from a borrowed `Value`. 48 | * Set supported Rust version to `1.36.0`. The MSRV is not guaranteed due to dependencies being free to bump their version. 49 | 50 | ### Updated 51 | 52 | * In general, fewer allocations are made when parsing values. 53 | * **Breaking change**: Refactored the `Read` trait to allow borrowing against the original data. 54 | 55 | ``` 56 | #[derive(Deserialize)] 57 | struct Info<'a> { 58 | name: Option<&'a str>, 59 | pieces: &'a [u8], 60 | } 61 | ``` 62 | 63 | should work now when using `from_slice`. 64 | * **Breaking change**: Refactored the `Error` type. 65 | 66 | The `Error::byte_offset()` method can help hint where the error occurred at (usually only helpful for deserialization). 67 | 68 | Refactored to use `Box` to reduce the size of the return types. Rationale is 69 | influenced by Serde JSON issues/discussions where an allocation for an exceptional code path is acceptable. 70 | 71 | ## [0.6.1] - 2022-03-31 72 | 73 | ### Updated 74 | 75 | * Fix wrong error returned when parsing an invalid list. 76 | * Add documentation to more items 77 | * Add #[must_use] to more functions 78 | 79 | ## [0.6.0] - 2022-03-21 80 | 81 | ### Added 82 | 83 | * Allow serialization when no_std. 84 | 85 | Adds `Write` trait and implementations. 86 | 87 | Thanks [@bheesham](https://github.com/bheesham). 88 | 89 | ## [0.5.1] - 2022-03-14 90 | 91 | ### Updated 92 | 93 | * Use `Bytes` for `Values::Dict` index access instead of allocating a `ByteBuf`. 94 | 95 | ## [0.5.0] - 2022-03-09 96 | 97 | ### Updated 98 | 99 | * Update to `itoa` version `1.0.1`. 100 | 101 | ## [0.4.0] - 2021-05-27 102 | 103 | ### Added 104 | 105 | * Allow deserialization of non-byte string values into raw byte buffers. In 106 | cases where a value is a non-byte string, a byte buffer can be used to capture 107 | the raw encoded value. For instance, assuming a dictionary with an `info` 108 | key which has a dictionary value: 109 | 110 | ``` 111 | #[derive(Deserialize)] 112 | struct Metainfo { 113 | info: ByteBuf, 114 | } 115 | ``` 116 | 117 | could be used to capture the raw bytes of the encoded `info` dictionary value. 118 | 119 | For untrusted input, the value should be verified as having the correct type 120 | (e.g. a dictionary) instead of a byte string which contains the raw encoded 121 | value. 122 | 123 | ## [0.3.0] - 2020-10-10 124 | 125 | ### Added 126 | 127 | * `Read` trait and helper implementations `IoRead` and `SliceRead` are made public. 128 | * Add `Value` `as_number()`. 129 | * Add multiple `From` implementations for all the common primitive signed and 130 | unsigned integers to `Number`. 131 | 132 | ## [0.2.0] - 2020-02-20 133 | 134 | ### Added 135 | 136 | * `Value` type and related functions. 137 | 138 | ## [0.1.0] - 2020-02-20 139 | 140 | ### Added 141 | 142 | * `Serializer`, `Deserializer`, and related functions. 143 | 144 | [Unreleased]: https://github.com/bluk/bt_bencode/compare/v0.8.1...HEAD 145 | [0.8.1]: https://github.com/bluk/bt_bencode/compare/v0.8.0...v0.8.1 146 | [0.8.0]: https://github.com/bluk/bt_bencode/compare/v0.7.0...v0.8.0 147 | [0.7.0]: https://github.com/bluk/bt_bencode/compare/v0.6.1...v0.7.0 148 | [0.6.1]: https://github.com/bluk/bt_bencode/compare/v0.6.0...v0.6.1 149 | [0.6.0]: https://github.com/bluk/bt_bencode/compare/v0.5.1...v0.6.0 150 | [0.5.1]: https://github.com/bluk/bt_bencode/compare/v0.5.0...v0.5.1 151 | [0.5.0]: https://github.com/bluk/bt_bencode/compare/v0.4.0...v0.5.0 152 | [0.4.0]: https://github.com/bluk/bt_bencode/compare/v0.3.0...v0.4.0 153 | [0.3.0]: https://github.com/bluk/bt_bencode/compare/v0.2.0...v0.3.0 154 | [0.2.0]: https://github.com/bluk/bt_bencode/compare/v0.1.0...v0.2.0 155 | [0.1.0]: https://github.com/bluk/bt_bencode/releases/tag/v0.1.0 156 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Rust CI 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | 9 | pull_request: 10 | 11 | jobs: 12 | build: 13 | name: Build 14 | strategy: 15 | matrix: 16 | os: 17 | - ubuntu-latest 18 | - macos-latest 19 | - windows-latest 20 | rust: 21 | - stable 22 | - 1.36.0 23 | exclude: 24 | - os: macos-latest 25 | rust: 1.36.0 26 | runs-on: ${{ matrix.os }} 27 | steps: 28 | - name: Checkout sources 29 | uses: actions/checkout@v5 30 | with: 31 | persist-credentials: false 32 | - name: Install toolchain 33 | uses: dtolnay/rust-toolchain@master 34 | with: 35 | toolchain: ${{ matrix.rust }} 36 | - name: Rust Version 37 | run: rustc --version 38 | - name: Run cargo build (--all-features) 39 | run: cargo build --release --all-features 40 | - name: Run cargo build (--features alloc) 41 | run: cargo build --release --no-default-features --features alloc 42 | - name: Run cargo build (--features std) 43 | run: cargo build --release --no-default-features --features std 44 | test: 45 | name: Test 46 | strategy: 47 | matrix: 48 | os: 49 | - ubuntu-latest 50 | - macos-latest 51 | - windows-latest 52 | rust: 53 | - stable 54 | - 1.56.0 55 | exclude: 56 | - os: macos-latest 57 | rust: 1.56.0 58 | runs-on: ${{ matrix.os }} 59 | steps: 60 | - name: Checkout sources 61 | uses: actions/checkout@v5 62 | with: 63 | persist-credentials: false 64 | - name: Install toolchain 65 | uses: dtolnay/rust-toolchain@master 66 | with: 67 | toolchain: ${{ matrix.rust }} 68 | - name: Rust Version 69 | run: rustc --version 70 | - name: Run cargo check (--all-features) 71 | run: cargo check --all-features 72 | - name: Run cargo test (default) 73 | run: cargo test 74 | - name: Run cargo test (--all-features) 75 | run: cargo test --all-features 76 | - name: Run cargo test (--features alloc) 77 | run: cargo test --no-default-features --features alloc 78 | - name: Run cargo test (--features std) 79 | run: cargo test --no-default-features --features std 80 | rustfmt: 81 | name: Format 82 | strategy: 83 | matrix: 84 | os: 85 | - ubuntu-latest 86 | rust: 87 | - stable 88 | - nightly 89 | runs-on: ${{ matrix.os }} 90 | steps: 91 | - name: Checkout sources 92 | uses: actions/checkout@v5 93 | with: 94 | persist-credentials: false 95 | - name: Install toolchain 96 | uses: dtolnay/rust-toolchain@master 97 | with: 98 | toolchain: ${{ matrix.rust }} 99 | components: rustfmt 100 | - name: Rust Version 101 | run: rustc --version 102 | - run: cargo fmt --all -- --check 103 | clippy: 104 | name: Clippy 105 | strategy: 106 | matrix: 107 | os: 108 | - ubuntu-latest 109 | rust: 110 | - stable 111 | - nightly 112 | runs-on: ${{ matrix.os }} 113 | steps: 114 | - name: Checkout sources 115 | uses: actions/checkout@v5 116 | with: 117 | persist-credentials: false 118 | - name: Install toolchain 119 | uses: dtolnay/rust-toolchain@master 120 | with: 121 | toolchain: ${{ matrix.rust }} 122 | components: clippy 123 | - name: Run cargo clippy 124 | run: cargo clippy --all-targets --all-features 125 | cargo_deny: 126 | name: Cargo Deny 127 | strategy: 128 | matrix: 129 | os: 130 | - ubuntu-latest 131 | rust: 132 | - stable 133 | runs-on: ${{ matrix.os }} 134 | steps: 135 | - name: Install toolchain 136 | uses: dtolnay/rust-toolchain@master 137 | with: 138 | toolchain: ${{ matrix.rust }} 139 | components: rustfmt 140 | - name: Rust Version 141 | run: rustc --version 142 | - run: cargo install cargo-deny 143 | - name: Checkout sources 144 | uses: actions/checkout@v5 145 | with: 146 | persist-credentials: false 147 | - run: cargo generate-lockfile 148 | - run: cargo deny check 149 | - run: cargo deny --all-features check 150 | - run: cargo deny --no-default-features --features alloc check 151 | - run: cargo deny --no-default-features --features std check 152 | semver: 153 | name: Semantic Versioning Check 154 | strategy: 155 | matrix: 156 | os: 157 | - ubuntu-latest 158 | rust: 159 | - stable 160 | runs-on: ${{ matrix.os }} 161 | steps: 162 | - name: Checkout sources 163 | uses: actions/checkout@v5 164 | with: 165 | persist-credentials: false 166 | - name: Install toolchain 167 | uses: dtolnay/rust-toolchain@master 168 | with: 169 | toolchain: ${{ matrix.rust }} 170 | - name: Rust Version 171 | run: rustc --version 172 | - name: Check semver 173 | uses: obi1kenobi/cargo-semver-checks-action@v2 174 | -------------------------------------------------------------------------------- /tests/de.rs: -------------------------------------------------------------------------------- 1 | use bt_bencode::{ByteString, Error, Value}; 2 | use serde::Deserialize; 3 | use serde_derive::Deserialize; 4 | 5 | static TORRENT_BYTES: &[u8] = include_bytes!("ubuntu-20.04.4-live-server-amd64.iso.torrent"); 6 | 7 | #[derive(Debug, Deserialize, Clone, Eq, Hash, PartialEq)] 8 | struct TorrentFile { 9 | announce: String, 10 | } 11 | 12 | #[test] 13 | fn test_deserialize_torrent_file_via_type() -> Result<(), Error> { 14 | let torrent_file: TorrentFile = bt_bencode::from_slice(TORRENT_BYTES)?; 15 | 16 | assert_eq!(torrent_file.announce, "https://torrent.ubuntu.com/announce"); 17 | 18 | Ok(()) 19 | } 20 | 21 | #[test] 22 | fn test_deserialize_torrent_file_via_value() -> Result<(), Error> { 23 | let decoded_value: Value = bt_bencode::from_slice(TORRENT_BYTES)?; 24 | 25 | let announce = decoded_value 26 | .get("announce") 27 | .and_then(bt_bencode::Value::as_byte_str) 28 | .map(|v| v.to_vec()); 29 | 30 | assert_eq!( 31 | announce, 32 | Some(String::from("https://torrent.ubuntu.com/announce").into_bytes()) 33 | ); 34 | 35 | Ok(()) 36 | } 37 | 38 | #[test] 39 | fn test_deserialize_torrent_file_via_value_index() -> Result<(), Error> { 40 | let decoded_value: Value = bt_bencode::from_slice(TORRENT_BYTES)?; 41 | 42 | let announce = decoded_value["announce"].as_str(); 43 | 44 | assert_eq!(announce, Some("https://torrent.ubuntu.com/announce")); 45 | 46 | Ok(()) 47 | } 48 | 49 | #[test] 50 | fn test_deserialize_info_hash() -> Result<(), Error> { 51 | use sha1::Digest; 52 | 53 | #[derive(Deserialize)] 54 | struct Metainfo { 55 | info: ByteString, 56 | } 57 | 58 | let metainfo: Metainfo = bt_bencode::from_slice(TORRENT_BYTES)?; 59 | 60 | let mut hasher = sha1::Sha1::new(); 61 | hasher.update(&metainfo.info); 62 | let orig_info_hash = hasher.finalize(); 63 | 64 | assert_eq!( 65 | orig_info_hash.as_slice(), 66 | &[ 67 | 0xb4, 0x4a, 0x0e, 0x20, 0xfa, 0x5b, 0x7c, 0xec, 0xb7, 0x71, 0x56, 0x33, 0x3b, 0x42, 68 | 0x68, 0xdf, 0xd7, 0xc3, 0x0a, 0xfb 69 | ] 70 | ); 71 | 72 | let info: Value = bt_bencode::from_slice(&metainfo.info).unwrap(); 73 | 74 | // Need to verify the value is actually a dictionary. The ByteBuf could have been any value. 75 | assert!(info.is_dict()); 76 | 77 | // Verify that a round-trip decoding and encoding produces the same info hash. 78 | // The re-encoding ensures that the original data was encoded correctly 79 | // according to bencode rules (ordering of keys, no leading zeros, etc.) 80 | let re_encoded_bytes: Vec = bt_bencode::to_vec(&info).unwrap(); 81 | let mut hasher = sha1::Sha1::new(); 82 | hasher.update(&re_encoded_bytes); 83 | let re_encoded_info_hash = hasher.finalize(); 84 | assert_eq!(orig_info_hash, re_encoded_info_hash); 85 | 86 | assert_eq!( 87 | info.get("piece length").and_then(bt_bencode::Value::as_u64), 88 | Some(262_144) 89 | ); 90 | assert_eq!( 91 | info.get("pieces") 92 | .and_then(bt_bencode::Value::as_byte_str) 93 | .map(|v| v.len()), 94 | Some(101_600) 95 | ); 96 | assert_eq!( 97 | info.get("length").and_then(bt_bencode::Value::as_u64), 98 | Some(1_331_691_520) 99 | ); 100 | 101 | Ok(()) 102 | } 103 | 104 | #[test] 105 | fn test_deserialize_info_hash_borrowed() -> Result<(), Error> { 106 | use sha1::Digest; 107 | 108 | #[derive(Deserialize)] 109 | struct Metainfo<'a> { 110 | info: &'a [u8], 111 | } 112 | 113 | #[derive(Deserialize)] 114 | struct Info<'a> { 115 | name: Option<&'a str>, 116 | pieces: &'a [u8], 117 | } 118 | 119 | let metainfo: Metainfo = bt_bencode::from_slice(TORRENT_BYTES)?; 120 | 121 | let mut hasher = sha1::Sha1::new(); 122 | hasher.update(metainfo.info); 123 | let orig_info_hash = hasher.finalize(); 124 | 125 | assert_eq!( 126 | orig_info_hash.as_slice(), 127 | &[ 128 | 0xb4, 0x4a, 0x0e, 0x20, 0xfa, 0x5b, 0x7c, 0xec, 0xb7, 0x71, 0x56, 0x33, 0x3b, 0x42, 129 | 0x68, 0xdf, 0xd7, 0xc3, 0x0a, 0xfb 130 | ] 131 | ); 132 | 133 | let info: Value = bt_bencode::from_slice(metainfo.info).unwrap(); 134 | 135 | // Need to verify the value is actually a dictionary. The ByteBuf could have been any value. 136 | assert!(info.is_dict()); 137 | 138 | // Verify that a round-trip decoding and encoding produces the same info hash. 139 | // The re-encoding ensures that the original data was encoded correctly 140 | // according to bencode rules (ordering of keys, no leading zeros, etc.) 141 | let re_encoded_bytes: Vec = bt_bencode::to_vec(&info).unwrap(); 142 | let mut hasher = sha1::Sha1::new(); 143 | hasher.update(&re_encoded_bytes); 144 | let re_encoded_info_hash = hasher.finalize(); 145 | assert_eq!(orig_info_hash, re_encoded_info_hash); 146 | 147 | assert_eq!( 148 | info.get("piece length").and_then(bt_bencode::Value::as_u64), 149 | Some(262_144) 150 | ); 151 | assert_eq!( 152 | info.get("pieces") 153 | .and_then(bt_bencode::Value::as_byte_str) 154 | .map(|v| v.len()), 155 | Some(101_600) 156 | ); 157 | assert_eq!( 158 | info.get("length").and_then(bt_bencode::Value::as_u64), 159 | Some(1_331_691_520) 160 | ); 161 | 162 | let info = Info::deserialize(&info)?; 163 | 164 | assert_eq!(info.name, Some("ubuntu-20.04.4-live-server-amd64.iso")); 165 | assert_eq!(info.pieces.len(), 101_600); 166 | 167 | Ok(()) 168 | } 169 | -------------------------------------------------------------------------------- /src/bstring.rs: -------------------------------------------------------------------------------- 1 | //! Byte string which helps with the deserialization. 2 | 3 | use core::{ 4 | borrow::{Borrow, BorrowMut}, 5 | cmp, fmt, 6 | ops::{Deref, DerefMut}, 7 | }; 8 | 9 | #[cfg(all(feature = "alloc", not(feature = "std")))] 10 | use alloc::{string::String, vec::Vec}; 11 | #[cfg(feature = "std")] 12 | use std::{string::String, vec::Vec}; 13 | 14 | use serde::{ 15 | de::{SeqAccess, Visitor}, 16 | Deserialize, Deserializer, 17 | }; 18 | 19 | /// A sequence of bytes like a `Vec`. 20 | /// 21 | /// Bencoded "strings" are not necessarily UTF-8 encoded values so if a field is 22 | /// not guranteed to be a UTF-8 string, then you should use a `ByteString` or 23 | /// another equivalent type. 24 | /// 25 | /// Ideally, if you knew a field was a bencoded "string", then you could use 26 | /// `Vec` or `&[u8]` to represent the field without having to use a wrapper 27 | /// like `ByteString` (which is just a newtype around `Vec`). However, due 28 | /// to a limitation within `serde` and Rust, a `Vec` and `&[u8]` will 29 | /// serialize and deserialize as a list of individual byte elements. 30 | /// 31 | /// The `serde_bytes` crate can overcome this limitation. `serde_bytes` is still 32 | /// pre-1.0 at the time of this writing, so a specific type within this crate 33 | /// exists. 34 | /// 35 | /// # Examples 36 | /// 37 | /// ```rust 38 | /// use bt_bencode::ByteString; 39 | /// 40 | /// let bstr = ByteString::from("hello"); 41 | /// assert_eq!(bstr.as_slice(), b"hello"); 42 | /// assert_eq!(&*bstr, b"hello"); 43 | /// assert_eq!(bstr, ByteString::from(String::from("hello"))); 44 | /// 45 | /// let expected: Vec = b"hello".to_vec(); 46 | /// assert_eq!(*&*bstr, expected); 47 | /// assert_eq!(bstr, expected.into()); 48 | /// 49 | /// let encoded = bt_bencode::to_vec(&bstr)?; 50 | /// assert_eq!(encoded, b"5:hello"); 51 | /// 52 | /// let decoded: ByteString = bt_bencode::from_slice(&encoded)?; 53 | /// assert_eq!(decoded.as_slice(), b"hello"); 54 | /// 55 | /// # Ok::<(), bt_bencode::Error>(()) 56 | /// ``` 57 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] 58 | pub struct ByteString(Vec); 59 | 60 | impl AsRef<[u8]> for ByteString { 61 | fn as_ref(&self) -> &[u8] { 62 | &self.0 63 | } 64 | } 65 | 66 | impl AsMut<[u8]> for ByteString { 67 | fn as_mut(&mut self) -> &mut [u8] { 68 | &mut self.0 69 | } 70 | } 71 | 72 | impl Borrow<[u8]> for ByteString { 73 | fn borrow(&self) -> &[u8] { 74 | &self.0 75 | } 76 | } 77 | 78 | impl BorrowMut<[u8]> for ByteString { 79 | fn borrow_mut(&mut self) -> &mut [u8] { 80 | &mut self.0 81 | } 82 | } 83 | 84 | impl fmt::Debug for ByteString { 85 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 86 | fmt::Debug::fmt(&self.0, f) 87 | } 88 | } 89 | 90 | impl Deref for ByteString { 91 | type Target = Vec; 92 | 93 | fn deref(&self) -> &Self::Target { 94 | &self.0 95 | } 96 | } 97 | 98 | impl DerefMut for ByteString { 99 | fn deref_mut(&mut self) -> &mut Self::Target { 100 | &mut self.0 101 | } 102 | } 103 | 104 | impl<'a> From<&'a [u8]> for ByteString { 105 | fn from(value: &'a [u8]) -> Self { 106 | Self(Vec::from(value)) 107 | } 108 | } 109 | 110 | impl<'a> From<&'a str> for ByteString { 111 | fn from(value: &'a str) -> Self { 112 | Self(Vec::from(value)) 113 | } 114 | } 115 | 116 | impl From for ByteString { 117 | fn from(value: String) -> Self { 118 | Self(Vec::from(value)) 119 | } 120 | } 121 | 122 | impl From> for ByteString { 123 | fn from(value: Vec) -> Self { 124 | Self(value) 125 | } 126 | } 127 | 128 | impl serde::Serialize for ByteString { 129 | fn serialize(&self, serializer: S) -> Result 130 | where 131 | S: serde::Serializer, 132 | { 133 | serializer.serialize_bytes(&self.0) 134 | } 135 | } 136 | 137 | struct BStringVisitor; 138 | 139 | impl<'de> Visitor<'de> for BStringVisitor { 140 | type Value = ByteString; 141 | 142 | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 143 | formatter.write_str("byte string") 144 | } 145 | 146 | fn visit_seq(self, mut visitor: V) -> Result 147 | where 148 | V: SeqAccess<'de>, 149 | { 150 | let capacity = cmp::min(visitor.size_hint().unwrap_or_default(), 4096); 151 | let mut bytes = Vec::with_capacity(capacity); 152 | 153 | while let Some(b) = visitor.next_element()? { 154 | bytes.push(b); 155 | } 156 | 157 | Ok(ByteString::from(bytes)) 158 | } 159 | 160 | fn visit_bytes(self, v: &[u8]) -> Result { 161 | Ok(ByteString::from(v)) 162 | } 163 | 164 | fn visit_byte_buf(self, v: Vec) -> Result 165 | where 166 | E: serde::de::Error, 167 | { 168 | Ok(ByteString::from(v)) 169 | } 170 | 171 | fn visit_str(self, v: &str) -> Result 172 | where 173 | E: serde::de::Error, 174 | { 175 | Ok(ByteString::from(v)) 176 | } 177 | 178 | fn visit_string(self, v: String) -> Result 179 | where 180 | E: serde::de::Error, 181 | { 182 | Ok(ByteString::from(v)) 183 | } 184 | } 185 | 186 | impl<'de> Deserialize<'de> for ByteString { 187 | fn deserialize(deserializer: D) -> Result 188 | where 189 | D: Deserializer<'de>, 190 | { 191 | deserializer.deserialize_byte_buf(BStringVisitor) 192 | } 193 | } 194 | 195 | impl ByteString { 196 | /// Returns the inner vector. 197 | #[inline] 198 | #[must_use] 199 | pub fn into_vec(self) -> Vec { 200 | self.0 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | //! Possible crate errors. 2 | 3 | use serde::{de, ser}; 4 | 5 | #[cfg(all(feature = "alloc", not(feature = "std")))] 6 | use alloc::{ 7 | boxed::Box, 8 | format, 9 | string::{String, ToString}, 10 | }; 11 | #[cfg(feature = "std")] 12 | use std::{ 13 | boxed::Box, 14 | error, format, 15 | string::{String, ToString}, 16 | }; 17 | 18 | use core::{ 19 | fmt::{self, Display}, 20 | result, 21 | }; 22 | 23 | /// Alias for a [`Result`][std::result::Result] with a [`bt_bencode::Error`][Error] error type. 24 | pub type Result = result::Result; 25 | 26 | /// Errors during serialization and deserialization. 27 | pub struct Error { 28 | inner: Box, 29 | } 30 | 31 | impl Error { 32 | /// Constructs an error with the kind and the byte offset where the error 33 | /// was detected. 34 | /// 35 | /// A byte offset value of `0` indicates that the byte offset is either 36 | /// unknown or not relevant. 37 | #[must_use] 38 | #[inline] 39 | pub fn new(kind: ErrorKind, byte_offset: usize) -> Self { 40 | Self { 41 | inner: Box::new(ErrorImpl { kind, byte_offset }), 42 | } 43 | } 44 | 45 | #[must_use] 46 | #[inline] 47 | pub(crate) fn with_kind(kind: ErrorKind) -> Self { 48 | Self::new(kind, 0) 49 | } 50 | 51 | /// The kind of error encountered 52 | #[must_use] 53 | #[inline] 54 | pub fn kind(&self) -> &ErrorKind { 55 | &self.inner.kind 56 | } 57 | 58 | /// The byte offset where the error was detected. 59 | /// 60 | /// Usually, the byte offset is after the problem has been detected. For 61 | /// instance, if an integer is not encoded correctly like `i12ae`, the byte 62 | /// offset may be after the `a` byte is read. 63 | #[must_use] 64 | #[inline] 65 | pub fn byte_offset(&self) -> usize { 66 | self.inner.byte_offset 67 | } 68 | } 69 | 70 | impl Display for Error { 71 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 72 | Display::fmt(&self.inner, f) 73 | } 74 | } 75 | 76 | impl fmt::Debug for Error { 77 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 78 | fmt::Debug::fmt(&self.inner, f) 79 | } 80 | } 81 | 82 | impl de::StdError for Error { 83 | #[cfg(feature = "std")] 84 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 85 | self.inner.kind.source() 86 | } 87 | } 88 | 89 | impl de::Error for Error { 90 | fn custom(msg: T) -> Self { 91 | Error::with_kind(ErrorKind::Deserialize(msg.to_string())) 92 | } 93 | 94 | fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Self { 95 | Error::with_kind(ErrorKind::Deserialize(format!( 96 | "unexpected type error. invalid_type={}, expected_type={}", 97 | unexp, exp 98 | ))) 99 | } 100 | } 101 | 102 | impl ser::Error for Error { 103 | fn custom(msg: T) -> Self { 104 | Error::with_kind(ErrorKind::Serialize(msg.to_string())) 105 | } 106 | } 107 | 108 | #[cfg(feature = "std")] 109 | impl From for std::io::Error { 110 | fn from(error: Error) -> Self { 111 | if let ErrorKind::Io(error) = error.inner.kind { 112 | return error; 113 | } 114 | std::io::Error::new(std::io::ErrorKind::Other, error.to_string()) 115 | } 116 | } 117 | 118 | struct ErrorImpl { 119 | kind: ErrorKind, 120 | byte_offset: usize, 121 | } 122 | 123 | impl Display for ErrorImpl { 124 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 125 | if self.byte_offset == 0 { 126 | Display::fmt(&self.kind, f) 127 | } else { 128 | write!(f, "{} at byte offset {}", self.kind, self.byte_offset) 129 | } 130 | } 131 | } 132 | 133 | impl fmt::Debug for ErrorImpl { 134 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 135 | f.debug_struct("Error") 136 | .field("kind", &self.kind) 137 | .field("byte_offset", &self.byte_offset) 138 | .finish() 139 | } 140 | } 141 | 142 | /// All possible crate errors. 143 | #[allow(clippy::module_name_repetitions)] 144 | // Should the type be non_exhaustive? Probably if this crate was version 1.0+ but would need to bump MSRV to 1.40.0 145 | // #[non_exhaustive] 146 | pub enum ErrorKind { 147 | /// General deserialization error. 148 | /// 149 | /// Usually the error is due to mismatching types (e.g. a struct was expecting an u64 but the data had a string). 150 | Deserialize(String), 151 | /// End of file was encountered while parsing a value. 152 | EofWhileParsingValue, 153 | /// A value was expected but the deserializer did not find a valid bencoded value. 154 | ExpectedSomeValue, 155 | /// When deserializing a byte string, the length was not a valid number. 156 | InvalidByteStrLen, 157 | /// When deserializing an integer, the integer contained non-number characters. 158 | InvalidInteger, 159 | /// When deserializing a dictionary, the dictionary was not encoded correctly. 160 | InvalidDict, 161 | /// When deserializing a list, the list was not encoded correctly. 162 | InvalidList, 163 | #[cfg(feature = "std")] 164 | /// An I/O error. 165 | Io(std::io::Error), 166 | /// When deserializing, a dictionary key was found which was not a byte string. 167 | KeyMustBeAByteStr, 168 | /// A dictionary key was serialized but a call to serialize the key's value 169 | /// was never made after. 170 | KeyWithoutValue, 171 | /// General serialization error. 172 | Serialize(String), 173 | /// Unparsed trailing data was detected 174 | TrailingData, 175 | /// An unsupported type was used during serialization. 176 | /// 177 | /// Bencode only supports integers, byte strings, lists, and dictionaries. 178 | /// Types like `bool`, `f64`, and enums are not supported in general. 179 | /// 180 | /// Dictionaries only support byte strings as keys. 181 | UnsupportedType, 182 | /// A dictionary value was serialized but a call to serialize the key was 183 | /// never made beforehand. 184 | ValueWithoutKey, 185 | } 186 | 187 | #[cfg(feature = "std")] 188 | impl error::Error for ErrorKind { 189 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 190 | match self { 191 | ErrorKind::Deserialize(_) 192 | | ErrorKind::EofWhileParsingValue 193 | | ErrorKind::ExpectedSomeValue 194 | | ErrorKind::InvalidByteStrLen 195 | | ErrorKind::InvalidInteger 196 | | ErrorKind::InvalidDict 197 | | ErrorKind::InvalidList 198 | | ErrorKind::KeyMustBeAByteStr 199 | | ErrorKind::KeyWithoutValue 200 | | ErrorKind::Serialize(_) 201 | | ErrorKind::TrailingData 202 | | ErrorKind::UnsupportedType 203 | | ErrorKind::ValueWithoutKey => None, 204 | #[cfg(feature = "std")] 205 | ErrorKind::Io(source) => Some(source), 206 | } 207 | } 208 | } 209 | 210 | impl Display for ErrorKind { 211 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 212 | match self { 213 | ErrorKind::Deserialize(str) | ErrorKind::Serialize(str) => f.write_str(str), 214 | ErrorKind::EofWhileParsingValue => f.write_str("eof while parsing value"), 215 | ErrorKind::ExpectedSomeValue => f.write_str("expected some value"), 216 | ErrorKind::InvalidByteStrLen => f.write_str("invalid byte string length"), 217 | ErrorKind::InvalidInteger => f.write_str("invalid integer"), 218 | ErrorKind::InvalidDict => f.write_str("invalid dictionary"), 219 | ErrorKind::InvalidList => f.write_str("invalid list"), 220 | ErrorKind::KeyMustBeAByteStr => f.write_str("key must be a byte string"), 221 | ErrorKind::KeyWithoutValue => f.write_str("key without value"), 222 | ErrorKind::TrailingData => f.write_str("trailing data error"), 223 | ErrorKind::UnsupportedType => f.write_str("unsupported type"), 224 | ErrorKind::ValueWithoutKey => f.write_str("value without key"), 225 | #[cfg(feature = "std")] 226 | ErrorKind::Io(source) => Display::fmt(source, f), 227 | } 228 | } 229 | } 230 | 231 | impl fmt::Debug for ErrorKind { 232 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 233 | match self { 234 | ErrorKind::Deserialize(str) | ErrorKind::Serialize(str) => f.write_str(str), 235 | ErrorKind::EofWhileParsingValue => f.write_str("eof while parsing value"), 236 | ErrorKind::ExpectedSomeValue => f.write_str("expected some value"), 237 | ErrorKind::InvalidByteStrLen => f.write_str("invalid byte string length"), 238 | ErrorKind::InvalidInteger => f.write_str("invalid integer"), 239 | ErrorKind::InvalidDict => f.write_str("invalid dictionary"), 240 | ErrorKind::InvalidList => f.write_str("invalid list"), 241 | ErrorKind::KeyMustBeAByteStr => f.write_str("key must be a byte string"), 242 | ErrorKind::KeyWithoutValue => f.write_str("key without value"), 243 | ErrorKind::TrailingData => f.write_str("trailing data error"), 244 | ErrorKind::UnsupportedType => f.write_str("unsupported type"), 245 | ErrorKind::ValueWithoutKey => f.write_str("value without key"), 246 | #[cfg(feature = "std")] 247 | ErrorKind::Io(source) => fmt::Debug::fmt(source, f), 248 | } 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/value/de.rs: -------------------------------------------------------------------------------- 1 | //! Deserializes from a [Value]. 2 | 3 | use super::{Number, Value}; 4 | use crate::error::Error; 5 | use crate::ByteString; 6 | use serde::de::{DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor}; 7 | use serde::forward_to_deserialize_any; 8 | 9 | #[cfg(all(feature = "alloc", not(feature = "std")))] 10 | use alloc::{borrow::Cow, collections::BTreeMap, vec}; 11 | use core::slice; 12 | #[cfg(feature = "std")] 13 | use std::{borrow::Cow, collections::BTreeMap, vec}; 14 | 15 | impl<'de> serde::Deserializer<'de> for Value { 16 | type Error = Error; 17 | 18 | fn deserialize_any(self, visitor: V) -> Result 19 | where 20 | V: Visitor<'de>, 21 | { 22 | match self { 23 | Value::ByteStr(s) => visitor.visit_byte_buf(s.into_vec()), 24 | Value::Int(n) => match n { 25 | Number::Signed(s) => visitor.visit_i64(s), 26 | Number::Unsigned(u) => visitor.visit_u64(u), 27 | }, 28 | Value::List(l) => { 29 | let len = l.len(); 30 | 31 | let mut deserializer = ListDeserializer { 32 | iter: l.into_iter(), 33 | }; 34 | let seq = visitor.visit_seq(&mut deserializer)?; 35 | if deserializer.iter.len() == 0 { 36 | Ok(seq) 37 | } else { 38 | Err(serde::de::Error::invalid_length( 39 | len, 40 | &"expected more elements to be consumed in list", 41 | )) 42 | } 43 | } 44 | Value::Dict(d) => { 45 | let len = d.len(); 46 | let mut deserializer = DictDeserializer { 47 | iter: d.into_iter(), 48 | value: None, 49 | }; 50 | let map = visitor.visit_map(&mut deserializer)?; 51 | if deserializer.iter.len() == 0 { 52 | Ok(map) 53 | } else { 54 | Err(serde::de::Error::invalid_length( 55 | len, 56 | &"expected more elements to be consumed in dict", 57 | )) 58 | } 59 | } 60 | } 61 | } 62 | 63 | forward_to_deserialize_any! { 64 | bool f32 f64 unit unit_struct 65 | 66 | i8 i16 i32 i64 i128 67 | u8 u16 u32 u64 u128 68 | 69 | char str string bytes byte_buf 70 | 71 | seq tuple tuple_struct map 72 | 73 | struct enum identifier ignored_any 74 | } 75 | 76 | #[inline] 77 | fn deserialize_option(self, visitor: V) -> Result 78 | where 79 | V: Visitor<'de>, 80 | { 81 | visitor.visit_some(self) 82 | } 83 | 84 | #[inline] 85 | fn deserialize_newtype_struct( 86 | self, 87 | _name: &'static str, 88 | visitor: V, 89 | ) -> Result 90 | where 91 | V: Visitor<'de>, 92 | { 93 | visitor.visit_newtype_struct(self) 94 | } 95 | 96 | #[inline] 97 | fn is_human_readable(&self) -> bool { 98 | false 99 | } 100 | } 101 | 102 | impl IntoDeserializer<'_, Error> for Value { 103 | type Deserializer = Self; 104 | 105 | fn into_deserializer(self) -> Self::Deserializer { 106 | self 107 | } 108 | } 109 | 110 | struct ListDeserializer { 111 | iter: vec::IntoIter, 112 | } 113 | 114 | impl<'de> SeqAccess<'de> for ListDeserializer { 115 | type Error = Error; 116 | 117 | fn next_element_seed(&mut self, seed: T) -> Result, Error> 118 | where 119 | T: DeserializeSeed<'de>, 120 | { 121 | match self.iter.next() { 122 | Some(value) => seed.deserialize(value).map(Some), 123 | None => Ok(None), 124 | } 125 | } 126 | 127 | fn size_hint(&self) -> Option { 128 | match self.iter.size_hint() { 129 | (lower, Some(upper)) if lower == upper => Some(upper), 130 | _ => None, 131 | } 132 | } 133 | } 134 | 135 | struct DictDeserializer { 136 | iter: as IntoIterator>::IntoIter, 137 | value: Option, 138 | } 139 | 140 | impl<'de> MapAccess<'de> for DictDeserializer { 141 | type Error = Error; 142 | 143 | fn next_key_seed(&mut self, seed: T) -> Result, Error> 144 | where 145 | T: DeserializeSeed<'de>, 146 | { 147 | match self.iter.next() { 148 | Some((key, value)) => { 149 | self.value = Some(value); 150 | let key_de = DictKey { 151 | key: Cow::Owned(key), 152 | }; 153 | seed.deserialize(key_de).map(Some) 154 | } 155 | None => Ok(None), 156 | } 157 | } 158 | 159 | fn next_value_seed(&mut self, seed: T) -> Result 160 | where 161 | T: DeserializeSeed<'de>, 162 | { 163 | match self.value.take() { 164 | Some(value) => seed.deserialize(value), 165 | None => Err(serde::de::Error::custom("value is missing")), 166 | } 167 | } 168 | 169 | fn size_hint(&self) -> Option { 170 | match self.iter.size_hint() { 171 | (lower, Some(upper)) if lower == upper => Some(upper), 172 | _ => None, 173 | } 174 | } 175 | } 176 | 177 | struct DictKey<'a> { 178 | key: Cow<'a, ByteString>, 179 | } 180 | 181 | impl<'de> serde::Deserializer<'de> for DictKey<'de> { 182 | type Error = Error; 183 | 184 | fn deserialize_any(self, visitor: V) -> Result 185 | where 186 | V: Visitor<'de>, 187 | { 188 | match self.key { 189 | Cow::Borrowed(bytes) => visitor.visit_borrowed_bytes(bytes), 190 | Cow::Owned(bytes) => visitor.visit_byte_buf(bytes.into_vec()), 191 | } 192 | } 193 | 194 | #[inline] 195 | fn deserialize_option(self, visitor: V) -> Result 196 | where 197 | V: Visitor<'de>, 198 | { 199 | visitor.visit_some(self) 200 | } 201 | 202 | #[inline] 203 | fn deserialize_newtype_struct( 204 | self, 205 | _name: &'static str, 206 | visitor: V, 207 | ) -> Result 208 | where 209 | V: Visitor<'de>, 210 | { 211 | visitor.visit_newtype_struct(self) 212 | } 213 | 214 | forward_to_deserialize_any! { 215 | bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 216 | bytes byte_buf unit unit_struct seq tuple 217 | tuple_struct map struct enum identifier ignored_any 218 | } 219 | } 220 | 221 | impl<'de> serde::Deserializer<'de> for &'de Value { 222 | type Error = Error; 223 | 224 | fn deserialize_any(self, visitor: V) -> Result 225 | where 226 | V: Visitor<'de>, 227 | { 228 | match self { 229 | Value::ByteStr(bytes) => visitor.visit_borrowed_bytes(bytes), 230 | Value::Int(n) => match n { 231 | Number::Signed(s) => visitor.visit_i64(*s), 232 | Number::Unsigned(u) => visitor.visit_u64(*u), 233 | }, 234 | Value::List(l) => { 235 | let len = l.len(); 236 | 237 | let mut deserializer = ListRefDeserializer { iter: l.iter() }; 238 | 239 | let seq = visitor.visit_seq(&mut deserializer)?; 240 | if deserializer.iter.len() == 0 { 241 | Ok(seq) 242 | } else { 243 | Err(serde::de::Error::invalid_length( 244 | len, 245 | &"expected more elements to be consumed in list", 246 | )) 247 | } 248 | } 249 | Value::Dict(d) => { 250 | let len = d.len(); 251 | let mut deserializer = DictRefDeserializer { 252 | iter: d.iter(), 253 | value: None, 254 | }; 255 | 256 | let map = visitor.visit_map(&mut deserializer)?; 257 | if deserializer.iter.len() == 0 { 258 | Ok(map) 259 | } else { 260 | Err(serde::de::Error::invalid_length( 261 | len, 262 | &"expected more elements to be consumed in dict", 263 | )) 264 | } 265 | } 266 | } 267 | } 268 | 269 | forward_to_deserialize_any! { 270 | bool f32 f64 unit unit_struct 271 | 272 | i8 i16 i32 i64 i128 273 | u8 u16 u32 u64 u128 274 | 275 | char str string bytes byte_buf 276 | 277 | seq tuple tuple_struct map 278 | 279 | struct enum identifier ignored_any 280 | } 281 | 282 | #[inline] 283 | fn deserialize_option(self, visitor: V) -> Result 284 | where 285 | V: Visitor<'de>, 286 | { 287 | visitor.visit_some(self) 288 | } 289 | 290 | #[inline] 291 | fn deserialize_newtype_struct( 292 | self, 293 | _name: &'static str, 294 | visitor: V, 295 | ) -> Result 296 | where 297 | V: Visitor<'de>, 298 | { 299 | visitor.visit_newtype_struct(self) 300 | } 301 | 302 | #[inline] 303 | fn is_human_readable(&self) -> bool { 304 | false 305 | } 306 | } 307 | 308 | struct ListRefDeserializer<'a> { 309 | iter: slice::Iter<'a, Value>, 310 | } 311 | 312 | impl<'a> SeqAccess<'a> for ListRefDeserializer<'a> { 313 | type Error = Error; 314 | 315 | fn next_element_seed(&mut self, seed: T) -> Result, Error> 316 | where 317 | T: DeserializeSeed<'a>, 318 | { 319 | match self.iter.next() { 320 | Some(value) => seed.deserialize(value).map(Some), 321 | None => Ok(None), 322 | } 323 | } 324 | 325 | fn size_hint(&self) -> Option { 326 | match self.iter.size_hint() { 327 | (lower, Some(upper)) if lower == upper => Some(upper), 328 | _ => None, 329 | } 330 | } 331 | } 332 | 333 | struct DictRefDeserializer<'a> { 334 | iter: <&'a BTreeMap as IntoIterator>::IntoIter, 335 | value: Option<&'a Value>, 336 | } 337 | 338 | impl<'a> MapAccess<'a> for DictRefDeserializer<'a> { 339 | type Error = Error; 340 | 341 | fn next_key_seed(&mut self, seed: T) -> Result, Error> 342 | where 343 | T: DeserializeSeed<'a>, 344 | { 345 | match self.iter.next() { 346 | Some((key, value)) => { 347 | self.value = Some(value); 348 | let key_de = DictKey { 349 | key: Cow::Borrowed(key), 350 | }; 351 | seed.deserialize(key_de).map(Some) 352 | } 353 | None => Ok(None), 354 | } 355 | } 356 | 357 | fn next_value_seed(&mut self, seed: T) -> Result 358 | where 359 | T: DeserializeSeed<'a>, 360 | { 361 | match self.value.take() { 362 | Some(value) => seed.deserialize(value), 363 | None => Err(serde::de::Error::custom("value is missing")), 364 | } 365 | } 366 | 367 | fn size_hint(&self) -> Option { 368 | match self.iter.size_hint() { 369 | (lower, Some(upper)) if lower == upper => Some(upper), 370 | _ => None, 371 | } 372 | } 373 | } 374 | 375 | #[cfg(test)] 376 | mod tests { 377 | use super::*; 378 | use crate::{error::Result, from_value}; 379 | 380 | #[cfg(all(feature = "alloc", not(feature = "std")))] 381 | use alloc::{string::String, vec, vec::Vec}; 382 | #[cfg(feature = "std")] 383 | use std::{string::String, vec, vec::Vec}; 384 | 385 | #[test] 386 | fn test_deserialize_string() -> Result<()> { 387 | let v = Value::ByteStr(ByteString::from(String::from("spam"))); 388 | let s: String = from_value(v)?; 389 | assert_eq!("spam", s); 390 | Ok(()) 391 | } 392 | 393 | #[test] 394 | fn test_deserialize_byte_str() -> Result<()> { 395 | let v = Value::ByteStr(ByteString::from(String::from("spam"))); 396 | let b: ByteString = from_value(v)?; 397 | assert_eq!(ByteString::from(String::from("spam")), b); 398 | Ok(()) 399 | } 400 | 401 | #[test] 402 | fn test_deserialize_integer_1() -> Result<()> { 403 | let v = Value::Int(Number::Unsigned(3)); 404 | let i: u64 = from_value(v)?; 405 | assert_eq!(i, 3); 406 | Ok(()) 407 | } 408 | 409 | #[test] 410 | fn test_deserialize_integer_2() -> Result<()> { 411 | let v = Value::Int(Number::Signed(-3)); 412 | let i: i64 = from_value(v)?; 413 | assert_eq!(i, -3); 414 | Ok(()) 415 | } 416 | 417 | #[test] 418 | fn test_deserialize_integer_3() -> Result<()> { 419 | let v = Value::Int(Number::Unsigned(0)); 420 | let i: u64 = from_value(v)?; 421 | assert_eq!(i, 0); 422 | Ok(()) 423 | } 424 | 425 | #[test] 426 | fn test_deserialize_list() -> Result<()> { 427 | let v = Value::List(vec![ 428 | Value::ByteStr(ByteString::from(String::from("spam"))), 429 | Value::ByteStr(ByteString::from(String::from("eggs"))), 430 | ]); 431 | let v: Vec = from_value(v)?; 432 | assert_eq!(v, vec!["spam", "eggs"]); 433 | Ok(()) 434 | } 435 | 436 | #[test] 437 | fn test_deserialize_dict_1() -> Result<()> { 438 | let mut m = BTreeMap::new(); 439 | m.insert( 440 | ByteString::from(String::from("cow")), 441 | Value::ByteStr(ByteString::from(String::from("moo"))), 442 | ); 443 | m.insert( 444 | ByteString::from(String::from("spam")), 445 | Value::ByteStr(ByteString::from(String::from("eggs"))), 446 | ); 447 | let d = Value::Dict(m); 448 | let d: BTreeMap = from_value(d)?; 449 | 450 | let mut expected = BTreeMap::new(); 451 | expected.insert(String::from("cow"), String::from("moo")); 452 | expected.insert(String::from("spam"), String::from("eggs")); 453 | assert_eq!(d, expected); 454 | Ok(()) 455 | } 456 | 457 | #[test] 458 | fn test_deserialize_dict_1_borrowed_value() -> Result<()> { 459 | use serde::Deserialize; 460 | 461 | let mut m = BTreeMap::new(); 462 | m.insert( 463 | ByteString::from(String::from("cow")), 464 | Value::ByteStr(ByteString::from(String::from("moo"))), 465 | ); 466 | m.insert( 467 | ByteString::from(String::from("spam")), 468 | Value::ByteStr(ByteString::from(String::from("eggs"))), 469 | ); 470 | let d = Value::Dict(m); 471 | let d = BTreeMap::<&str, &str>::deserialize(&d)?; 472 | 473 | let mut expected = BTreeMap::new(); 474 | expected.insert("cow", "moo"); 475 | expected.insert("spam", "eggs"); 476 | assert_eq!(d, expected); 477 | Ok(()) 478 | } 479 | 480 | #[test] 481 | fn test_deserialize_dict_2() -> Result<()> { 482 | let mut m = BTreeMap::new(); 483 | m.insert( 484 | ByteString::from(String::from("spam")), 485 | Value::List(vec![ 486 | Value::ByteStr(ByteString::from(String::from("a"))), 487 | Value::ByteStr(ByteString::from(String::from("b"))), 488 | ]), 489 | ); 490 | let d = Value::Dict(m); 491 | let d: BTreeMap> = from_value(d)?; 492 | 493 | let mut expected = BTreeMap::new(); 494 | expected.insert( 495 | String::from("spam"), 496 | vec![String::from("a"), String::from("b")], 497 | ); 498 | assert_eq!(d, expected); 499 | Ok(()) 500 | } 501 | 502 | #[test] 503 | fn test_deserialize_dict_2_borrowed_value() -> Result<()> { 504 | use serde::Deserialize; 505 | 506 | let mut m = BTreeMap::new(); 507 | m.insert( 508 | ByteString::from(String::from("spam")), 509 | Value::List(vec![ 510 | Value::ByteStr(ByteString::from(String::from("a"))), 511 | Value::ByteStr(ByteString::from(String::from("b"))), 512 | ]), 513 | ); 514 | let d = Value::Dict(m); 515 | let d = BTreeMap::<&str, Vec<&str>>::deserialize(&d)?; 516 | 517 | let mut expected = BTreeMap::new(); 518 | expected.insert("spam", vec!["a", "b"]); 519 | assert_eq!(d, expected); 520 | Ok(()) 521 | } 522 | 523 | #[test] 524 | fn test_deserialize_dict_2_borrowed_value_as_bytes() -> Result<()> { 525 | use serde::Deserialize; 526 | 527 | let mut m = BTreeMap::new(); 528 | m.insert( 529 | ByteString::from(String::from("spam")), 530 | Value::List(vec![ 531 | Value::ByteStr(ByteString::from(String::from("a"))), 532 | Value::ByteStr(ByteString::from(String::from("b"))), 533 | ]), 534 | ); 535 | let d = Value::Dict(m); 536 | let d = BTreeMap::<&str, Vec<&[u8]>>::deserialize(&d)?; 537 | 538 | let mut expected = BTreeMap::new(); 539 | expected.insert("spam", vec!["a".as_bytes(), "b".as_bytes()]); 540 | assert_eq!(d, expected); 541 | Ok(()) 542 | } 543 | 544 | #[test] 545 | fn test_deserialize_dict_3() -> Result<()> { 546 | let mut m = BTreeMap::new(); 547 | m.insert( 548 | ByteString::from(String::from("spam")), 549 | Value::List(vec![ 550 | Value::ByteStr(ByteString::from(String::from("a"))), 551 | Value::ByteStr(ByteString::from(String::from("b"))), 552 | ]), 553 | ); 554 | let d = Value::Dict(m); 555 | let d: BTreeMap = from_value(d)?; 556 | 557 | let mut expected = BTreeMap::new(); 558 | expected.insert( 559 | String::from("spam"), 560 | Value::List(vec![ 561 | Value::ByteStr(ByteString::from(String::from("a"))), 562 | Value::ByteStr(ByteString::from(String::from("b"))), 563 | ]), 564 | ); 565 | assert_eq!(d, expected); 566 | Ok(()) 567 | } 568 | 569 | #[test] 570 | fn test_deserialize_dict_4() -> Result<()> { 571 | let mut m = BTreeMap::new(); 572 | m.insert( 573 | ByteString::from(String::from("spam")), 574 | Value::List(vec![ 575 | Value::ByteStr(ByteString::from(String::from("a"))), 576 | Value::ByteStr(ByteString::from(String::from("b"))), 577 | ]), 578 | ); 579 | let d = Value::Dict(m); 580 | let d: BTreeMap> = from_value(d)?; 581 | 582 | let mut expected = BTreeMap::new(); 583 | expected.insert( 584 | String::from("spam"), 585 | vec![ 586 | Value::ByteStr(ByteString::from(String::from("a"))), 587 | Value::ByteStr(ByteString::from(String::from("b"))), 588 | ], 589 | ); 590 | assert_eq!(d, expected); 591 | Ok(()) 592 | } 593 | } 594 | -------------------------------------------------------------------------------- /src/value/ser.rs: -------------------------------------------------------------------------------- 1 | //! Serializes into a [Value]. 2 | 3 | use super::{Number, Value}; 4 | use crate::{ 5 | error::{Error, ErrorKind, Result}, 6 | ByteString, 7 | }; 8 | use serde::{ser, Serialize}; 9 | 10 | #[cfg(all(feature = "alloc", not(feature = "std")))] 11 | use alloc::{collections::BTreeMap, vec::Vec}; 12 | #[cfg(feature = "std")] 13 | use std::{collections::BTreeMap, vec::Vec}; 14 | 15 | pub(super) struct Serializer; 16 | 17 | impl ser::Serializer for Serializer { 18 | type Ok = Value; 19 | type Error = Error; 20 | 21 | type SerializeSeq = SerializeList; 22 | type SerializeTuple = ser::Impossible; 23 | type SerializeTupleStruct = ser::Impossible; 24 | type SerializeTupleVariant = ser::Impossible; 25 | type SerializeMap = SerializeDict; 26 | type SerializeStruct = SerializeDict; 27 | type SerializeStructVariant = ser::Impossible; 28 | 29 | #[inline] 30 | fn serialize_bool(self, _value: bool) -> Result { 31 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 32 | } 33 | 34 | #[inline] 35 | fn serialize_i8(self, value: i8) -> Result { 36 | self.serialize_i64(i64::from(value)) 37 | } 38 | 39 | #[inline] 40 | fn serialize_i16(self, value: i16) -> Result { 41 | self.serialize_i64(i64::from(value)) 42 | } 43 | 44 | #[inline] 45 | fn serialize_i32(self, value: i32) -> Result { 46 | self.serialize_i64(i64::from(value)) 47 | } 48 | 49 | #[inline] 50 | fn serialize_i64(self, value: i64) -> Result { 51 | Ok(Value::Int(Number::Signed(value))) 52 | } 53 | 54 | #[inline] 55 | fn serialize_u8(self, value: u8) -> Result { 56 | self.serialize_u64(u64::from(value)) 57 | } 58 | 59 | #[inline] 60 | fn serialize_u16(self, value: u16) -> Result { 61 | self.serialize_u64(u64::from(value)) 62 | } 63 | 64 | #[inline] 65 | fn serialize_u32(self, value: u32) -> Result { 66 | self.serialize_u64(u64::from(value)) 67 | } 68 | 69 | #[inline] 70 | fn serialize_u64(self, value: u64) -> Result { 71 | Ok(Value::Int(Number::Unsigned(value))) 72 | } 73 | 74 | #[inline] 75 | fn serialize_f32(self, _value: f32) -> Result { 76 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 77 | } 78 | 79 | #[inline] 80 | fn serialize_f64(self, _value: f64) -> Result { 81 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 82 | } 83 | 84 | #[inline] 85 | fn serialize_char(self, value: char) -> Result { 86 | let mut buf = [0; 4]; 87 | self.serialize_str(value.encode_utf8(&mut buf)) 88 | } 89 | 90 | #[inline] 91 | fn serialize_str(self, value: &str) -> Result { 92 | Ok(Value::ByteStr(ByteString::from(value))) 93 | } 94 | 95 | #[inline] 96 | fn serialize_bytes(self, value: &[u8]) -> Result { 97 | Ok(Value::ByteStr(ByteString::from(value))) 98 | } 99 | 100 | #[inline] 101 | fn serialize_none(self) -> Result { 102 | self.serialize_unit() 103 | } 104 | 105 | #[inline] 106 | fn serialize_some(self, value: &T) -> Result 107 | where 108 | T: ?Sized + Serialize, 109 | { 110 | value.serialize(self) 111 | } 112 | 113 | #[inline] 114 | fn serialize_unit(self) -> Result { 115 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 116 | } 117 | 118 | #[inline] 119 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 120 | self.serialize_unit() 121 | } 122 | 123 | #[inline] 124 | fn serialize_unit_variant( 125 | self, 126 | _name: &'static str, 127 | _variant_index: u32, 128 | _variant: &'static str, 129 | ) -> Result { 130 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 131 | } 132 | 133 | #[inline] 134 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result 135 | where 136 | T: ?Sized + Serialize, 137 | { 138 | value.serialize(self) 139 | } 140 | 141 | #[inline] 142 | fn serialize_newtype_variant( 143 | self, 144 | _name: &'static str, 145 | _variant_index: u32, 146 | _variant: &'static str, 147 | _value: &T, 148 | ) -> Result 149 | where 150 | T: ?Sized + Serialize, 151 | { 152 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 153 | } 154 | 155 | #[inline] 156 | fn serialize_seq(self, len: Option) -> Result { 157 | Ok(SerializeList { 158 | list: Vec::with_capacity(len.unwrap_or(0)), 159 | }) 160 | } 161 | 162 | #[inline] 163 | fn serialize_tuple(self, _len: usize) -> Result { 164 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 165 | } 166 | 167 | #[inline] 168 | fn serialize_tuple_struct( 169 | self, 170 | _name: &'static str, 171 | _len: usize, 172 | ) -> Result { 173 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 174 | } 175 | 176 | #[inline] 177 | fn serialize_tuple_variant( 178 | self, 179 | _name: &'static str, 180 | _variant_index: u32, 181 | _variant: &'static str, 182 | _len: usize, 183 | ) -> Result { 184 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 185 | } 186 | 187 | #[inline] 188 | fn serialize_map(self, _len: Option) -> Result { 189 | Ok(SerializeDict { 190 | dict: BTreeMap::new(), 191 | current_key: None, 192 | }) 193 | } 194 | 195 | #[inline] 196 | fn serialize_struct(self, _name: &'static str, len: usize) -> Result { 197 | self.serialize_map(Some(len)) 198 | } 199 | 200 | #[inline] 201 | fn serialize_struct_variant( 202 | self, 203 | _name: &'static str, 204 | _variant_index: u32, 205 | _variant: &'static str, 206 | _len: usize, 207 | ) -> Result { 208 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 209 | } 210 | 211 | fn is_human_readable(&self) -> bool { 212 | false 213 | } 214 | } 215 | 216 | pub(super) struct SerializeList { 217 | list: Vec, 218 | } 219 | 220 | impl ser::SerializeSeq for SerializeList { 221 | type Ok = Value; 222 | type Error = Error; 223 | 224 | #[inline] 225 | fn serialize_element(&mut self, value: &T) -> Result<()> 226 | where 227 | T: ?Sized + Serialize, 228 | { 229 | self.list.push(super::to_value(value)?); 230 | Ok(()) 231 | } 232 | 233 | #[inline] 234 | fn end(self) -> Result { 235 | Ok(Value::List(self.list)) 236 | } 237 | } 238 | 239 | pub(super) struct SerializeDict { 240 | dict: BTreeMap, 241 | current_key: Option, 242 | } 243 | 244 | impl ser::SerializeMap for SerializeDict { 245 | type Ok = Value; 246 | type Error = Error; 247 | 248 | #[inline] 249 | fn serialize_key(&mut self, key: &T) -> Result<()> 250 | where 251 | T: ?Sized + Serialize, 252 | { 253 | if self.current_key.is_some() { 254 | return Err(Error::with_kind(ErrorKind::KeyWithoutValue)); 255 | } 256 | self.current_key = Some(key.serialize(&mut DictKeySerializer)?); 257 | Ok(()) 258 | } 259 | 260 | #[inline] 261 | fn serialize_value(&mut self, value: &T) -> Result<()> 262 | where 263 | T: ?Sized + Serialize, 264 | { 265 | let key = self 266 | .current_key 267 | .take() 268 | .ok_or_else(|| Error::with_kind(ErrorKind::ValueWithoutKey))?; 269 | let value = super::to_value(value)?; 270 | self.dict.insert(key, value); 271 | Ok(()) 272 | } 273 | 274 | #[inline] 275 | fn end(self) -> Result { 276 | Ok(Value::Dict(self.dict)) 277 | } 278 | } 279 | 280 | impl ser::SerializeStruct for SerializeDict { 281 | type Ok = Value; 282 | type Error = Error; 283 | 284 | #[inline] 285 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 286 | where 287 | T: ?Sized + Serialize, 288 | { 289 | let key = key.serialize(&mut DictKeySerializer)?; 290 | let value = super::to_value(value)?; 291 | self.dict.insert(key, value); 292 | Ok(()) 293 | } 294 | 295 | #[inline] 296 | fn end(self) -> Result { 297 | Ok(Value::Dict(self.dict)) 298 | } 299 | } 300 | 301 | struct DictKeySerializer; 302 | 303 | impl ser::Serializer for &mut DictKeySerializer { 304 | type Ok = ByteString; 305 | type Error = Error; 306 | 307 | type SerializeSeq = ser::Impossible; 308 | type SerializeTuple = ser::Impossible; 309 | type SerializeTupleStruct = ser::Impossible; 310 | type SerializeTupleVariant = ser::Impossible; 311 | type SerializeMap = ser::Impossible; 312 | type SerializeStruct = ser::Impossible; 313 | type SerializeStructVariant = ser::Impossible; 314 | 315 | fn serialize_bool(self, _value: bool) -> Result { 316 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 317 | } 318 | 319 | fn serialize_i8(self, _value: i8) -> Result { 320 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 321 | } 322 | 323 | fn serialize_i16(self, _value: i16) -> Result { 324 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 325 | } 326 | 327 | fn serialize_i32(self, _value: i32) -> Result { 328 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 329 | } 330 | 331 | fn serialize_i64(self, _value: i64) -> Result { 332 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 333 | } 334 | 335 | fn serialize_u8(self, _value: u8) -> Result { 336 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 337 | } 338 | 339 | fn serialize_u16(self, _value: u16) -> Result { 340 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 341 | } 342 | 343 | fn serialize_u32(self, _value: u32) -> Result { 344 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 345 | } 346 | 347 | fn serialize_u64(self, _value: u64) -> Result { 348 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 349 | } 350 | 351 | fn serialize_f32(self, _value: f32) -> Result { 352 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 353 | } 354 | 355 | fn serialize_f64(self, _value: f64) -> Result { 356 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 357 | } 358 | 359 | fn serialize_char(self, value: char) -> Result { 360 | let mut buf = [0; 4]; 361 | self.serialize_str(value.encode_utf8(&mut buf)) 362 | } 363 | 364 | fn serialize_str(self, value: &str) -> Result { 365 | Ok(ByteString::from(value)) 366 | } 367 | 368 | fn serialize_bytes(self, value: &[u8]) -> Result { 369 | Ok(ByteString::from(value)) 370 | } 371 | 372 | fn serialize_unit(self) -> Result { 373 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 374 | } 375 | 376 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 377 | self.serialize_unit() 378 | } 379 | 380 | fn serialize_unit_variant( 381 | self, 382 | _name: &'static str, 383 | _variant_index: u32, 384 | _variant: &'static str, 385 | ) -> Result { 386 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 387 | } 388 | 389 | fn serialize_newtype_struct( 390 | self, 391 | _name: &'static str, 392 | _value: &T, 393 | ) -> Result { 394 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 395 | } 396 | 397 | fn serialize_newtype_variant( 398 | self, 399 | _name: &'static str, 400 | _variant_index: u32, 401 | _variant: &'static str, 402 | _value: &T, 403 | ) -> Result { 404 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 405 | } 406 | 407 | fn serialize_none(self) -> Result { 408 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 409 | } 410 | 411 | fn serialize_some(self, _value: &T) -> Result { 412 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 413 | } 414 | 415 | fn serialize_seq(self, _len: Option) -> Result> { 416 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 417 | } 418 | 419 | fn serialize_tuple(self, _size: usize) -> Result> { 420 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 421 | } 422 | 423 | fn serialize_tuple_struct( 424 | self, 425 | _name: &'static str, 426 | _len: usize, 427 | ) -> Result> { 428 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 429 | } 430 | 431 | fn serialize_tuple_variant( 432 | self, 433 | _name: &'static str, 434 | _variant_index: u32, 435 | _variant: &'static str, 436 | _len: usize, 437 | ) -> Result> { 438 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 439 | } 440 | 441 | fn serialize_map(self, _len: Option) -> Result> { 442 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 443 | } 444 | 445 | fn serialize_struct( 446 | self, 447 | _name: &'static str, 448 | _len: usize, 449 | ) -> Result> { 450 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 451 | } 452 | 453 | fn serialize_struct_variant( 454 | self, 455 | _name: &'static str, 456 | _variant_index: u32, 457 | _variant: &'static str, 458 | _len: usize, 459 | ) -> Result> { 460 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 461 | } 462 | } 463 | 464 | #[cfg(test)] 465 | mod tests { 466 | use super::*; 467 | use crate::to_value; 468 | 469 | #[cfg(all(feature = "alloc", not(feature = "std")))] 470 | use alloc::{string::String, vec}; 471 | #[cfg(feature = "std")] 472 | use std::{string::String, vec}; 473 | 474 | macro_rules! assert_is_unsupported_type { 475 | ($e:expr) => { 476 | match $e { 477 | Ok(_) => unreachable!(), 478 | Err(error) => match error.kind() { 479 | ErrorKind::UnsupportedType => {} 480 | _ => panic!("wrong error type"), 481 | }, 482 | } 483 | }; 484 | } 485 | 486 | #[test] 487 | fn test_serialize_bool() { 488 | assert_is_unsupported_type!(to_value(&true)); 489 | } 490 | 491 | #[test] 492 | fn test_serialize_isize() { 493 | let value: isize = 2; 494 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 495 | let value: isize = -2; 496 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(-2))); 497 | } 498 | 499 | #[test] 500 | fn test_serialize_i8() { 501 | let value: i8 = 2; 502 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 503 | let value: i8 = -2; 504 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(-2))); 505 | } 506 | 507 | #[test] 508 | fn test_serialize_i16() { 509 | let value: i16 = 2; 510 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 511 | let value: i16 = -2; 512 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(-2))); 513 | } 514 | 515 | #[test] 516 | fn test_serialize_i32() { 517 | let value: i32 = 2; 518 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 519 | let value: i32 = -2; 520 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(-2))); 521 | } 522 | 523 | #[test] 524 | fn test_serialize_i64() { 525 | let value: i64 = 2; 526 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 527 | let value: i64 = -2; 528 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(-2))); 529 | } 530 | 531 | #[test] 532 | fn test_serialize_usize() { 533 | let value: usize = 2; 534 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Unsigned(2))); 535 | } 536 | 537 | #[test] 538 | fn test_serialize_u8() { 539 | let value: u8 = 2; 540 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Unsigned(2))); 541 | } 542 | 543 | #[test] 544 | fn test_serialize_u16() { 545 | let value: u16 = 2; 546 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Unsigned(2))); 547 | } 548 | 549 | #[test] 550 | fn test_serialize_u32() { 551 | let value: u32 = 2; 552 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Unsigned(2))); 553 | } 554 | 555 | #[test] 556 | fn test_serialize_u64() { 557 | let value: u64 = 2; 558 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Unsigned(2))); 559 | } 560 | 561 | #[test] 562 | fn test_serialize_u64_greater_than_i64_max() { 563 | let value: u64 = (i64::max_value() as u64) + 1; 564 | assert_eq!( 565 | to_value(&value).unwrap(), 566 | Value::Int(Number::Unsigned(value)) 567 | ); 568 | } 569 | 570 | #[test] 571 | fn test_serialize_f32() { 572 | let value: f32 = 2.0; 573 | assert_is_unsupported_type!(to_value(&value)); 574 | } 575 | 576 | #[test] 577 | fn test_serialize_f64() { 578 | let value: f64 = 2.0; 579 | assert_is_unsupported_type!(to_value(&value)); 580 | } 581 | 582 | #[test] 583 | fn test_serialize_char() { 584 | let value: char = 'a'; 585 | assert_eq!( 586 | to_value(&value).unwrap(), 587 | Value::ByteStr(ByteString::from("a")) 588 | ); 589 | } 590 | 591 | #[test] 592 | fn test_serialize_str() { 593 | let value: &str = "Hello world!"; 594 | assert_eq!( 595 | to_value(&value).unwrap(), 596 | Value::ByteStr(ByteString::from(value)) 597 | ); 598 | } 599 | 600 | #[test] 601 | fn test_serialize_empty_str() { 602 | let value: &str = ""; 603 | assert_eq!( 604 | to_value(&value).unwrap(), 605 | Value::ByteStr(ByteString::from(value)) 606 | ); 607 | } 608 | 609 | #[test] 610 | fn test_serialize_bytes() { 611 | let value = ByteString::from(String::from("123").into_bytes()); 612 | assert_eq!(to_value(&&value).unwrap(), Value::ByteStr(value)); 613 | } 614 | 615 | #[test] 616 | fn test_serialize_unit() { 617 | assert_is_unsupported_type!(to_value(&())); 618 | } 619 | 620 | #[test] 621 | fn test_serialize_none() { 622 | let value: Option = None; 623 | assert_is_unsupported_type!(to_value(&value)); 624 | } 625 | 626 | #[test] 627 | fn test_serialize_some() { 628 | let value: Option = Some(2); 629 | assert_eq!(to_value(&value).unwrap(), Value::Int(Number::Signed(2))); 630 | } 631 | 632 | #[test] 633 | fn test_serialize_unit_struct() { 634 | use serde::Serializer; 635 | 636 | assert_is_unsupported_type!(Serializer.serialize_unit_struct("Nothing")); 637 | } 638 | 639 | #[test] 640 | fn test_serialize_unit_variant() { 641 | use serde::Serializer; 642 | 643 | assert_is_unsupported_type!(Serializer.serialize_unit_variant("Nothing", 0, "Case")); 644 | } 645 | 646 | #[test] 647 | fn test_serialize_newtype_struct() { 648 | use serde::Serializer; 649 | 650 | Serializer.serialize_newtype_struct("Nothing", &2).unwrap(); 651 | } 652 | 653 | #[test] 654 | fn test_serialize_newtype_variant() { 655 | use serde::Serializer; 656 | 657 | assert_is_unsupported_type!(Serializer.serialize_unit_variant("Nothing", 0, "Case")); 658 | } 659 | 660 | #[test] 661 | fn test_serialize_seq() { 662 | let value: Vec = vec![1, 2, 3]; 663 | assert_eq!( 664 | to_value(&&value).unwrap(), 665 | Value::List(vec![ 666 | Value::Int(Number::Unsigned(1)), 667 | Value::Int(Number::Unsigned(2)), 668 | Value::Int(Number::Unsigned(3)), 669 | ]) 670 | ); 671 | } 672 | 673 | #[test] 674 | fn test_serialize_seq_empty() { 675 | let value: Vec = vec![]; 676 | assert_eq!(to_value(&&value).unwrap(), Value::List(Vec::new())); 677 | } 678 | 679 | #[test] 680 | fn test_serialize_tuple() { 681 | use serde::Serializer; 682 | 683 | assert_is_unsupported_type!(Serializer.serialize_tuple(0)); 684 | } 685 | 686 | #[test] 687 | fn test_serialize_tuple_struct() { 688 | use serde::Serializer; 689 | 690 | assert_is_unsupported_type!(Serializer.serialize_tuple_struct("Tuple Struct", 2)); 691 | } 692 | 693 | #[test] 694 | fn test_serialize_tuple_variant() { 695 | use serde::Serializer; 696 | 697 | assert_is_unsupported_type!(Serializer.serialize_tuple_variant( 698 | "Tuple Variant", 699 | 2, 700 | "Case", 701 | 1 702 | )); 703 | } 704 | 705 | #[test] 706 | fn test_serialize_struct_variant() { 707 | use serde::Serializer; 708 | 709 | assert_is_unsupported_type!(Serializer.serialize_struct_variant( 710 | "Struct Variant", 711 | 2, 712 | "Case", 713 | 1 714 | )); 715 | } 716 | 717 | #[test] 718 | fn test_serialize_struct() { 719 | use serde_derive::Serialize; 720 | 721 | #[derive(Serialize)] 722 | struct Test { 723 | int: u32, 724 | s: String, 725 | } 726 | 727 | let test = Test { 728 | int: 3, 729 | s: String::from("Hello, World!"), 730 | }; 731 | let mut expected = BTreeMap::new(); 732 | expected.insert( 733 | ByteString::from(String::from("int")), 734 | Value::Int(Number::Unsigned(3)), 735 | ); 736 | expected.insert( 737 | ByteString::from(String::from("s")), 738 | Value::ByteStr(ByteString::from(String::from("Hello, World!"))), 739 | ); 740 | 741 | assert_eq!(to_value(&test).unwrap(), Value::Dict(expected)); 742 | } 743 | } 744 | -------------------------------------------------------------------------------- /src/read.rs: -------------------------------------------------------------------------------- 1 | //! [Read] trait and helpers to read bytes for the deserializer. 2 | 3 | use crate::error::{Error, ErrorKind, Result}; 4 | use core::ops::Deref; 5 | 6 | #[cfg(all(feature = "alloc", not(feature = "std")))] 7 | use alloc::vec::Vec; 8 | 9 | #[cfg(feature = "std")] 10 | use std::{io, vec::Vec}; 11 | 12 | /// A reference to borrowed data. 13 | /// 14 | /// The variant determines if the slice comes from a long lived source (e.g. an 15 | /// existing byte array) or if it comes from a temporary buffer. 16 | /// 17 | /// In the deserializer code, the different variants determine which visitor 18 | /// method to call (e.g. `visit_borrowed_str` vs. `visit_str`). Each variant 19 | /// has a different lifetime which is what the compiler uses to ensure the data 20 | /// will live long enough. 21 | #[derive(Debug)] 22 | pub enum Ref<'a, 'b, T> 23 | where 24 | T: 'static + ?Sized, 25 | { 26 | /// Reference from the original source of data. 27 | Source(&'a T), 28 | /// Reference from the given data buffer. 29 | Buffer(&'b T), 30 | } 31 | 32 | impl Deref for Ref<'_, '_, T> 33 | where 34 | T: 'static + ?Sized, 35 | { 36 | type Target = T; 37 | 38 | fn deref(&self) -> &Self::Target { 39 | match *self { 40 | Ref::Source(s) => s, 41 | Ref::Buffer(b) => b, 42 | } 43 | } 44 | } 45 | 46 | /// Trait used by the [`de::Deserializer`][crate::de::Deserializer] to read bytes. 47 | pub trait Read<'a> { 48 | /// Consumes and returns the next read byte. 49 | fn next(&mut self) -> Option>; 50 | 51 | /// Returns the next byte but does not consume. 52 | /// 53 | /// Repeated peeks (with no [`next()`][Read::next] call) should return the same byte. 54 | fn peek(&mut self) -> Option>; 55 | 56 | /// Returns the position in the stream of bytes. 57 | fn byte_offset(&self) -> usize; 58 | 59 | /// Returns the next slice of data for the given length. 60 | /// 61 | /// If all of the data is already read and available to borrowed against, 62 | /// the returned result could be a reference to the original underlying 63 | /// data. 64 | /// 65 | /// If the data is not already available and needs to be buffered, the data 66 | /// could be added to the given buffer parameter and a borrowed slice from 67 | /// the buffer could be returned. 68 | /// 69 | /// # Errors 70 | /// 71 | /// Errors include: 72 | /// 73 | /// - malformatted input 74 | /// - end of file 75 | fn parse_byte_str<'b>(&'b mut self, buf: &'b mut Vec) -> Result>; 76 | 77 | /// Consumes and returns the next integer raw encoding. 78 | /// 79 | /// The buffer can be used as a temporary buffer for storing any bytes which need to be read. 80 | /// The contents of the buffer is not guaranteed before or after the method is called. 81 | /// 82 | /// # Errors 83 | /// 84 | /// Errors include: 85 | /// 86 | /// - malformatted input 87 | /// - end of file 88 | fn parse_raw_integer<'b>(&'b mut self, buf: &'b mut Vec) -> Result>; 89 | 90 | /// Consumes and returns the next byte string raw encoding. 91 | /// 92 | /// The buffer can be used as a temporary buffer for storing any bytes which need to be read. 93 | /// The contents of the buffer is not guaranteed before or after the method is called. 94 | /// 95 | /// # Errors 96 | /// 97 | /// Errors include: 98 | /// 99 | /// - malformatted input 100 | /// - end of file 101 | fn parse_raw_byte_str<'b>(&mut self, buf: &'b mut Vec) -> Result>; 102 | 103 | /// Consumes and returns the next list raw encoding. 104 | /// 105 | /// The buffer can be used as a temporary buffer for storing any bytes which need to be read. 106 | /// The contents of the buffer is not guaranteed before or after the method is called. 107 | /// 108 | /// # Errors 109 | /// 110 | /// Errors include: 111 | /// 112 | /// - malformatted input 113 | /// - end of file 114 | fn parse_raw_list<'b>(&'b mut self, buf: &'b mut Vec) -> Result>; 115 | 116 | /// Consumes and returns the next dictionary raw encoding. 117 | /// 118 | /// The buffer can be used as a temporary buffer for storing any bytes which need to be read. 119 | /// The contents of the buffer is not guaranteed before or after the method is called. 120 | /// 121 | /// # Errors 122 | /// 123 | /// Errors include: 124 | /// 125 | /// - malformatted input 126 | /// - end of file 127 | fn parse_raw_dict<'b>(&'b mut self, buf: &'b mut Vec) -> Result>; 128 | } 129 | 130 | /// A wrapper to implement this crate's [Read] trait for [`std::io::Read`] trait implementations. 131 | #[cfg(feature = "std")] 132 | #[derive(Debug)] 133 | #[allow(clippy::module_name_repetitions)] 134 | pub struct IoRead 135 | where 136 | R: io::Read, 137 | { 138 | iter: io::Bytes, 139 | peeked_byte: Option, 140 | byte_offset: usize, 141 | } 142 | 143 | #[cfg(feature = "std")] 144 | impl IoRead 145 | where 146 | R: io::Read, 147 | { 148 | /// Instantiates a new reader. 149 | /// 150 | /// # Performance 151 | /// 152 | /// It is strongly recommended to use a [BufReader][std::io::BufReader] or a 153 | /// similar type (which buffers read data in-memory) as the `reader` 154 | /// argument. See `BufReader`'s documentation for more information. 155 | pub fn new(reader: R) -> Self { 156 | IoRead { 157 | iter: reader.bytes(), 158 | peeked_byte: None, 159 | byte_offset: 0, 160 | } 161 | } 162 | } 163 | 164 | #[cfg(feature = "std")] 165 | impl<'a, R> Read<'a> for IoRead 166 | where 167 | R: io::Read, 168 | { 169 | #[inline] 170 | fn next(&mut self) -> Option> { 171 | match self.peeked_byte.take() { 172 | Some(b) => { 173 | self.byte_offset += 1; 174 | Some(Ok(b)) 175 | } 176 | None => match self.iter.next() { 177 | Some(Ok(b)) => { 178 | self.byte_offset += 1; 179 | Some(Ok(b)) 180 | } 181 | Some(Err(err)) => Some(Err(Error::new(ErrorKind::Io(err), self.byte_offset()))), 182 | None => None, 183 | }, 184 | } 185 | } 186 | 187 | #[inline] 188 | fn peek(&mut self) -> Option> { 189 | match self.peeked_byte { 190 | Some(b) => Some(Ok(b)), 191 | None => match self.iter.next() { 192 | Some(Ok(b)) => { 193 | self.peeked_byte = Some(b); 194 | Some(Ok(b)) 195 | } 196 | Some(Err(err)) => Some(Err(Error::new(ErrorKind::Io(err), self.byte_offset()))), 197 | None => None, 198 | }, 199 | } 200 | } 201 | 202 | #[inline] 203 | fn byte_offset(&self) -> usize { 204 | self.byte_offset 205 | } 206 | 207 | fn parse_byte_str<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 208 | debug_assert!(buf.is_empty()); 209 | 210 | let mut len: usize = 0; 211 | loop { 212 | match self 213 | .next() 214 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 215 | { 216 | b':' => { 217 | break; 218 | } 219 | n @ b'0'..=b'9' => { 220 | len = len.checked_mul(10).ok_or_else(|| { 221 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 222 | })?; 223 | len = len.checked_add(usize::from(n - b'0')).ok_or_else(|| { 224 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 225 | })?; 226 | } 227 | _ => return Err(Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset())), 228 | } 229 | } 230 | 231 | buf.reserve(len); 232 | 233 | for _ in 0..len { 234 | buf.push(self.next().ok_or_else(|| { 235 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 236 | })??); 237 | } 238 | 239 | Ok(Ref::Buffer(&buf[..])) 240 | } 241 | 242 | fn parse_raw_integer<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 243 | let start_idx = buf.len(); 244 | buf.push( 245 | self.next() 246 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??, 247 | ); 248 | 249 | match self 250 | .peek() 251 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 252 | { 253 | b'-' => { 254 | buf.push(self.next().ok_or_else(|| { 255 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 256 | })??); 257 | } 258 | b'0'..=b'9' => {} 259 | _ => return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())), 260 | } 261 | 262 | match self 263 | .peek() 264 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 265 | { 266 | b'0'..=b'9' => {} 267 | _ => { 268 | return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())); 269 | } 270 | } 271 | 272 | loop { 273 | match self 274 | .next() 275 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 276 | { 277 | b'e' => { 278 | buf.push(b'e'); 279 | return Ok(Ref::Buffer(&buf[start_idx..])); 280 | } 281 | n @ b'0'..=b'9' => buf.push(n), 282 | _ => return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())), 283 | } 284 | } 285 | } 286 | 287 | fn parse_raw_byte_str<'b>(&mut self, buf: &'b mut Vec) -> Result> { 288 | let start_idx = buf.len(); 289 | let mut len: usize = 0; 290 | loop { 291 | match self 292 | .next() 293 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 294 | { 295 | b':' => { 296 | buf.push(b':'); 297 | break; 298 | } 299 | n @ b'0'..=b'9' => { 300 | buf.push(n); 301 | 302 | len = len.checked_mul(10).ok_or_else(|| { 303 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 304 | })?; 305 | len = len.checked_add(usize::from(n - b'0')).ok_or_else(|| { 306 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 307 | })?; 308 | } 309 | _ => return Err(Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset())), 310 | } 311 | } 312 | 313 | buf.reserve(len); 314 | for _ in 0..len { 315 | buf.push(self.next().ok_or_else(|| { 316 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 317 | })??); 318 | } 319 | Ok(Ref::Buffer(&buf[start_idx..])) 320 | } 321 | 322 | fn parse_raw_list<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 323 | let start_idx = buf.len(); 324 | buf.push( 325 | self.next() 326 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??, 327 | ); 328 | 329 | loop { 330 | match self 331 | .peek() 332 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 333 | { 334 | b'e' => { 335 | buf.push(self.next().ok_or_else(|| { 336 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 337 | })??); 338 | return Ok(Ref::Buffer(&buf[start_idx..])); 339 | } 340 | b'0'..=b'9' => { 341 | self.parse_raw_byte_str(buf)?; 342 | } 343 | b'i' => { 344 | self.parse_raw_integer(buf)?; 345 | } 346 | b'l' => { 347 | self.parse_raw_list(buf)?; 348 | } 349 | b'd' => { 350 | self.parse_raw_dict(buf)?; 351 | } 352 | _ => return Err(Error::new(ErrorKind::InvalidList, self.byte_offset())), 353 | } 354 | } 355 | } 356 | 357 | fn parse_raw_dict<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 358 | let start_idx = buf.len(); 359 | buf.push( 360 | self.next() 361 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??, 362 | ); 363 | 364 | loop { 365 | match self 366 | .peek() 367 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 368 | { 369 | b'0'..=b'9' => { 370 | self.parse_raw_byte_str(buf)?; 371 | } 372 | b'e' => { 373 | buf.push(self.next().ok_or_else(|| { 374 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 375 | })??); 376 | return Ok(Ref::Buffer(&buf[start_idx..])); 377 | } 378 | _ => { 379 | return Err(Error::new(ErrorKind::InvalidDict, self.byte_offset())); 380 | } 381 | } 382 | 383 | match self 384 | .peek() 385 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 386 | { 387 | b'0'..=b'9' => { 388 | self.parse_raw_byte_str(buf)?; 389 | } 390 | b'i' => { 391 | self.parse_raw_integer(buf)?; 392 | } 393 | b'l' => { 394 | self.parse_raw_list(buf)?; 395 | } 396 | b'd' => { 397 | self.parse_raw_dict(buf)?; 398 | } 399 | _ => { 400 | return Err(Error::new(ErrorKind::InvalidDict, self.byte_offset())); 401 | } 402 | } 403 | } 404 | } 405 | } 406 | 407 | /// A wrapper to implement this crate's [Read] trait for byte slices. 408 | #[derive(Debug)] 409 | #[allow(clippy::module_name_repetitions)] 410 | pub struct SliceRead<'a> { 411 | slice: &'a [u8], 412 | byte_offset: usize, 413 | } 414 | 415 | impl<'a> SliceRead<'a> { 416 | /// Instantiates a new reader. 417 | #[must_use] 418 | pub fn new(slice: &'a [u8]) -> Self { 419 | SliceRead { 420 | slice, 421 | byte_offset: 0, 422 | } 423 | } 424 | } 425 | 426 | impl<'a> Read<'a> for SliceRead<'a> { 427 | #[inline] 428 | fn next(&mut self) -> Option> { 429 | if self.byte_offset < self.slice.len() { 430 | let b = self.slice[self.byte_offset]; 431 | self.byte_offset += 1; 432 | Some(Ok(b)) 433 | } else { 434 | None 435 | } 436 | } 437 | 438 | #[inline] 439 | fn peek(&mut self) -> Option> { 440 | if self.byte_offset < self.slice.len() { 441 | Some(Ok(self.slice[self.byte_offset])) 442 | } else { 443 | None 444 | } 445 | } 446 | 447 | #[inline] 448 | fn byte_offset(&self) -> usize { 449 | self.byte_offset 450 | } 451 | 452 | #[inline] 453 | fn parse_byte_str<'b>(&'b mut self, _buf: &'b mut Vec) -> Result> { 454 | let mut len: usize = 0; 455 | loop { 456 | match self 457 | .next() 458 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 459 | { 460 | b':' => { 461 | break; 462 | } 463 | n @ b'0'..=b'9' => { 464 | len = len.checked_mul(10).ok_or_else(|| { 465 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 466 | })?; 467 | len = len.checked_add(usize::from(n - b'0')).ok_or_else(|| { 468 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 469 | })?; 470 | } 471 | _ => return Err(Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset())), 472 | } 473 | } 474 | 475 | let start_idx = self.byte_offset; 476 | self.byte_offset += len; 477 | 478 | let slice_len = self.slice.len(); 479 | if slice_len < self.byte_offset { 480 | self.byte_offset = slice_len; 481 | return Err(Error::new( 482 | ErrorKind::EofWhileParsingValue, 483 | self.byte_offset(), 484 | )); 485 | } 486 | 487 | Ok(Ref::Source(&self.slice[start_idx..self.byte_offset])) 488 | } 489 | 490 | fn parse_raw_integer<'b>(&'b mut self, _buf: &'b mut Vec) -> Result> { 491 | let start_idx = self.byte_offset; 492 | 493 | self.next() 494 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 495 | 496 | match self 497 | .peek() 498 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 499 | { 500 | b'-' => { 501 | self.next().ok_or_else(|| { 502 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 503 | })??; 504 | } 505 | b'0'..=b'9' => {} 506 | _ => return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())), 507 | } 508 | 509 | match self 510 | .peek() 511 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 512 | { 513 | b'0'..=b'9' => {} 514 | _ => { 515 | return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())); 516 | } 517 | } 518 | 519 | loop { 520 | match self 521 | .next() 522 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 523 | { 524 | b'e' => { 525 | return Ok(Ref::Source(&self.slice[start_idx..self.byte_offset])); 526 | } 527 | b'0'..=b'9' => {} 528 | _ => return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())), 529 | } 530 | } 531 | } 532 | 533 | fn parse_raw_byte_str<'b>(&mut self, _buf: &'b mut Vec) -> Result> { 534 | let start_idx = self.byte_offset; 535 | 536 | let mut len: usize = 0; 537 | loop { 538 | match self 539 | .next() 540 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 541 | { 542 | b':' => { 543 | break; 544 | } 545 | n @ b'0'..=b'9' => { 546 | len = len.checked_mul(10).ok_or_else(|| { 547 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 548 | })?; 549 | len = len.checked_add(usize::from(n - b'0')).ok_or_else(|| { 550 | Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset()) 551 | })?; 552 | } 553 | _ => return Err(Error::new(ErrorKind::InvalidByteStrLen, self.byte_offset())), 554 | } 555 | } 556 | self.byte_offset += len; 557 | 558 | let slice_len = self.slice.len(); 559 | if slice_len < self.byte_offset { 560 | self.byte_offset = slice_len; 561 | return Err(Error::new( 562 | ErrorKind::EofWhileParsingValue, 563 | self.byte_offset(), 564 | )); 565 | } 566 | 567 | Ok(Ref::Source(&self.slice[start_idx..self.byte_offset])) 568 | } 569 | 570 | fn parse_raw_list<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 571 | let start_idx = self.byte_offset; 572 | 573 | self.next() 574 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 575 | 576 | loop { 577 | match self 578 | .peek() 579 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 580 | { 581 | b'e' => { 582 | self.next().ok_or_else(|| { 583 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 584 | })??; 585 | return Ok(Ref::Source(&self.slice[start_idx..self.byte_offset])); 586 | } 587 | b'0'..=b'9' => { 588 | self.parse_raw_byte_str(buf)?; 589 | } 590 | b'i' => { 591 | self.parse_raw_integer(buf)?; 592 | } 593 | b'l' => { 594 | self.parse_raw_list(buf)?; 595 | } 596 | b'd' => { 597 | self.parse_raw_dict(buf)?; 598 | } 599 | _ => return Err(Error::new(ErrorKind::InvalidList, self.byte_offset())), 600 | } 601 | } 602 | } 603 | 604 | fn parse_raw_dict<'b>(&'b mut self, buf: &'b mut Vec) -> Result> { 605 | let start_idx = self.byte_offset; 606 | 607 | self.next() 608 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 609 | 610 | loop { 611 | match self 612 | .peek() 613 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 614 | { 615 | b'e' => { 616 | self.next().ok_or_else(|| { 617 | Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()) 618 | })??; 619 | return Ok(Ref::Source(&self.slice[start_idx..self.byte_offset])); 620 | } 621 | b'0'..=b'9' => { 622 | self.parse_raw_byte_str(buf)?; 623 | } 624 | _ => { 625 | return Err(Error::new(ErrorKind::InvalidDict, self.byte_offset())); 626 | } 627 | } 628 | 629 | match self 630 | .peek() 631 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 632 | { 633 | b'0'..=b'9' => { 634 | self.parse_raw_byte_str(buf)?; 635 | } 636 | b'i' => { 637 | self.parse_raw_integer(buf)?; 638 | } 639 | b'l' => { 640 | self.parse_raw_list(buf)?; 641 | } 642 | b'd' => { 643 | self.parse_raw_dict(buf)?; 644 | } 645 | _ => { 646 | return Err(Error::new(ErrorKind::InvalidDict, self.byte_offset())); 647 | } 648 | } 649 | } 650 | } 651 | } 652 | -------------------------------------------------------------------------------- /src/value.rs: -------------------------------------------------------------------------------- 1 | //! Represents valid Bencode data. 2 | 3 | use crate::{error::Error, ByteString}; 4 | use core::fmt::Display; 5 | use serde::{ 6 | de::{Deserialize, DeserializeOwned, MapAccess, SeqAccess, Visitor}, 7 | ser::Serialize, 8 | }; 9 | 10 | #[cfg(all(feature = "alloc", not(feature = "std")))] 11 | use alloc::{collections::BTreeMap, fmt, str, str::FromStr, string::String, vec::Vec}; 12 | 13 | #[cfg(feature = "std")] 14 | use std::{collections::BTreeMap, fmt, str, str::FromStr, string::String, vec::Vec}; 15 | 16 | /// Represents a valid Bencode number. 17 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 18 | pub enum Number { 19 | /// A signed integer. 20 | Signed(i64), 21 | /// An unsigned integer. 22 | Unsigned(u64), 23 | } 24 | 25 | impl Display for Number { 26 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 27 | match self { 28 | Number::Signed(arg0) => Display::fmt(arg0, f), 29 | Number::Unsigned(arg0) => Display::fmt(arg0, f), 30 | } 31 | } 32 | } 33 | 34 | impl From for Number { 35 | fn from(value: isize) -> Self { 36 | Number::Signed(value as i64) 37 | } 38 | } 39 | 40 | impl From for Number { 41 | fn from(value: i64) -> Self { 42 | Number::Signed(value) 43 | } 44 | } 45 | 46 | impl From for Number { 47 | fn from(value: i32) -> Self { 48 | Number::Signed(i64::from(value)) 49 | } 50 | } 51 | 52 | impl From for Number { 53 | fn from(value: i16) -> Self { 54 | Number::Signed(i64::from(value)) 55 | } 56 | } 57 | 58 | impl From for Number { 59 | fn from(value: i8) -> Self { 60 | Number::Signed(i64::from(value)) 61 | } 62 | } 63 | 64 | impl From for Number { 65 | fn from(value: usize) -> Self { 66 | Number::Unsigned(value as u64) 67 | } 68 | } 69 | 70 | impl From for Number { 71 | fn from(value: u64) -> Self { 72 | Number::Unsigned(value) 73 | } 74 | } 75 | 76 | impl From for Number { 77 | fn from(value: u32) -> Self { 78 | Number::Unsigned(u64::from(value)) 79 | } 80 | } 81 | 82 | impl From for Number { 83 | fn from(value: u16) -> Self { 84 | Number::Unsigned(u64::from(value)) 85 | } 86 | } 87 | 88 | impl From for Number { 89 | fn from(value: u8) -> Self { 90 | Number::Unsigned(u64::from(value)) 91 | } 92 | } 93 | 94 | /// Represents a valid Bencode value. 95 | /// 96 | /// It is useful when it is unknown what the data may contain (e.g. when different kinds of 97 | /// messages can be received in a network packet). 98 | #[derive(Clone, PartialEq)] 99 | pub enum Value { 100 | /// A byte string. 101 | /// 102 | /// Encoded strings can contain non-UTF-8 bytes, so a byte string is used to represent 103 | /// "strings". 104 | ByteStr(ByteString), 105 | /// An integer which can be signed or unsigned. 106 | Int(Number), 107 | /// A list of values. 108 | List(Vec), 109 | /// A dictionary of values. 110 | Dict(BTreeMap), 111 | } 112 | 113 | impl Value { 114 | /// If the value is a byte string, returns a reference to the underlying value. 115 | #[must_use] 116 | pub fn as_byte_str(&self) -> Option<&ByteString> { 117 | match self { 118 | Value::ByteStr(b) => Some(b), 119 | _ => None, 120 | } 121 | } 122 | 123 | /// If the value is a byte string, returns a mutable reference to the underlying value. 124 | #[must_use] 125 | pub fn as_byte_str_mut(&mut self) -> Option<&mut ByteString> { 126 | match self { 127 | Value::ByteStr(ref mut b) => Some(b), 128 | _ => None, 129 | } 130 | } 131 | 132 | /// If the value is a UTF-8 string, returns a reference to the underlying value. 133 | #[must_use] 134 | pub fn as_str(&self) -> Option<&str> { 135 | match self { 136 | Value::ByteStr(b) => str::from_utf8(b.as_slice()).ok(), 137 | _ => None, 138 | } 139 | } 140 | 141 | /// If the value is a UTF-8 string, returns a mutable reference to the underlying value. 142 | #[must_use] 143 | pub fn as_str_mut(&mut self) -> Option<&mut str> { 144 | match self { 145 | Value::ByteStr(ref mut b) => str::from_utf8_mut(b.as_mut_slice()).ok(), 146 | _ => None, 147 | } 148 | } 149 | 150 | /// If the value is a number, returns a reference to the underlying value. 151 | #[must_use] 152 | pub fn as_number(&self) -> Option<&Number> { 153 | match self { 154 | Value::Int(n) => Some(n), 155 | _ => None, 156 | } 157 | } 158 | 159 | /// If the value is a [u64], returns the underlying value. 160 | #[must_use] 161 | pub fn as_u64(&self) -> Option { 162 | match self { 163 | Value::Int(Number::Unsigned(n)) => Some(*n), 164 | _ => None, 165 | } 166 | } 167 | 168 | /// If the value is a [i64], returns the underlying value. 169 | #[must_use] 170 | pub fn as_i64(&self) -> Option { 171 | match self { 172 | Value::Int(Number::Signed(n)) => Some(*n), 173 | _ => None, 174 | } 175 | } 176 | 177 | /// If the value is a list, returns a reference to the underlying value. 178 | #[must_use] 179 | pub fn as_list(&self) -> Option<&Vec> { 180 | match self { 181 | Value::List(ref l) => Some(l), 182 | _ => None, 183 | } 184 | } 185 | 186 | /// If the value is a list, returns a mutable reference to the underlying value. 187 | #[must_use] 188 | pub fn as_list_mut(&mut self) -> Option<&mut Vec> { 189 | match self { 190 | Value::List(ref mut l) => Some(l), 191 | _ => None, 192 | } 193 | } 194 | 195 | /// If the value is a list, returns a reference to the underlying value. 196 | /// 197 | /// Alternative method name for [Value::as_list()]. 198 | #[inline] 199 | #[must_use] 200 | pub fn as_array(&self) -> Option<&Vec> { 201 | self.as_list() 202 | } 203 | 204 | /// If the value is a list, returns a mutable reference to the underlying value. 205 | /// 206 | /// Alternative method name for [Value::as_list_mut()]. 207 | #[inline] 208 | #[must_use] 209 | pub fn as_array_mut(&mut self) -> Option<&mut Vec> { 210 | self.as_list_mut() 211 | } 212 | 213 | /// If the value is a dictionary, returns a reference to the underlying value. 214 | #[must_use] 215 | pub fn as_dict(&self) -> Option<&BTreeMap> { 216 | match self { 217 | Value::Dict(d) => Some(d), 218 | _ => None, 219 | } 220 | } 221 | 222 | /// If the value is a dictionary, returns a mutable reference to the underlying value. 223 | #[must_use] 224 | pub fn as_dict_mut(&mut self) -> Option<&mut BTreeMap> { 225 | match self { 226 | Value::Dict(ref mut d) => Some(d), 227 | _ => None, 228 | } 229 | } 230 | 231 | /// Returns true if the value is a byte string. 232 | #[must_use] 233 | pub fn is_byte_str(&self) -> bool { 234 | self.as_byte_str().is_some() 235 | } 236 | 237 | /// Returns true if the value is a UTF-8 string. 238 | /// 239 | /// Note that the value could be a byte string but not a UTF-8 string. 240 | #[must_use] 241 | pub fn is_string(&self) -> bool { 242 | self.as_str().is_some() 243 | } 244 | 245 | /// Returns true if the value is a an [u64]. 246 | /// 247 | /// Note that the value could be a [i64]. 248 | #[must_use] 249 | pub fn is_u64(&self) -> bool { 250 | self.as_u64().is_some() 251 | } 252 | 253 | /// Returns true if the value is a an [i64]. 254 | /// 255 | /// Note that the value could be a [u64]. 256 | #[must_use] 257 | pub fn is_i64(&self) -> bool { 258 | self.as_i64().is_some() 259 | } 260 | 261 | /// Returns true if the value is a list. 262 | #[must_use] 263 | pub fn is_list(&self) -> bool { 264 | self.as_list().is_some() 265 | } 266 | 267 | /// Returns true if the value is a list. 268 | /// 269 | /// Alternative method name for [Value::is_list()]. 270 | #[must_use] 271 | pub fn is_array(&self) -> bool { 272 | self.is_list() 273 | } 274 | 275 | /// Returns true if the value is a dictionary. 276 | #[must_use] 277 | pub fn is_dict(&self) -> bool { 278 | self.as_dict().is_some() 279 | } 280 | } 281 | 282 | impl fmt::Debug for Value { 283 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 284 | struct DebugByteStr<'a>(&'a ByteString); 285 | 286 | impl fmt::Debug for DebugByteStr<'_> { 287 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 288 | match core::str::from_utf8(self.0) { 289 | Ok(key) => f.debug_tuple("ByteStr").field(&key).finish(), 290 | Err(_) => f.debug_tuple("ByteStr").field(&self.0).finish(), 291 | } 292 | } 293 | } 294 | 295 | match self { 296 | Value::ByteStr(arg0) => fmt::Debug::fmt(&DebugByteStr(arg0), f), 297 | Value::Int(arg0) => f.debug_tuple("Int").field(arg0).finish(), 298 | Value::List(arg0) => f.debug_tuple("List").field(arg0).finish(), 299 | Value::Dict(arg0) => { 300 | struct DebugDict<'a>(&'a BTreeMap); 301 | 302 | impl fmt::Debug for DebugDict<'_> { 303 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 304 | let mut d = &mut f.debug_map(); 305 | for (key, value) in self.0 { 306 | d = d.entry(&DebugByteStr(key), value); 307 | } 308 | d.finish() 309 | } 310 | } 311 | 312 | f.debug_tuple("Dict").field(&DebugDict(arg0)).finish() 313 | } 314 | } 315 | } 316 | } 317 | 318 | impl From for Value { 319 | fn from(other: i8) -> Value { 320 | Value::Int(Number::from(other)) 321 | } 322 | } 323 | 324 | impl From for Value { 325 | fn from(other: i16) -> Value { 326 | Value::Int(Number::from(other)) 327 | } 328 | } 329 | 330 | impl From for Value { 331 | fn from(other: i32) -> Value { 332 | Value::Int(Number::from(other)) 333 | } 334 | } 335 | 336 | impl From for Value { 337 | fn from(other: i64) -> Value { 338 | Value::Int(Number::from(other)) 339 | } 340 | } 341 | 342 | impl From for Value { 343 | fn from(other: isize) -> Value { 344 | Value::Int(Number::from(other)) 345 | } 346 | } 347 | 348 | impl From for Value { 349 | fn from(other: u8) -> Value { 350 | Value::Int(Number::from(other)) 351 | } 352 | } 353 | 354 | impl From for Value { 355 | fn from(other: u16) -> Value { 356 | Value::Int(Number::from(other)) 357 | } 358 | } 359 | 360 | impl From for Value { 361 | fn from(other: u32) -> Value { 362 | Value::Int(Number::from(other)) 363 | } 364 | } 365 | 366 | impl From for Value { 367 | fn from(other: u64) -> Value { 368 | Value::Int(Number::from(other)) 369 | } 370 | } 371 | 372 | impl From for Value { 373 | fn from(other: usize) -> Value { 374 | Value::Int(Number::from(other)) 375 | } 376 | } 377 | 378 | impl FromStr for Value { 379 | type Err = Error; 380 | 381 | fn from_str(s: &str) -> Result { 382 | Ok(Value::ByteStr(ByteString::from(String::from(s)))) 383 | } 384 | } 385 | 386 | impl<'a> From<&'a str> for Value { 387 | fn from(other: &'a str) -> Value { 388 | Value::ByteStr(ByteString::from(other)) 389 | } 390 | } 391 | 392 | impl From for Value { 393 | fn from(other: String) -> Value { 394 | Value::ByteStr(ByteString::from(other)) 395 | } 396 | } 397 | 398 | impl> From> for Value { 399 | fn from(other: Vec) -> Value { 400 | Value::List(other.into_iter().map(Into::into).collect()) 401 | } 402 | } 403 | 404 | impl, V: Into> From> for Value { 405 | fn from(other: BTreeMap) -> Value { 406 | Value::Dict( 407 | other 408 | .into_iter() 409 | .map(|(k, v)| (k.into(), v.into())) 410 | .collect(), 411 | ) 412 | } 413 | } 414 | 415 | impl<'de> Deserialize<'de> for Value { 416 | #[inline] 417 | fn deserialize(deserializer: T) -> Result 418 | where 419 | T: serde::Deserializer<'de>, 420 | { 421 | struct ValueVisitor; 422 | 423 | impl<'de> Visitor<'de> for ValueVisitor { 424 | type Value = Value; 425 | 426 | #[inline] 427 | fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 428 | f.write_str("any valid Bencode value") 429 | } 430 | 431 | #[inline] 432 | fn visit_i64(self, value: i64) -> Result { 433 | Ok(Value::Int(Number::Signed(value))) 434 | } 435 | 436 | #[inline] 437 | fn visit_u64(self, value: u64) -> Result { 438 | Ok(Value::Int(Number::Unsigned(value))) 439 | } 440 | 441 | #[inline] 442 | fn visit_str(self, value: &str) -> Result { 443 | Ok(Value::ByteStr(ByteString::from(String::from(value)))) 444 | } 445 | 446 | #[inline] 447 | fn visit_string(self, value: String) -> Result { 448 | Ok(Value::ByteStr(ByteString::from(value))) 449 | } 450 | 451 | #[inline] 452 | fn visit_bytes(self, value: &[u8]) -> Result { 453 | Ok(Value::ByteStr(ByteString::from(value))) 454 | } 455 | 456 | #[inline] 457 | fn visit_byte_buf(self, value: Vec) -> Result { 458 | Ok(Value::ByteStr(ByteString::from(value))) 459 | } 460 | 461 | #[inline] 462 | fn visit_some(self, deserializer: D) -> Result 463 | where 464 | D: serde::Deserializer<'de>, 465 | { 466 | Deserialize::deserialize(deserializer) 467 | } 468 | 469 | fn visit_seq(self, mut visitor: V) -> Result 470 | where 471 | V: SeqAccess<'de>, 472 | { 473 | let mut list = Vec::new(); 474 | if let Some(size_hint) = visitor.size_hint() { 475 | list.reserve(size_hint); 476 | } 477 | while let Some(elem) = visitor.next_element()? { 478 | list.push(elem); 479 | } 480 | Ok(Value::List(list)) 481 | } 482 | 483 | fn visit_map(self, mut visitor: V) -> Result 484 | where 485 | V: MapAccess<'de>, 486 | { 487 | let mut dict = BTreeMap::new(); 488 | while let Some((key, value)) = visitor.next_entry()? { 489 | dict.insert(key, value); 490 | } 491 | Ok(Value::Dict(dict)) 492 | } 493 | } 494 | 495 | deserializer.deserialize_any(ValueVisitor) 496 | } 497 | } 498 | 499 | impl Serialize for Value { 500 | fn serialize(&self, serializer: S) -> Result 501 | where 502 | S: serde::Serializer, 503 | { 504 | match self { 505 | Value::ByteStr(ref b) => b.serialize(serializer), 506 | Value::Int(i) => match i { 507 | Number::Signed(s) => s.serialize(serializer), 508 | Number::Unsigned(u) => u.serialize(serializer), 509 | }, 510 | Value::List(l) => l.serialize(serializer), 511 | Value::Dict(d) => d.serialize(serializer), 512 | } 513 | } 514 | } 515 | 516 | mod de; 517 | mod index; 518 | mod ser; 519 | 520 | pub use index::Index; 521 | 522 | impl Value { 523 | /// Used to get a reference to a value with an index. 524 | #[inline] 525 | pub fn get(&self, index: I) -> Option<&Value> { 526 | index.index(self) 527 | } 528 | 529 | /// Used to get a mutable reference to a value with an index. 530 | #[inline] 531 | pub fn get_mut(&mut self, index: I) -> Option<&mut Value> { 532 | index.index_mut(self) 533 | } 534 | } 535 | 536 | /// Deserializes an instance of `T` from a [Value]. 537 | /// 538 | /// # Errors 539 | /// 540 | /// Deserialization can fail if the data is not valid, if the data cannot cannot be deserialized 541 | /// into an instance of `T`, and other IO errors. 542 | #[allow(clippy::module_name_repetitions)] 543 | #[inline] 544 | pub fn from_value(value: Value) -> Result 545 | where 546 | T: DeserializeOwned, 547 | { 548 | T::deserialize(value) 549 | } 550 | 551 | /// Serializes an instance of `T` into a [Value]. 552 | /// 553 | /// # Errors 554 | /// 555 | /// Serialization can fail if `T`'s implementation of 556 | /// [`Serialize`] decides to fail, if `T` contains 557 | /// unsupported types for serialization, or if `T` contains a map with 558 | /// non-string keys. 559 | #[allow(clippy::module_name_repetitions)] 560 | #[inline] 561 | pub fn to_value(value: &T) -> Result 562 | where 563 | T: ?Sized + Serialize, 564 | { 565 | value.serialize(ser::Serializer) 566 | } 567 | 568 | #[cfg(test)] 569 | mod tests { 570 | use super::*; 571 | use crate::error::Result; 572 | 573 | #[cfg(all(feature = "alloc", not(feature = "std")))] 574 | use alloc::vec; 575 | #[cfg(feature = "std")] 576 | use std::vec; 577 | 578 | #[test] 579 | fn test_deserialize_string() -> Result<()> { 580 | let input = "4:spam"; 581 | let v: Value = crate::de::from_slice(input.as_bytes())?; 582 | assert_eq!(v, Value::ByteStr(ByteString::from(String::from("spam")))); 583 | Ok(()) 584 | } 585 | 586 | #[test] 587 | fn test_deserialize_integer_1() -> Result<()> { 588 | let input = "i3e"; 589 | let v: Value = crate::de::from_slice(input.as_bytes())?; 590 | assert_eq!(v, Value::Int(Number::Unsigned(3))); 591 | Ok(()) 592 | } 593 | 594 | #[test] 595 | fn test_deserialize_integer_2() -> Result<()> { 596 | let input = "i-3e"; 597 | let v: Value = crate::de::from_slice(input.as_bytes())?; 598 | assert_eq!(v, Value::Int(Number::Signed(-3))); 599 | Ok(()) 600 | } 601 | 602 | #[test] 603 | fn test_deserialize_integer_3() -> Result<()> { 604 | let input = "i0e"; 605 | let v: Value = crate::de::from_slice(input.as_bytes())?; 606 | assert_eq!(v, Value::Int(Number::Unsigned(0))); 607 | Ok(()) 608 | } 609 | 610 | #[test] 611 | fn test_deserialize_list() -> Result<()> { 612 | let input = "l4:spam4:eggse"; 613 | let v: Value = crate::de::from_slice(input.as_bytes())?; 614 | assert_eq!( 615 | v, 616 | Value::List(vec![ 617 | Value::ByteStr(ByteString::from(String::from("spam"))), 618 | Value::ByteStr(ByteString::from(String::from("eggs"))), 619 | ]) 620 | ); 621 | Ok(()) 622 | } 623 | 624 | #[test] 625 | fn test_deserialize_dict_1() -> Result<()> { 626 | let input = "d3:cow3:moo4:spam4:eggse"; 627 | let v: Value = crate::de::from_slice(input.as_bytes())?; 628 | 629 | let mut expected = BTreeMap::new(); 630 | expected.insert( 631 | ByteString::from(String::from("cow")), 632 | Value::ByteStr(ByteString::from(String::from("moo"))), 633 | ); 634 | expected.insert( 635 | ByteString::from(String::from("spam")), 636 | Value::ByteStr(ByteString::from(String::from("eggs"))), 637 | ); 638 | assert_eq!(v, Value::Dict(expected)); 639 | Ok(()) 640 | } 641 | 642 | #[test] 643 | fn test_deserialize_dict_2() -> Result<()> { 644 | let input = "d4:spaml1:a1:bee"; 645 | let v: Value = crate::de::from_slice(input.as_bytes())?; 646 | let mut expected = BTreeMap::new(); 647 | expected.insert( 648 | ByteString::from(String::from("spam")), 649 | Value::List(vec![ 650 | Value::ByteStr(ByteString::from(String::from("a"))), 651 | Value::ByteStr(ByteString::from(String::from("b"))), 652 | ]), 653 | ); 654 | assert_eq!(v, Value::Dict(expected)); 655 | Ok(()) 656 | } 657 | 658 | #[test] 659 | #[cfg(feature = "std")] 660 | fn test_serialize_string() -> Result<()> { 661 | let expected = "4:spam"; 662 | let v: Vec = 663 | crate::ser::to_vec(&Value::ByteStr(ByteString::from(String::from("spam"))))?; 664 | assert_eq!(v, expected.to_string().into_bytes()); 665 | Ok(()) 666 | } 667 | 668 | #[test] 669 | #[cfg(feature = "std")] 670 | fn test_serialize_integer_1() -> Result<()> { 671 | let expected = "i3e"; 672 | let v: Vec = crate::ser::to_vec(&Value::Int(Number::Unsigned(3)))?; 673 | assert_eq!(v, expected.to_string().into_bytes()); 674 | Ok(()) 675 | } 676 | 677 | #[test] 678 | #[cfg(feature = "std")] 679 | fn test_serialize_integer_2() -> Result<()> { 680 | let expected = "i-3e"; 681 | let v: Vec = crate::ser::to_vec(&Value::Int(Number::Signed(-3)))?; 682 | assert_eq!(v, expected.to_string().into_bytes()); 683 | Ok(()) 684 | } 685 | 686 | #[test] 687 | #[cfg(feature = "std")] 688 | fn test_serialize_integer_3() -> Result<()> { 689 | let expected = "i0e"; 690 | let v: Vec = crate::ser::to_vec(&Value::Int(Number::Unsigned(0)))?; 691 | assert_eq!(v, expected.to_string().into_bytes()); 692 | Ok(()) 693 | } 694 | 695 | #[test] 696 | #[cfg(feature = "std")] 697 | fn test_serialize_list() -> Result<()> { 698 | let expected = "l4:spam4:eggse"; 699 | let v: Vec = crate::ser::to_vec(&Value::List(vec![ 700 | Value::ByteStr(ByteString::from(String::from("spam"))), 701 | Value::ByteStr(ByteString::from(String::from("eggs"))), 702 | ]))?; 703 | assert_eq!(v, expected.to_string().into_bytes()); 704 | Ok(()) 705 | } 706 | 707 | #[test] 708 | #[cfg(feature = "std")] 709 | fn test_serialize_dict_1() -> Result<()> { 710 | let expected = "d3:cow3:moo4:spam4:eggse"; 711 | let mut dict = BTreeMap::new(); 712 | dict.insert( 713 | ByteString::from(String::from("cow")), 714 | Value::ByteStr(ByteString::from(String::from("moo"))), 715 | ); 716 | dict.insert( 717 | ByteString::from(String::from("spam")), 718 | Value::ByteStr(ByteString::from(String::from("eggs"))), 719 | ); 720 | let v: Vec = crate::ser::to_vec(&Value::Dict(dict))?; 721 | assert_eq!(v, expected.to_string().into_bytes()); 722 | Ok(()) 723 | } 724 | 725 | #[test] 726 | #[cfg(feature = "std")] 727 | fn test_serialize_dict_2() -> Result<()> { 728 | let expected = "d4:spaml1:a1:bee"; 729 | let mut dict = BTreeMap::new(); 730 | dict.insert( 731 | ByteString::from(String::from("spam")), 732 | Value::List(vec![ 733 | Value::ByteStr(ByteString::from(String::from("a"))), 734 | Value::ByteStr(ByteString::from(String::from("b"))), 735 | ]), 736 | ); 737 | let v: Vec = crate::ser::to_vec(&Value::Dict(dict))?; 738 | assert_eq!(v, expected.to_string().into_bytes()); 739 | Ok(()) 740 | } 741 | } 742 | -------------------------------------------------------------------------------- /src/de.rs: -------------------------------------------------------------------------------- 1 | //! Deserializes Bencode data. 2 | 3 | use crate::error::{Error, ErrorKind, Result}; 4 | use crate::read::{self, Read, Ref}; 5 | use serde::de::{self, Expected, Unexpected}; 6 | 7 | #[cfg(all(feature = "alloc", not(feature = "std")))] 8 | use alloc::vec::Vec; 9 | #[cfg(feature = "std")] 10 | use std::{io, vec::Vec}; 11 | 12 | /// Deserializes an instance of `T` from the bytes of an [`io::Read`] type. 13 | /// 14 | /// The entire [`io::Read`] source is consumed, and it is an error if there is 15 | /// trailing data. If trailing data is expected, then the [`Deserializer`] 16 | /// should be constructed directly. See [`Deserializer::byte_offset()`] for an 17 | /// example. 18 | /// 19 | /// # Errors 20 | /// 21 | /// Deserialization can fail if the data is not valid, if the data cannot be 22 | /// deserialized into an instance of `T`, if there is trailing data, and other 23 | /// IO errors. 24 | #[cfg(feature = "std")] 25 | pub fn from_reader(r: R) -> Result 26 | where 27 | R: io::Read, 28 | T: de::DeserializeOwned, 29 | { 30 | let mut de = Deserializer::new(read::IoRead::new(r)); 31 | let value = T::deserialize(&mut de)?; 32 | de.end()?; 33 | Ok(value) 34 | } 35 | 36 | /// Deserializes an instance of `T` from a slice of bytes. 37 | /// 38 | /// The entire slice of bytes is consumed, and it is an error if there is 39 | /// trailing data. If trailing data is expected, then the [`Deserializer`] 40 | /// should be constructed directly. See [`Deserializer::byte_offset()`] for an 41 | /// example. 42 | /// 43 | /// # Errors 44 | /// 45 | /// Deserialization can fail if the data is not valid, if the data cannot be 46 | /// deserialized into an instance of `T`, if there is trailing data, and other 47 | /// IO errors. 48 | pub fn from_slice<'a, T>(s: &'a [u8]) -> Result 49 | where 50 | T: de::Deserialize<'a>, 51 | { 52 | let mut de = Deserializer::new(read::SliceRead::new(s)); 53 | let value = T::deserialize(&mut de)?; 54 | de.end()?; 55 | Ok(value) 56 | } 57 | 58 | #[derive(Debug)] 59 | /// A `Bencode` Deserializer for types which implement [Deserialize][serde::de::Deserialize]. 60 | pub struct Deserializer { 61 | read: R, 62 | /// Temporary buffer used to reduce allocations made 63 | buf: Vec, 64 | } 65 | 66 | impl<'a, R> Deserializer 67 | where 68 | R: Read<'a>, 69 | { 70 | /// Constructs a Deserializer from a readable source. 71 | pub fn new(read: R) -> Self { 72 | Deserializer { 73 | read, 74 | buf: Vec::default(), 75 | } 76 | } 77 | 78 | /// Returns the byte offset in the underlying readable source. 79 | /// 80 | /// For most use cases, the entire source should be consumed with no 81 | /// trailing data (e.g. a metainfo file should not have extra data after the 82 | /// bencoded data). 83 | /// 84 | /// If there is expected trailing data, then it may be helpful to know how 85 | /// much data was read. 86 | /// 87 | /// # Example 88 | /// 89 | /// ``` 90 | /// use serde::Deserialize as _; 91 | /// use bt_bencode::Deserializer; 92 | /// 93 | /// let bytes: &[u8] = b"4:spameggs"; 94 | /// let mut de = Deserializer::from_slice(bytes); 95 | /// let value: &str = <&str>::deserialize(&mut de)?; 96 | /// assert_eq!(value, "spam"); 97 | /// 98 | /// // Do not call `de.end()` which checks for trailing data 99 | /// 100 | /// assert_eq!(de.byte_offset(), 6); 101 | /// assert_eq!(b"eggs", &bytes[de.byte_offset()..]); 102 | /// 103 | /// # Ok::<_, bt_bencode::Error>(()) 104 | /// ``` 105 | pub fn byte_offset(&self) -> usize { 106 | self.read.byte_offset() 107 | } 108 | 109 | /// Should be called after a value from the source is deserialized to 110 | /// validate that the entire source was read. 111 | /// 112 | /// If trailing data is expected, do not call this method. It may be 113 | /// beneficial to know how much data was read. See 114 | /// [`Deserializer::byte_offset()`]. 115 | /// 116 | /// # Errors 117 | /// 118 | /// An error is returned if there are unconsumed bytes in the readable 119 | /// source. 120 | pub fn end(&mut self) -> Result<()> { 121 | match self.read.peek() { 122 | Some(r) => r.and(Err(Error::new( 123 | ErrorKind::TrailingData, 124 | self.read.byte_offset(), 125 | ))), 126 | None => Ok(()), 127 | } 128 | } 129 | 130 | fn on_end_seq(&mut self) -> Result<()> { 131 | match self.parse_peek()? { 132 | b'e' => { 133 | self.parse_next()?; 134 | Ok(()) 135 | } 136 | _ => Err(Error::new(ErrorKind::InvalidList, self.read.byte_offset())), 137 | } 138 | } 139 | 140 | fn on_end_map(&mut self) -> Result<()> { 141 | match self.parse_peek()? { 142 | b'e' => { 143 | self.parse_next()?; 144 | Ok(()) 145 | } 146 | _ => Err(Error::new(ErrorKind::InvalidDict, self.read.byte_offset())), 147 | } 148 | } 149 | 150 | fn unexpected_type_err(&mut self, exp: &dyn Expected) -> Result { 151 | match self.parse_peek()? { 152 | b'0'..=b'9' => { 153 | self.buf.clear(); 154 | let bytes = self.read.parse_byte_str(&mut self.buf)?; 155 | Ok(de::Error::invalid_type(Unexpected::Bytes(&bytes), exp)) 156 | } 157 | b'i' => { 158 | self.parse_next()?; 159 | let (is_positive, num) = self.parse_integer()?; 160 | if is_positive { 161 | Ok(de::Error::invalid_type(Unexpected::Unsigned(num), exp)) 162 | } else { 163 | use core::convert::TryFrom; 164 | 165 | Ok(de::Error::invalid_type( 166 | Unexpected::Signed(-i64::try_from(num).map_err(|_| { 167 | Error::new(ErrorKind::InvalidInteger, self.read.byte_offset()) 168 | })?), 169 | exp, 170 | )) 171 | } 172 | } 173 | b'l' => Ok(de::Error::invalid_type(Unexpected::Seq, exp)), 174 | b'd' => Ok(de::Error::invalid_type(Unexpected::Map, exp)), 175 | _ => Err(Error::new( 176 | ErrorKind::ExpectedSomeValue, 177 | self.read.byte_offset(), 178 | )), 179 | } 180 | } 181 | 182 | #[inline] 183 | fn parse_peek(&mut self) -> Result { 184 | self.read 185 | .peek() 186 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.read.byte_offset()))? 187 | } 188 | 189 | #[inline] 190 | fn parse_next(&mut self) -> Result { 191 | self.read 192 | .next() 193 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.read.byte_offset()))? 194 | } 195 | 196 | fn parse_integer(&mut self) -> Result<(bool, u64)> { 197 | let peek = self 198 | .read 199 | .peek() 200 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 201 | let is_positive = if peek == b'-' { 202 | self.read 203 | .next() 204 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 205 | false 206 | } else { 207 | true 208 | }; 209 | 210 | let peek = self 211 | .read 212 | .peek() 213 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))??; 214 | match peek { 215 | b'0'..=b'9' => {} 216 | _ => { 217 | return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())); 218 | } 219 | } 220 | 221 | let mut value: u64 = 0; 222 | 223 | loop { 224 | match self 225 | .read 226 | .next() 227 | .ok_or_else(|| Error::new(ErrorKind::EofWhileParsingValue, self.byte_offset()))?? 228 | { 229 | b'e' => { 230 | return Ok((is_positive, value)); 231 | } 232 | n @ b'0'..=b'9' => { 233 | value = value 234 | .checked_mul(10) 235 | .ok_or_else(|| Error::new(ErrorKind::InvalidInteger, self.byte_offset()))?; 236 | value = value 237 | .checked_add(u64::from(n - b'0')) 238 | .ok_or_else(|| Error::new(ErrorKind::InvalidInteger, self.byte_offset()))?; 239 | } 240 | _ => return Err(Error::new(ErrorKind::InvalidInteger, self.byte_offset())), 241 | } 242 | } 243 | } 244 | } 245 | 246 | #[cfg(feature = "std")] 247 | impl Deserializer> 248 | where 249 | R: io::Read, 250 | { 251 | /// Constructs a Deserializer from an [`std::io::Read`][std::io::Read] source. 252 | #[must_use] 253 | pub fn from_reader(reader: R) -> Self { 254 | Deserializer::new(read::IoRead::new(reader)) 255 | } 256 | } 257 | 258 | impl<'a> Deserializer> { 259 | /// Constructs a Deserializer from a `&[u8]`. 260 | #[must_use] 261 | pub fn from_slice(bytes: &'a [u8]) -> Self { 262 | Deserializer::new(read::SliceRead::new(bytes)) 263 | } 264 | } 265 | 266 | impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer { 267 | type Error = Error; 268 | 269 | fn deserialize_any(self, visitor: V) -> Result 270 | where 271 | V: de::Visitor<'de>, 272 | { 273 | match self.parse_peek()? { 274 | b'0'..=b'9' => { 275 | self.buf.clear(); 276 | match self.read.parse_byte_str(&mut self.buf)? { 277 | Ref::Source(bytes) => visitor.visit_borrowed_bytes(bytes), 278 | Ref::Buffer(bytes) => visitor.visit_bytes(bytes), 279 | } 280 | } 281 | b'i' => { 282 | self.parse_next()?; 283 | 284 | let (is_positive, num) = self.parse_integer()?; 285 | if is_positive { 286 | visitor.visit_u64(num) 287 | } else { 288 | use core::convert::TryFrom; 289 | 290 | visitor.visit_i64(-i64::try_from(num).map_err(|_| { 291 | Error::new(ErrorKind::InvalidInteger, self.read.byte_offset()) 292 | })?) 293 | } 294 | } 295 | b'l' => { 296 | self.parse_next()?; 297 | let ret = visitor.visit_seq(SeqAccess { de: self }); 298 | match (ret, self.on_end_seq()) { 299 | (Ok(ret), Ok(())) => Ok(ret), 300 | (Err(err), _) | (_, Err(err)) => Err(err), 301 | } 302 | } 303 | b'd' => { 304 | self.parse_next()?; 305 | let ret = visitor.visit_map(MapAccess { de: self }); 306 | match (ret, self.on_end_map()) { 307 | (Ok(ret), Ok(())) => Ok(ret), 308 | (Err(err), _) | (_, Err(err)) => Err(err), 309 | } 310 | } 311 | _ => Err(Error::new( 312 | ErrorKind::ExpectedSomeValue, 313 | self.read.byte_offset(), 314 | )), 315 | } 316 | } 317 | 318 | forward_to_deserialize_any! { 319 | bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 unit unit_struct 320 | 321 | char str string 322 | 323 | seq tuple tuple_struct map 324 | 325 | struct enum identifier ignored_any 326 | } 327 | 328 | fn deserialize_bytes(self, visitor: V) -> Result 329 | where 330 | V: de::Visitor<'de>, 331 | { 332 | // The hint is that the next value should be in the form of bytes. 333 | // 334 | // For a byte string value, the parsed byte string is returned (removing 335 | // the preceding length and `:`). 336 | // 337 | // If the next value is any other type, then capture the "raw" byte 338 | // representation of the value. For example, an integer value would 339 | // return the bytes for `i1234e` which includes the `i` and `e` encoding 340 | // bytes. 341 | // 342 | // The idea is to allow the capture of the raw representation of a field 343 | // as-is. The primary use case is to capture the `info` value in a 344 | // BitTorrent metainfo. The `info` value would be captured as-is without 345 | // parsing which allows the infohash to be generated according to the specification. 346 | match self.parse_peek()? { 347 | b'0'..=b'9' => { 348 | self.buf.clear(); 349 | match self.read.parse_byte_str(&mut self.buf)? { 350 | Ref::Source(bytes) => visitor.visit_borrowed_bytes(bytes), 351 | Ref::Buffer(bytes) => visitor.visit_bytes(bytes), 352 | } 353 | } 354 | b'i' => { 355 | self.buf.clear(); 356 | match self.read.parse_raw_integer(&mut self.buf)? { 357 | Ref::Source(bytes) => visitor.visit_borrowed_bytes(bytes), 358 | Ref::Buffer(bytes) => visitor.visit_bytes(bytes), 359 | } 360 | } 361 | b'l' => { 362 | self.buf.clear(); 363 | match self.read.parse_raw_list(&mut self.buf)? { 364 | Ref::Source(bytes) => visitor.visit_borrowed_bytes(bytes), 365 | Ref::Buffer(bytes) => visitor.visit_bytes(bytes), 366 | } 367 | } 368 | b'd' => { 369 | self.buf.clear(); 370 | match self.read.parse_raw_dict(&mut self.buf)? { 371 | Ref::Source(bytes) => visitor.visit_borrowed_bytes(bytes), 372 | Ref::Buffer(bytes) => visitor.visit_bytes(bytes), 373 | } 374 | } 375 | _ => Err(self.unexpected_type_err(&visitor)?), 376 | } 377 | } 378 | 379 | #[inline] 380 | fn deserialize_byte_buf(self, visitor: V) -> Result 381 | where 382 | V: de::Visitor<'de>, 383 | { 384 | self.deserialize_bytes(visitor) 385 | } 386 | 387 | #[inline] 388 | fn deserialize_option(self, visitor: V) -> Result 389 | where 390 | V: de::Visitor<'de>, 391 | { 392 | visitor.visit_some(self) 393 | } 394 | 395 | #[inline] 396 | fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result 397 | where 398 | V: de::Visitor<'de>, 399 | { 400 | visitor.visit_newtype_struct(self) 401 | } 402 | 403 | #[inline] 404 | fn is_human_readable(&self) -> bool { 405 | false 406 | } 407 | } 408 | 409 | struct SeqAccess<'a, R> { 410 | de: &'a mut Deserializer, 411 | } 412 | 413 | impl<'de, 'a, R: Read<'de> + 'a> de::SeqAccess<'de> for SeqAccess<'a, R> { 414 | type Error = Error; 415 | 416 | fn next_element_seed(&mut self, seed: T) -> Result> 417 | where 418 | T: de::DeserializeSeed<'de>, 419 | { 420 | match self.de.parse_peek()? { 421 | b'e' => Ok(None), 422 | _ => Ok(Some(seed.deserialize(&mut *self.de)?)), 423 | } 424 | } 425 | } 426 | 427 | struct MapAccess<'a, R> { 428 | de: &'a mut Deserializer, 429 | } 430 | 431 | impl<'de, 'a, R: Read<'de> + 'a> de::MapAccess<'de> for MapAccess<'a, R> { 432 | type Error = Error; 433 | 434 | fn next_key_seed(&mut self, seed: K) -> Result> 435 | where 436 | K: de::DeserializeSeed<'de>, 437 | { 438 | match self.de.parse_peek()? { 439 | b'0'..=b'9' => seed.deserialize(MapKey { de: &mut *self.de }).map(Some), 440 | b'e' => Ok(None), 441 | _ => Err(Error::new( 442 | ErrorKind::KeyMustBeAByteStr, 443 | self.de.read.byte_offset(), 444 | )), 445 | } 446 | } 447 | 448 | #[inline] 449 | fn next_value_seed(&mut self, seed: V) -> Result 450 | where 451 | V: de::DeserializeSeed<'de>, 452 | { 453 | seed.deserialize(&mut *self.de) 454 | } 455 | } 456 | 457 | struct MapKey<'a, R> { 458 | de: &'a mut Deserializer, 459 | } 460 | 461 | impl<'de, R> de::Deserializer<'de> for MapKey<'_, R> 462 | where 463 | R: Read<'de>, 464 | { 465 | type Error = Error; 466 | 467 | #[inline] 468 | fn deserialize_any(self, visitor: V) -> Result 469 | where 470 | V: de::Visitor<'de>, 471 | { 472 | self.de.deserialize_any(visitor) 473 | } 474 | 475 | #[inline] 476 | fn deserialize_option(self, visitor: V) -> Result 477 | where 478 | V: de::Visitor<'de>, 479 | { 480 | visitor.visit_some(self) 481 | } 482 | 483 | #[inline] 484 | fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result 485 | where 486 | V: de::Visitor<'de>, 487 | { 488 | visitor.visit_newtype_struct(self) 489 | } 490 | 491 | forward_to_deserialize_any! { 492 | bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 unit unit_struct seq tuple tuple_struct map 493 | char str string bytes byte_buf enum struct identifier ignored_any 494 | } 495 | } 496 | 497 | #[cfg(test)] 498 | mod tests { 499 | use crate::ByteString; 500 | 501 | use super::*; 502 | use serde_derive::Deserialize; 503 | 504 | #[cfg(all(feature = "alloc", not(feature = "std")))] 505 | use alloc::{collections::BTreeMap, string::String, vec}; 506 | #[cfg(feature = "std")] 507 | use std::{collections::BTreeMap, string::String, vec}; 508 | 509 | #[test] 510 | fn test_deserialize_str() -> Result<()> { 511 | let s: &str = from_slice("4:spam".as_bytes())?; 512 | assert_eq!(s, "spam"); 513 | Ok(()) 514 | } 515 | 516 | #[test] 517 | fn test_deserialize_string() -> Result<()> { 518 | let s: String = from_slice("4:spam".as_bytes())?; 519 | assert_eq!(s, "spam"); 520 | Ok(()) 521 | } 522 | 523 | #[test] 524 | fn test_deserialize_integer_1() -> Result<()> { 525 | let input = "i3e"; 526 | let i: u64 = from_slice(input.as_bytes())?; 527 | assert_eq!(i, 3); 528 | Ok(()) 529 | } 530 | 531 | #[test] 532 | fn test_deserialize_integer_2() -> Result<()> { 533 | let input = "i-3e"; 534 | let i: i64 = from_slice(input.as_bytes())?; 535 | assert_eq!(i, -3); 536 | Ok(()) 537 | } 538 | 539 | #[test] 540 | fn test_deserialize_integer_3() -> Result<()> { 541 | let input = "i0e"; 542 | let i: u64 = from_slice(input.as_bytes())?; 543 | assert_eq!(i, 0); 544 | Ok(()) 545 | } 546 | 547 | #[test] 548 | fn test_deserialize_integer_4() -> Result<()> { 549 | let input = "i0e"; 550 | let i: i64 = from_slice(input.as_bytes())?; 551 | assert_eq!(i, 0); 552 | Ok(()) 553 | } 554 | 555 | #[test] 556 | fn test_deserialize_illegal_unsigned_int() { 557 | let input = "ie"; 558 | let result: Result = from_slice(input.as_bytes()); 559 | let error = result.unwrap_err(); 560 | match error.kind() { 561 | ErrorKind::InvalidInteger => {} 562 | _ => panic!(), 563 | } 564 | assert_eq!(error.byte_offset(), 1); 565 | } 566 | 567 | #[test] 568 | fn test_deserialize_illegal_signed_int() { 569 | let input = "i-e"; 570 | let result: Result = from_slice(input.as_bytes()); 571 | let error = result.unwrap_err(); 572 | match error.kind() { 573 | ErrorKind::InvalidInteger => {} 574 | _ => panic!(), 575 | } 576 | assert_eq!(error.byte_offset(), 2); 577 | } 578 | 579 | #[test] 580 | fn test_deserialize_list() -> Result<()> { 581 | let input = "l4:spam4:eggse"; 582 | let v: Vec = from_slice(input.as_bytes())?; 583 | assert_eq!(v, vec!["spam", "eggs"]); 584 | Ok(()) 585 | } 586 | 587 | #[test] 588 | fn test_deserialize_list_str() -> Result<()> { 589 | let input = "l4:spam4:eggse"; 590 | let v: Vec<&str> = from_slice(input.as_bytes())?; 591 | assert_eq!(v, vec!["spam", "eggs"]); 592 | Ok(()) 593 | } 594 | 595 | #[test] 596 | fn test_deserialize_list_as_tuple() -> Result<()> { 597 | let input = "li123e4:eggse"; 598 | let v: (i64, &str) = from_slice(input.as_bytes())?; 599 | assert_eq!(v, (123, "eggs")); 600 | Ok(()) 601 | } 602 | 603 | #[test] 604 | fn test_deserialize_list_as_struct_tuple() -> Result<()> { 605 | #[derive(Debug, serde_derive::Deserialize, PartialEq, Eq)] 606 | struct S<'a>(i64, &'a str); 607 | 608 | let input = "li123e4:eggse"; 609 | let v: S<'_> = from_slice(input.as_bytes())?; 610 | assert_eq!(v, S(123, "eggs")); 611 | Ok(()) 612 | } 613 | 614 | #[test] 615 | fn test_deserialize_dict_1() -> Result<()> { 616 | let input = "d3:cow3:moo4:spam4:eggse"; 617 | let m: BTreeMap = from_slice(input.as_bytes())?; 618 | let mut expected = BTreeMap::new(); 619 | expected.insert(String::from("cow"), String::from("moo")); 620 | expected.insert(String::from("spam"), String::from("eggs")); 621 | assert_eq!(m, expected); 622 | Ok(()) 623 | } 624 | 625 | #[test] 626 | fn test_deserialize_dict_1_str() -> Result<()> { 627 | let input = "d3:cow3:moo4:spam4:eggse"; 628 | let m: BTreeMap<&str, &str> = from_slice(input.as_bytes())?; 629 | let mut expected = BTreeMap::new(); 630 | expected.insert("cow", "moo"); 631 | expected.insert("spam", "eggs"); 632 | assert_eq!(m, expected); 633 | Ok(()) 634 | } 635 | 636 | #[test] 637 | fn test_deserialize_dict_2() -> Result<()> { 638 | let input = "d4:spaml1:a1:bee"; 639 | let m: BTreeMap> = from_slice(input.as_bytes())?; 640 | let mut expected = BTreeMap::new(); 641 | expected.insert(String::from("spam"), vec!["a".into(), "b".into()]); 642 | assert_eq!(m, expected); 643 | Ok(()) 644 | } 645 | 646 | #[test] 647 | fn test_deserialize_dict_2_str() -> Result<()> { 648 | let input = "d4:spaml1:a1:bee"; 649 | let m: BTreeMap<&str, Vec<&str>> = from_slice(input.as_bytes())?; 650 | let mut expected = BTreeMap::new(); 651 | expected.insert("spam", vec!["a", "b"]); 652 | assert_eq!(m, expected); 653 | Ok(()) 654 | } 655 | 656 | #[test] 657 | fn test_deserialize_struct() -> Result<()> { 658 | #[derive(Debug, PartialEq, Deserialize)] 659 | struct S { 660 | spam: Vec, 661 | } 662 | 663 | let input = "d4:spaml1:a1:bee"; 664 | let s: S = from_slice(input.as_bytes())?; 665 | let expected = S { 666 | spam: vec!["a".into(), "b".into()], 667 | }; 668 | assert_eq!(s, expected); 669 | Ok(()) 670 | } 671 | 672 | #[test] 673 | fn test_deserialize_integer_as_raw_slice() -> Result<()> { 674 | #[derive(Debug, PartialEq, Deserialize)] 675 | struct S<'a>(&'a [u8]); 676 | 677 | let input = "i-1234e"; 678 | let s: S<'_> = from_slice(input.as_bytes())?; 679 | let expected = S(input.as_bytes()); 680 | assert_eq!(s, expected); 681 | Ok(()) 682 | } 683 | 684 | #[test] 685 | fn test_deserialize_list_as_raw_slice() -> Result<()> { 686 | #[derive(Debug, PartialEq, Deserialize)] 687 | struct S<'a>(&'a [u8]); 688 | 689 | let input = "l4:spam4:eggse"; 690 | let s: S<'_> = from_slice(input.as_bytes())?; 691 | let expected = S(input.as_bytes()); 692 | assert_eq!(s, expected); 693 | Ok(()) 694 | } 695 | 696 | #[test] 697 | fn test_deserialize_map_value_as_raw_slice() -> Result<()> { 698 | #[derive(Debug, PartialEq, Deserialize)] 699 | struct S<'a> { 700 | spam: &'a [u8], 701 | } 702 | 703 | let input = "d4:spamd1:a1:bee"; 704 | let s: S<'_> = from_slice(input.as_bytes())?; 705 | let expected = S { spam: b"d1:a1:be" }; 706 | assert_eq!(s, expected); 707 | Ok(()) 708 | } 709 | 710 | #[test] 711 | fn test_deserialize_map_as_raw_slice() -> Result<()> { 712 | #[derive(Debug, PartialEq, Deserialize)] 713 | struct S<'a>(&'a [u8]); 714 | 715 | let input = "d4:spamd1:a1:bee"; 716 | let s: S<'_> = from_slice(input.as_bytes())?; 717 | let expected = S(input.as_bytes()); 718 | assert_eq!(s, expected); 719 | Ok(()) 720 | } 721 | 722 | #[test] 723 | fn test_deserialize_integer_as_raw_bytes() -> Result<()> { 724 | #[derive(Debug, PartialEq, Deserialize)] 725 | struct S(ByteString); 726 | 727 | let input = "i-1234e"; 728 | let s: S = from_slice(input.as_bytes())?; 729 | let expected = S(ByteString::from(input.as_bytes().to_vec())); 730 | assert_eq!(s, expected); 731 | Ok(()) 732 | } 733 | 734 | #[test] 735 | fn test_deserialize_list_as_raw_bytes() -> Result<()> { 736 | #[derive(Debug, PartialEq, Deserialize)] 737 | struct S(ByteString); 738 | 739 | let input = "l4:spam4:eggse"; 740 | let s: S = from_slice(input.as_bytes())?; 741 | let expected = S(ByteString::from(input.as_bytes().to_vec())); 742 | assert_eq!(s, expected); 743 | Ok(()) 744 | } 745 | 746 | #[test] 747 | fn test_deserialize_map_value_as_raw_bytes() -> Result<()> { 748 | #[derive(Debug, PartialEq, Deserialize)] 749 | struct S { 750 | spam: ByteString, 751 | } 752 | 753 | let input = "d4:spamd1:a1:bee"; 754 | let s: S = from_slice(input.as_bytes())?; 755 | let expected = S { 756 | spam: ByteString::from(b"d1:a1:be".to_vec()), 757 | }; 758 | assert_eq!(s, expected); 759 | Ok(()) 760 | } 761 | 762 | #[test] 763 | fn test_deserialize_map_as_raw_bytes() -> Result<()> { 764 | #[derive(Debug, PartialEq, Deserialize)] 765 | struct S(ByteString); 766 | 767 | let input = "d4:spamd1:a1:bee"; 768 | let s: S = from_slice(input.as_bytes())?; 769 | let expected = S(ByteString::from(input.as_bytes().to_vec())); 770 | assert_eq!(s, expected); 771 | Ok(()) 772 | } 773 | } 774 | -------------------------------------------------------------------------------- /src/ser.rs: -------------------------------------------------------------------------------- 1 | //! Serializes Bencode data. 2 | 3 | use crate::error::{Error, ErrorKind, Result}; 4 | use serde::{ser, Serialize}; 5 | 6 | #[cfg(all(feature = "alloc", not(feature = "std")))] 7 | use alloc::{collections::BTreeMap, vec::Vec}; 8 | 9 | #[cfg(feature = "std")] 10 | use std::{collections::BTreeMap, io, vec::Vec}; 11 | 12 | use crate::write::Write; 13 | 14 | /// Serializes an instance of `T` into the writer `W` as `Bencode` data. 15 | /// 16 | /// # Errors 17 | /// 18 | /// Serialization can fail if `T`'s implementation of 19 | /// [Serialize][serde::ser::Serialize] decides to fail, if `T` contains 20 | /// unsupported types for serialization, or if `T` contains a map with 21 | /// non-string keys. 22 | #[cfg(feature = "std")] 23 | #[inline] 24 | pub fn to_writer(writer: W, value: &T) -> Result<()> 25 | where 26 | W: io::Write, 27 | T: ?Sized + Serialize, 28 | { 29 | let mut ser = Serializer::new(crate::write::IoWrite::new(writer)); 30 | value.serialize(&mut ser)?; 31 | Ok(()) 32 | } 33 | 34 | /// Serializes an instance of `T` into a new [Vec] as `Bencode` data. 35 | /// 36 | /// # Errors 37 | /// 38 | /// Serialization can fail if `T`'s implemenation of 39 | /// [Serialize][serde::ser::Serialize] decides to fail, if `T` contains 40 | /// unsupported types for serialization, or if `T` contains a map with 41 | /// non-string keys. 42 | #[inline] 43 | pub fn to_vec(value: &T) -> Result> 44 | where 45 | T: ?Sized + Serialize, 46 | { 47 | let mut writer = Vec::new(); 48 | let mut ser = Serializer::new(&mut writer); 49 | value.serialize(&mut ser)?; 50 | Ok(writer) 51 | } 52 | 53 | /// A `Bencode` Serializer for types which implement [Serialize][serde::ser::Serialize]. 54 | #[derive(Debug)] 55 | pub struct Serializer { 56 | writer: W, 57 | } 58 | 59 | impl Serializer 60 | where 61 | W: Write, 62 | { 63 | /// Constructs a Serializer with an [Write] target. 64 | pub fn new(writer: W) -> Self { 65 | Serializer { writer } 66 | } 67 | } 68 | 69 | impl Serializer 70 | where 71 | W: Write, 72 | { 73 | /// Returns the inner writer. 74 | /// 75 | /// Useful when the serializer is done and the writer is needed to write other data. 76 | #[inline] 77 | pub fn into_inner(self) -> W { 78 | self.writer 79 | } 80 | } 81 | 82 | impl<'a, W> ser::Serializer for &'a mut Serializer 83 | where 84 | W: Write, 85 | { 86 | type Ok = (); 87 | type Error = Error; 88 | 89 | type SerializeSeq = Self; 90 | type SerializeTuple = Self; 91 | type SerializeTupleStruct = Self; 92 | type SerializeTupleVariant = ser::Impossible<(), Error>; 93 | type SerializeMap = SerializeMap<'a, W>; 94 | type SerializeStruct = SerializeMap<'a, W>; 95 | type SerializeStructVariant = ser::Impossible<(), Error>; 96 | 97 | #[inline] 98 | fn serialize_bool(self, _value: bool) -> Result<()> { 99 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 100 | } 101 | 102 | #[inline] 103 | fn serialize_i8(self, value: i8) -> Result<()> { 104 | self.serialize_i64(i64::from(value)) 105 | } 106 | 107 | #[inline] 108 | fn serialize_i16(self, value: i16) -> Result<()> { 109 | self.serialize_i64(i64::from(value)) 110 | } 111 | 112 | #[inline] 113 | fn serialize_i32(self, value: i32) -> Result<()> { 114 | self.serialize_i64(i64::from(value)) 115 | } 116 | 117 | #[inline] 118 | fn serialize_i64(self, value: i64) -> Result<()> { 119 | self.writer.write_all(b"i")?; 120 | self.writer 121 | .write_all(itoa::Buffer::new().format(value).as_bytes())?; 122 | self.writer.write_all(b"e")?; 123 | Ok(()) 124 | } 125 | 126 | #[inline] 127 | fn serialize_u8(self, value: u8) -> Result<()> { 128 | self.serialize_u64(u64::from(value)) 129 | } 130 | 131 | #[inline] 132 | fn serialize_u16(self, value: u16) -> Result<()> { 133 | self.serialize_u64(u64::from(value)) 134 | } 135 | 136 | #[inline] 137 | fn serialize_u32(self, value: u32) -> Result<()> { 138 | self.serialize_u64(u64::from(value)) 139 | } 140 | 141 | #[inline] 142 | fn serialize_u64(self, value: u64) -> Result<()> { 143 | self.writer.write_all(b"i")?; 144 | self.writer 145 | .write_all(itoa::Buffer::new().format(value).as_bytes())?; 146 | self.writer.write_all(b"e")?; 147 | Ok(()) 148 | } 149 | 150 | #[inline] 151 | fn serialize_f32(self, _value: f32) -> Result<()> { 152 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 153 | } 154 | 155 | #[inline] 156 | fn serialize_f64(self, _value: f64) -> Result<()> { 157 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 158 | } 159 | 160 | #[inline] 161 | fn serialize_char(self, value: char) -> Result<()> { 162 | let mut buf = [0; 4]; 163 | self.serialize_str(value.encode_utf8(&mut buf)) 164 | } 165 | 166 | #[inline] 167 | fn serialize_str(self, value: &str) -> Result<()> { 168 | self.writer 169 | .write_all(itoa::Buffer::new().format(value.len()).as_bytes())?; 170 | self.writer.write_all(b":")?; 171 | self.writer.write_all(value.as_bytes()) 172 | } 173 | 174 | #[inline] 175 | fn serialize_bytes(self, value: &[u8]) -> Result<()> { 176 | self.writer 177 | .write_all(itoa::Buffer::new().format(value.len()).as_bytes())?; 178 | self.writer.write_all(b":")?; 179 | self.writer.write_all(value) 180 | } 181 | 182 | #[inline] 183 | fn serialize_none(self) -> Result<()> { 184 | self.serialize_unit() 185 | } 186 | 187 | #[inline] 188 | fn serialize_some(self, value: &T) -> Result<()> 189 | where 190 | T: ?Sized + Serialize, 191 | { 192 | value.serialize(self) 193 | } 194 | 195 | #[inline] 196 | fn serialize_unit(self) -> Result<()> { 197 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 198 | } 199 | 200 | #[inline] 201 | fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { 202 | self.serialize_unit() 203 | } 204 | 205 | #[inline] 206 | fn serialize_unit_variant( 207 | self, 208 | _name: &'static str, 209 | _variant_index: u32, 210 | _variant: &'static str, 211 | ) -> Result<()> { 212 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 213 | } 214 | 215 | #[inline] 216 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> 217 | where 218 | T: ?Sized + Serialize, 219 | { 220 | value.serialize(self) 221 | } 222 | 223 | #[inline] 224 | fn serialize_newtype_variant( 225 | self, 226 | _name: &'static str, 227 | _variant_index: u32, 228 | _variant: &'static str, 229 | _value: &T, 230 | ) -> Result<()> 231 | where 232 | T: ?Sized + Serialize, 233 | { 234 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 235 | } 236 | 237 | #[inline] 238 | fn serialize_seq(self, _len: Option) -> Result { 239 | self.writer.write_all(b"l")?; 240 | Ok(self) 241 | } 242 | 243 | #[inline] 244 | fn serialize_tuple(self, len: usize) -> Result { 245 | self.serialize_seq(Some(len)) 246 | } 247 | 248 | #[inline] 249 | fn serialize_tuple_struct( 250 | self, 251 | _name: &'static str, 252 | len: usize, 253 | ) -> Result { 254 | self.serialize_seq(Some(len)) 255 | } 256 | 257 | #[inline] 258 | fn serialize_tuple_variant( 259 | self, 260 | _name: &'static str, 261 | _variant_index: u32, 262 | _variant: &'static str, 263 | _len: usize, 264 | ) -> Result { 265 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 266 | } 267 | 268 | #[inline] 269 | fn serialize_map(self, _len: Option) -> Result { 270 | self.writer.write_all(b"d")?; 271 | Ok(SerializeMap::new(self)) 272 | } 273 | 274 | #[inline] 275 | fn serialize_struct(self, _name: &'static str, len: usize) -> Result { 276 | self.serialize_map(Some(len)) 277 | } 278 | 279 | #[inline] 280 | fn serialize_struct_variant( 281 | self, 282 | _name: &'static str, 283 | _variant_index: u32, 284 | _variant: &'static str, 285 | _len: usize, 286 | ) -> Result { 287 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 288 | } 289 | 290 | fn is_human_readable(&self) -> bool { 291 | false 292 | } 293 | } 294 | 295 | impl ser::SerializeSeq for &mut Serializer 296 | where 297 | W: Write, 298 | { 299 | type Ok = (); 300 | type Error = Error; 301 | 302 | #[inline] 303 | fn serialize_element(&mut self, value: &T) -> Result<()> 304 | where 305 | T: ?Sized + Serialize, 306 | { 307 | value.serialize(&mut **self) 308 | } 309 | 310 | #[inline] 311 | fn end(self) -> Result<()> { 312 | self.writer.write_all(b"e")?; 313 | Ok(()) 314 | } 315 | } 316 | 317 | impl ser::SerializeTuple for &mut Serializer 318 | where 319 | W: Write, 320 | { 321 | type Ok = (); 322 | type Error = Error; 323 | 324 | #[inline] 325 | fn serialize_element(&mut self, value: &T) -> Result<()> 326 | where 327 | T: ?Sized + Serialize, 328 | { 329 | value.serialize(&mut **self) 330 | } 331 | 332 | #[inline] 333 | fn end(self) -> Result<()> { 334 | self.writer.write_all(b"e")?; 335 | Ok(()) 336 | } 337 | } 338 | 339 | impl ser::SerializeTupleStruct for &mut Serializer 340 | where 341 | W: Write, 342 | { 343 | type Ok = (); 344 | type Error = Error; 345 | 346 | #[inline] 347 | fn serialize_field(&mut self, value: &T) -> Result<()> 348 | where 349 | T: ?Sized + Serialize, 350 | { 351 | value.serialize(&mut **self) 352 | } 353 | 354 | #[inline] 355 | fn end(self) -> Result<()> { 356 | self.writer.write_all(b"e")?; 357 | Ok(()) 358 | } 359 | } 360 | 361 | /// A serializer for writing map data. 362 | #[doc(hidden)] 363 | #[derive(Debug)] 364 | pub struct SerializeMap<'a, W> { 365 | ser: &'a mut Serializer, 366 | entries: BTreeMap, Vec>, 367 | current_key: Option>, 368 | } 369 | 370 | impl<'a, W> SerializeMap<'a, W> 371 | where 372 | W: Write, 373 | { 374 | #[inline] 375 | fn new(ser: &'a mut Serializer) -> Self { 376 | SerializeMap { 377 | ser, 378 | entries: BTreeMap::new(), 379 | current_key: None, 380 | } 381 | } 382 | 383 | #[inline] 384 | fn end_map(&mut self) -> Result<()> { 385 | if self.current_key.is_some() { 386 | return Err(Error::with_kind(ErrorKind::KeyWithoutValue)); 387 | } 388 | 389 | for (k, v) in &self.entries { 390 | ser::Serializer::serialize_bytes(&mut *self.ser, k.as_ref())?; 391 | self.ser.writer.write_all(v)?; 392 | } 393 | 394 | Ok(()) 395 | } 396 | } 397 | 398 | impl ser::SerializeMap for SerializeMap<'_, W> 399 | where 400 | W: Write, 401 | { 402 | type Ok = (); 403 | type Error = Error; 404 | 405 | #[inline] 406 | fn serialize_key(&mut self, key: &T) -> Result<()> 407 | where 408 | T: ?Sized + Serialize, 409 | { 410 | if self.current_key.is_some() { 411 | return Err(Error::with_kind(ErrorKind::KeyWithoutValue)); 412 | } 413 | self.current_key = Some(key.serialize(&mut MapKeySerializer {})?); 414 | Ok(()) 415 | } 416 | 417 | #[inline] 418 | fn serialize_value(&mut self, value: &T) -> Result<()> 419 | where 420 | T: ?Sized + Serialize, 421 | { 422 | let key = self 423 | .current_key 424 | .take() 425 | .ok_or_else(|| Error::with_kind(ErrorKind::ValueWithoutKey))?; 426 | let buf: Vec = Vec::new(); 427 | let mut ser = Serializer::new(buf); 428 | value.serialize(&mut ser)?; 429 | self.entries.insert(key, ser.into_inner()); 430 | Ok(()) 431 | } 432 | 433 | #[inline] 434 | fn end(mut self) -> Result<()> { 435 | self.end_map()?; 436 | self.ser.writer.write_all(b"e")?; 437 | Ok(()) 438 | } 439 | } 440 | 441 | impl ser::SerializeStruct for SerializeMap<'_, W> 442 | where 443 | W: Write, 444 | { 445 | type Ok = (); 446 | type Error = Error; 447 | 448 | #[inline] 449 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 450 | where 451 | T: ?Sized + Serialize, 452 | { 453 | let key = key.serialize(&mut MapKeySerializer {})?; 454 | 455 | let buf: Vec = Vec::new(); 456 | let mut ser = Serializer::new(buf); 457 | value.serialize(&mut ser)?; 458 | self.entries.insert(key, ser.into_inner()); 459 | Ok(()) 460 | } 461 | 462 | #[inline] 463 | fn end(mut self) -> Result<()> { 464 | self.end_map()?; 465 | self.ser.writer.write_all(b"e")?; 466 | Ok(()) 467 | } 468 | } 469 | 470 | struct MapKeySerializer; 471 | 472 | impl ser::Serializer for &mut MapKeySerializer { 473 | type Ok = Vec; 474 | type Error = Error; 475 | 476 | type SerializeSeq = ser::Impossible, Error>; 477 | type SerializeTuple = ser::Impossible, Error>; 478 | type SerializeTupleStruct = ser::Impossible, Error>; 479 | type SerializeTupleVariant = ser::Impossible, Error>; 480 | type SerializeMap = ser::Impossible, Error>; 481 | type SerializeStruct = ser::Impossible, Error>; 482 | type SerializeStructVariant = ser::Impossible, Error>; 483 | 484 | fn serialize_bool(self, _value: bool) -> Result> { 485 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 486 | } 487 | 488 | fn serialize_i8(self, _value: i8) -> Result> { 489 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 490 | } 491 | 492 | fn serialize_i16(self, _value: i16) -> Result> { 493 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 494 | } 495 | 496 | fn serialize_i32(self, _value: i32) -> Result> { 497 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 498 | } 499 | 500 | fn serialize_i64(self, _value: i64) -> Result> { 501 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 502 | } 503 | 504 | fn serialize_u8(self, _value: u8) -> Result> { 505 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 506 | } 507 | 508 | fn serialize_u16(self, _value: u16) -> Result> { 509 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 510 | } 511 | 512 | fn serialize_u32(self, _value: u32) -> Result> { 513 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 514 | } 515 | 516 | fn serialize_u64(self, _value: u64) -> Result> { 517 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 518 | } 519 | 520 | fn serialize_f32(self, _value: f32) -> Result> { 521 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 522 | } 523 | 524 | fn serialize_f64(self, _value: f64) -> Result> { 525 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 526 | } 527 | 528 | fn serialize_char(self, value: char) -> Result> { 529 | let mut buf = [0; 4]; 530 | self.serialize_str(value.encode_utf8(&mut buf)) 531 | } 532 | 533 | fn serialize_str(self, value: &str) -> Result> { 534 | let mut buf: Vec = Vec::with_capacity(value.len()); 535 | buf.extend_from_slice(value.as_bytes()); 536 | Ok(buf) 537 | } 538 | 539 | fn serialize_bytes(self, value: &[u8]) -> Result> { 540 | let mut buf: Vec = Vec::with_capacity(value.len()); 541 | buf.extend_from_slice(value); 542 | Ok(buf) 543 | } 544 | 545 | fn serialize_unit(self) -> Result> { 546 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 547 | } 548 | 549 | fn serialize_unit_struct(self, _name: &'static str) -> Result> { 550 | self.serialize_unit() 551 | } 552 | 553 | fn serialize_unit_variant( 554 | self, 555 | _name: &'static str, 556 | _variant_index: u32, 557 | _variant: &'static str, 558 | ) -> Result> { 559 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 560 | } 561 | 562 | fn serialize_newtype_struct( 563 | self, 564 | _name: &'static str, 565 | _value: &T, 566 | ) -> Result> { 567 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 568 | } 569 | 570 | fn serialize_newtype_variant( 571 | self, 572 | _name: &'static str, 573 | _variant_index: u32, 574 | _variant: &'static str, 575 | _value: &T, 576 | ) -> Result> { 577 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 578 | } 579 | 580 | fn serialize_none(self) -> Result> { 581 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 582 | } 583 | 584 | fn serialize_some(self, _value: &T) -> Result> { 585 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 586 | } 587 | 588 | fn serialize_seq(self, _len: Option) -> Result, Error>> { 589 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 590 | } 591 | 592 | fn serialize_tuple(self, _size: usize) -> Result, Error>> { 593 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 594 | } 595 | 596 | fn serialize_tuple_struct( 597 | self, 598 | _name: &'static str, 599 | _len: usize, 600 | ) -> Result, Error>> { 601 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 602 | } 603 | 604 | fn serialize_tuple_variant( 605 | self, 606 | _name: &'static str, 607 | _variant_index: u32, 608 | _variant: &'static str, 609 | _len: usize, 610 | ) -> Result, Error>> { 611 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 612 | } 613 | 614 | fn serialize_map(self, _len: Option) -> Result, Error>> { 615 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 616 | } 617 | 618 | fn serialize_struct( 619 | self, 620 | _name: &'static str, 621 | _len: usize, 622 | ) -> Result, Error>> { 623 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 624 | } 625 | 626 | fn serialize_struct_variant( 627 | self, 628 | _name: &'static str, 629 | _variant_index: u32, 630 | _variant: &'static str, 631 | _len: usize, 632 | ) -> Result, Error>> { 633 | Err(Error::with_kind(ErrorKind::UnsupportedType)) 634 | } 635 | } 636 | 637 | #[cfg(test)] 638 | mod tests { 639 | use crate::ByteString; 640 | 641 | use super::*; 642 | 643 | #[cfg(all(feature = "alloc", not(feature = "std")))] 644 | use alloc::{format, string::String, vec}; 645 | #[cfg(feature = "std")] 646 | use std::string::String; 647 | 648 | macro_rules! assert_is_unsupported_type { 649 | ($e:expr) => { 650 | match $e { 651 | Ok(_) => unreachable!(), 652 | Err(error) => match error.kind() { 653 | ErrorKind::UnsupportedType => {} 654 | _ => panic!("wrong error type"), 655 | }, 656 | } 657 | }; 658 | } 659 | 660 | #[test] 661 | fn test_serialize_bool() { 662 | assert_is_unsupported_type!(to_vec(&true)); 663 | } 664 | 665 | #[test] 666 | fn test_serialize_isize() { 667 | let value: isize = 2; 668 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 669 | let value: isize = -2; 670 | assert_eq!(to_vec(&value).unwrap(), String::from("i-2e").into_bytes()); 671 | } 672 | 673 | #[test] 674 | fn test_serialize_i8() { 675 | let value: i8 = 2; 676 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 677 | let value: i8 = -2; 678 | assert_eq!(to_vec(&value).unwrap(), String::from("i-2e").into_bytes()); 679 | } 680 | 681 | #[test] 682 | fn test_serialize_i16() { 683 | let value: i16 = 2; 684 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 685 | let value: i16 = -2; 686 | assert_eq!(to_vec(&value).unwrap(), String::from("i-2e").into_bytes()); 687 | } 688 | 689 | #[test] 690 | fn test_serialize_i32() { 691 | let value: i32 = 2; 692 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 693 | let value: i32 = -2; 694 | assert_eq!(to_vec(&value).unwrap(), String::from("i-2e").into_bytes()); 695 | } 696 | 697 | #[test] 698 | fn test_serialize_i64() { 699 | let value: i64 = 2; 700 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 701 | let value: i64 = -2; 702 | assert_eq!(to_vec(&value).unwrap(), String::from("i-2e").into_bytes()); 703 | } 704 | 705 | #[test] 706 | fn test_serialize_usize() { 707 | let value: usize = 2; 708 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 709 | } 710 | 711 | #[test] 712 | fn test_serialize_u8() { 713 | let value: u8 = 2; 714 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 715 | } 716 | 717 | #[test] 718 | fn test_serialize_u16() { 719 | let value: u16 = 2; 720 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 721 | } 722 | 723 | #[test] 724 | fn test_serialize_u32() { 725 | let value: u32 = 2; 726 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 727 | } 728 | 729 | #[test] 730 | fn test_serialize_u64() { 731 | let value: u64 = 2; 732 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 733 | } 734 | 735 | #[test] 736 | fn test_serialize_u64_greater_than_i64_max() { 737 | let value: u64 = (i64::max_value() as u64) + 1; 738 | assert_eq!(to_vec(&value).unwrap(), format!("i{}e", value).into_bytes()); 739 | } 740 | 741 | #[test] 742 | fn test_serialize_f32() { 743 | let value: f32 = 2.0; 744 | assert_is_unsupported_type!(to_vec(&value)); 745 | } 746 | 747 | #[test] 748 | fn test_serialize_f64() { 749 | let value: f64 = 2.0; 750 | assert_is_unsupported_type!(to_vec(&value)); 751 | } 752 | 753 | #[test] 754 | fn test_serialize_char() { 755 | let value: char = 'a'; 756 | assert_eq!(to_vec(&value).unwrap(), String::from("1:a").into_bytes()); 757 | } 758 | 759 | #[test] 760 | fn test_serialize_str() { 761 | let value: &str = "Hello world!"; 762 | assert_eq!( 763 | to_vec(&value).unwrap(), 764 | String::from("12:Hello world!").into_bytes() 765 | ); 766 | } 767 | 768 | #[test] 769 | fn test_serialize_empty_str() { 770 | let value: &str = ""; 771 | assert_eq!(to_vec(&value).unwrap(), String::from("0:").into_bytes()); 772 | } 773 | 774 | #[test] 775 | fn test_serialize_bytes() { 776 | let value = ByteString::from(String::from("123").into_bytes()); 777 | assert_eq!(to_vec(&&value).unwrap(), String::from("3:123").into_bytes()); 778 | } 779 | 780 | #[test] 781 | fn test_serialize_unit() { 782 | assert_is_unsupported_type!(to_vec(&())); 783 | } 784 | 785 | #[test] 786 | fn test_serialize_none() { 787 | let value: Option = None; 788 | assert_is_unsupported_type!(to_vec(&value)); 789 | } 790 | 791 | #[test] 792 | fn test_serialize_some() { 793 | let value: Option = Some(2); 794 | assert_eq!(to_vec(&value).unwrap(), String::from("i2e").into_bytes()); 795 | } 796 | 797 | #[test] 798 | fn test_serialize_unit_struct() { 799 | use serde::Serializer; 800 | 801 | let mut writer = Vec::new(); 802 | assert_is_unsupported_type!( 803 | super::Serializer::new(&mut writer).serialize_unit_struct("Nothing") 804 | ); 805 | } 806 | 807 | #[test] 808 | fn test_serialize_unit_variant() { 809 | use serde::Serializer; 810 | 811 | let mut writer = Vec::new(); 812 | assert_is_unsupported_type!( 813 | super::Serializer::new(&mut writer).serialize_unit_variant("Nothing", 0, "Case") 814 | ); 815 | } 816 | 817 | #[test] 818 | fn test_serialize_newtype_struct() { 819 | use serde::Serializer; 820 | 821 | let mut writer = Vec::new(); 822 | 823 | super::Serializer::new(&mut writer) 824 | .serialize_newtype_struct("Nothing", &2) 825 | .unwrap(); 826 | 827 | assert_eq!(String::from_utf8(writer).unwrap(), "i2e"); 828 | } 829 | 830 | #[test] 831 | fn test_serialize_newtype_variant() { 832 | use serde::Serializer; 833 | 834 | let mut writer = Vec::new(); 835 | assert_is_unsupported_type!( 836 | super::Serializer::new(&mut writer).serialize_unit_variant("Nothing", 0, "Case") 837 | ); 838 | } 839 | 840 | #[test] 841 | fn test_serialize_seq() { 842 | let value: Vec = vec![1, 2, 3]; 843 | assert_eq!( 844 | to_vec(&&value).unwrap(), 845 | String::from("li1ei2ei3ee").into_bytes() 846 | ); 847 | } 848 | 849 | #[test] 850 | fn test_serialize_seq_empty() { 851 | let value: Vec = vec![]; 852 | assert_eq!(to_vec(&&value).unwrap(), String::from("le").into_bytes()); 853 | } 854 | 855 | #[test] 856 | fn test_serialize_tuple() { 857 | assert_eq!( 858 | to_vec(&(201, "spam")).unwrap(), 859 | String::from("li201e4:spame").into_bytes() 860 | ); 861 | } 862 | 863 | #[test] 864 | fn test_serialize_tuple_struct() { 865 | #[derive(serde_derive::Serialize)] 866 | struct S<'a>(i64, &'a str); 867 | 868 | assert_eq!( 869 | to_vec(&S(201, "spam")).unwrap(), 870 | String::from("li201e4:spame").into_bytes() 871 | ); 872 | } 873 | 874 | #[test] 875 | fn test_serialize_tuple_variant() { 876 | use serde::Serializer; 877 | 878 | let mut writer = Vec::new(); 879 | assert_is_unsupported_type!(super::Serializer::new(&mut writer).serialize_tuple_variant( 880 | "Tuple Variant", 881 | 2, 882 | "Case", 883 | 1 884 | )); 885 | } 886 | 887 | #[test] 888 | fn test_serialize_struct_variant() { 889 | use serde::Serializer; 890 | 891 | let mut writer = Vec::new(); 892 | assert_is_unsupported_type!( 893 | super::Serializer::new(&mut writer).serialize_struct_variant( 894 | "Struct Variant", 895 | 2, 896 | "Case", 897 | 1 898 | ) 899 | ); 900 | } 901 | 902 | #[test] 903 | fn test_serialize_struct() { 904 | use serde_derive::Serialize; 905 | 906 | #[derive(Serialize)] 907 | struct Test { 908 | int: u32, 909 | s: String, 910 | } 911 | 912 | let test = Test { 913 | int: 3, 914 | s: String::from("Hello, World!"), 915 | }; 916 | assert_eq!( 917 | to_vec(&test).unwrap(), 918 | String::from("d3:inti3e1:s13:Hello, World!e").into_bytes() 919 | ); 920 | } 921 | } 922 | --------------------------------------------------------------------------------