serde_cbor-0.11.2/.cargo_vcs_info.json0000644000000001120000000000000132150ustar { "git": { "sha1": "347a3f096d5a1e8e380b9968e74838c9037a5b14" } } serde_cbor-0.11.2/.editorconfig000064400000000000000000000002060000000000000144440ustar 00000000000000# see https://editorconfig.org for more options, and setup instructions for yours editor [*.rs] indent_style = space indent_size = 4 serde_cbor-0.11.2/.gitignore000064400000000000000000000001260000000000000137600ustar 00000000000000target Cargo.lock *.rs.bk tokamak.toml .idea *.iml examples/ferris.cbor .cargo/config serde_cbor-0.11.2/.travis.yml000064400000000000000000000021100000000000000140740ustar 00000000000000language: rust rust: - 1.40.0 - stable - beta - nightly matrix: allow_failures: - rust: nightly sudo: false before_script: - rustup component add rustfmt - rustup target add thumbv7em-none-eabihf # Any target that does not have a standard library will do script: - cargo fmt --all -- --check - (rustup component add clippy && cargo clippy --all -- -D clippy::all) || true - cargo build - cargo test - > [[ $TRAVIS_RUST_VERSION == "1.31.0" ]] || cargo build --no-default-features --features alloc --target thumbv7em-none-eabihf # Test we can build a platform that does not have std. - cargo test --no-default-features --lib --tests # Run no_std tests - > [[ $TRAVIS_RUST_VERSION == "1.31.0" ]] || cargo build --no-default-features --features alloc - cargo build --features unsealed_read_write # The crate should still build when the unsealed_read_write feature is enabled. - cargo build --no-default-features --features unsealed_read_write # The crate should still build when the unsealed_read_write feature is enabled and std disabled. serde_cbor-0.11.2/CONTRIBUTING.md000064400000000000000000000023670000000000000142320ustar 00000000000000# Contributing to Serde CBOR Thanks for your interest! There are many ways to help: * write an issue about a problem you encountered * submit a pull request * add documentation and examples ## Pull Requests Code should be easy to understand and documented. For new features and fixed bugs please add a test to one of the files in `test/`. The tests are run on Travis CI to catch regressions early. Format your code with `cargo fmt` before committing. Currently Serde CBOR does not contain `unsafe` code and I would like to keep it this way. ## Making a Release * [ ] Make sure the crate compiles and all tests pass. * [ ] (Optional) Test that the fuzzer works and fuzz the crate for some time. * [ ] Write a list with all changes made since the last release * [ ] Increment the version number in `Cargo.toml` and the `README.md`. Bugfixes increase the patch version while new features or an increased minimum Rust version require a new minor version. * [ ] Check that the file `examples/readme.rs` and the example from the `README.md` match. * [ ] Commit the changes. * [ ] Add a git tag with the new version number: `git tag "v42.0.2"` * [ ] Push the changes: `git push --tags` * [ ] Run `cargo publish` * [ ] Add a new release to GitHub with a list of changes.serde_cbor-0.11.2/Cargo.lock0000644000000032750000000000000112050ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "half" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0" [[package]] name = "proc-macro2" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" dependencies = [ "proc-macro2", ] [[package]] name = "serde" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" [[package]] name = "serde_cbor" version = "0.11.2" dependencies = [ "half", "serde", "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "syn" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" serde_cbor-0.11.2/Cargo.toml0000644000000023610000000000000112230ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "serde_cbor" version = "0.11.2" authors = ["Pyfisch ", "Steven Fackler "] description = "CBOR support for serde." readme = "README.md" keywords = ["serde", "cbor", "serialization", "no_std"] categories = ["encoding"] license = "MIT/Apache-2.0" repository = "https://github.com/pyfisch/cbor" [dependencies.half] version = "1.2.0" [dependencies.serde] version = "1.0.14" default-features = false [dev-dependencies.serde_derive] version = "1.0.14" default-features = false [features] alloc = ["serde/alloc"] default = ["std"] std = ["serde/std"] tags = [] unsealed_read_write = [] [badges.maintenance] status = "as-is" [badges.travis-ci] repository = "pyfisch/cbor" serde_cbor-0.11.2/Cargo.toml.orig000064400000000000000000000014670000000000000146700ustar 00000000000000[package] name = "serde_cbor" version = "0.11.2" authors = [ "Pyfisch ", "Steven Fackler "] repository = "https://github.com/pyfisch/cbor" readme = "README.md" license = "MIT/Apache-2.0" description = "CBOR support for serde." keywords = ["serde", "cbor", "serialization", "no_std"] categories = ["encoding"] edition = "2018" [badges] travis-ci = { repository = "pyfisch/cbor" } maintenance = { status = "as-is" } [dependencies] half = "1.2.0" serde = { version = "1.0.14", default-features = false } [dev-dependencies] serde_derive = { version = "1.0.14", default-features = false } [features] default = ["std"] # Uses `alloc` library and adds support for vector functions with # `no_std`. alloc = ["serde/alloc"] std = ["serde/std" ] unsealed_read_write = [] tags = [] serde_cbor-0.11.2/LICENSE-APACHE000064400000000000000000000251370000000000000137250ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. serde_cbor-0.11.2/LICENSE-MIT000064400000000000000000000020330000000000000134230ustar 00000000000000Copyright (c) 2015 Pyfisch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. serde_cbor-0.11.2/README.md000064400000000000000000000071710000000000000132560ustar 00000000000000# Serde CBOR [![Build Status](https://travis-ci.org/pyfisch/cbor.svg?branch=master)](https://travis-ci.org/pyfisch/cbor) [![Crates.io](https://img.shields.io/crates/v/serde_cbor.svg)](https://crates.io/crates/serde_cbor) [![Documentation](https://docs.rs/serde_cbor/badge.svg)](https://docs.rs/serde_cbor) ## PROJECT IS ARCHIVED After almost 6 years it is time to retire this crate. This implementation of CBOR for serde is used in hundreds of projects with widely differing needs. Besides the standard features it contains code for no-std environments, a packed encoding and CBOR tags. However while these features are useful to many people they sometimes interact poorly with each others and with optional features of serde itself. Because I don't use the crate myself and because of the potential for new errors I have been reluctant to accept any changes or additional features for the crate. Since this situation is unlikely to change anytime soon and no one else stepped up to maintain this crate I am archiving the repository today. If the crate works for you there is no need to switch to another implementation. However if you encounter problems or for new projects I recommend you take a look at these crates: * [ciborium](https://crates.io/crates/ciborium) * [minicbor](https://crates.io/crates/minicbor) ~~ Pyfisch, August 2021 This crate implements the Concise Binary Object Representation from [RFC 7049]. It builds on [Serde], the generic serialization framework for Rust. CBOR provides a binary encoding for a superset of the JSON data model that is small and very fast to parse. [RFC 7049]: https://tools.ietf.org/html/rfc7049 [Serde]: https://github.com/serde-rs/serde ## Usage Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`: ```toml [dependencies] serde_cbor = "0.11.2" ``` Storing and loading Rust types is easy and requires only minimal modifications to the program code. ```rust use serde_derive::{Deserialize, Serialize}; use std::error::Error; use std::fs::File; // Types annotated with `Serialize` can be stored as CBOR. // To be able to load them again add `Deserialize`. #[derive(Debug, Serialize, Deserialize)] struct Mascot { name: String, species: String, year_of_birth: u32, } fn main() -> Result<(), Box> { let ferris = Mascot { name: "Ferris".to_owned(), species: "crab".to_owned(), year_of_birth: 2015, }; let ferris_file = File::create("examples/ferris.cbor")?; // Write Ferris to the given file. // Instead of a file you can use any type that implements `io::Write` // like a HTTP body, database connection etc. serde_cbor::to_writer(ferris_file, &ferris)?; let tux_file = File::open("examples/tux.cbor")?; // Load Tux from a file. // Serde CBOR performs roundtrip serialization meaning that // the data will not change in any way. let tux: Mascot = serde_cbor::from_reader(tux_file)?; println!("{:?}", tux); // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 } Ok(()) } ``` There are a lot of options available to customize the format. To operate on untyped CBOR values have a look at the `Value` type. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. serde_cbor-0.11.2/examples/readme.rs000064400000000000000000000022570000000000000154200ustar 00000000000000// NOTE: This file should be kept in sync with README.md use serde_derive::{Deserialize, Serialize}; use std::error::Error; use std::fs::File; // Types annotated with `Serialize` can be stored as CBOR. // To be able to load them again add `Deserialize`. #[derive(Debug, Serialize, Deserialize)] struct Mascot { name: String, species: String, year_of_birth: u32, } fn main() -> Result<(), Box> { let ferris = Mascot { name: "Ferris".to_owned(), species: "crab".to_owned(), year_of_birth: 2015, }; let ferris_file = File::create("examples/ferris.cbor")?; // Write Ferris to the given file. // Instead of a file you can use any type that implements `io::Write` // like a HTTP body, database connection etc. serde_cbor::to_writer(ferris_file, &ferris)?; let tux_file = File::open("examples/tux.cbor")?; // Load Tux from a file. // Serde CBOR performs roundtrip serialization meaning that // the data will not change in any way. let tux: Mascot = serde_cbor::from_reader(tux_file)?; println!("{:?}", tux); // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 } Ok(()) } serde_cbor-0.11.2/examples/tags.rs000064400000000000000000000053530000000000000151210ustar 00000000000000use serde::de::{Deserialize, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_cbor::tags::Tagged; use serde_cbor::Value; use serde_derive::{Deserialize, Serialize}; use std::error::Error; /// https://tools.ietf.org/html/rfc7049#section-2.4.1 #[derive(Debug, PartialEq)] struct Date(String); impl Serialize for Date { fn serialize(&self, s: S) -> Result { Tagged::new(Some(0), &self.0).serialize(s) } } impl<'de> Deserialize<'de> for Date { fn deserialize>(deserializer: D) -> Result { let tagged = Tagged::::deserialize(deserializer)?; match tagged.tag { Some(0) | None => Ok(Date(tagged.value)), Some(_) => Err(serde::de::Error::custom("unexpected tag")), } } } /// https://tools.ietf.org/html/rfc7049#section-2.4.4.3 #[derive(Debug, PartialEq)] struct Uri(String); impl Serialize for Uri { fn serialize(&self, s: S) -> Result { Tagged::new(Some(32), &self.0).serialize(s) } } impl<'de> Deserialize<'de> for Uri { fn deserialize>(deserializer: D) -> Result { let tagged = Tagged::::deserialize(deserializer)?; match tagged.tag { // allow deserialization even if there is no tag. Allows roundtrip via other formats such as json Some(0) | None => Ok(Uri(tagged.value)), Some(_) => Err(serde::de::Error::custom("unexpected tag")), } } } #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Bookmark { title: String, link: Uri, created: Date, } fn main() -> Result<(), Box> { let bookmark = Bookmark { title: "The Example Domain".into(), link: Uri("http://example.org/".into()), created: Date("2003-12-13T18:30:02Z".into()), }; // serialize the struct to bytes let bytes1 = serde_cbor::to_vec(&bookmark)?; // deserialize to a serde_cbor::Value let value1: Value = serde_cbor::from_slice(&bytes1)?; println!("{:?}", value1); // serialize the value to bytes let bytes2 = serde_cbor::to_vec(&value1)?; // deserialize to a serde_cbor::Value let value2: Value = serde_cbor::from_slice(&bytes2)?; println!("{:?}", value2); // deserialize to a Bookmark let result: Bookmark = serde_cbor::from_slice(&bytes2)?; // check that the roundtrip was successful assert_eq!(value1, value2); assert_eq!(bookmark, result); // check that going via a format that does not support tags does work // let json = serde_json::to_vec(&bookmark)?; // let result: Bookmark = serde_json::from_slice(&json)?; // assert_eq!(bookmark, result); Ok(()) } serde_cbor-0.11.2/examples/tux.cbor000064400000000000000000000000530000000000000152740ustar 00000000000000£dnamecTuxgspeciesgpenguinmyear_of_birthĢserde_cbor-0.11.2/src/de.rs000064400000000000000000001163340000000000000135260ustar 00000000000000//! Deserialization. use core::f32; use core::marker::PhantomData; use core::result; use core::str; use half::f16; use serde::de; #[cfg(feature = "std")] use std::io; use crate::error::{Error, ErrorCode, Result}; #[cfg(not(feature = "unsealed_read_write"))] use crate::read::EitherLifetime; #[cfg(feature = "unsealed_read_write")] pub use crate::read::EitherLifetime; #[cfg(feature = "std")] pub use crate::read::IoRead; use crate::read::Offset; #[cfg(any(feature = "std", feature = "alloc"))] pub use crate::read::SliceRead; pub use crate::read::{MutSliceRead, Read, SliceReadFixed}; #[cfg(feature = "tags")] use crate::tags::set_tag; /// Decodes a value from CBOR data in a slice. /// /// # Examples /// /// Deserialize a `String` /// /// ``` /// # use serde_cbor::de; /// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; /// let value: String = de::from_slice(&v[..]).unwrap(); /// assert_eq!(value, "foobar"); /// ``` /// /// Deserialize a borrowed string with zero copies. /// /// ``` /// # use serde_cbor::de; /// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; /// let value: &str = de::from_slice(&v[..]).unwrap(); /// assert_eq!(value, "foobar"); /// ``` #[cfg(any(feature = "std", feature = "alloc"))] pub fn from_slice<'a, T>(slice: &'a [u8]) -> Result where T: de::Deserialize<'a>, { let mut deserializer = Deserializer::from_slice(slice); let value = de::Deserialize::deserialize(&mut deserializer)?; deserializer.end()?; Ok(value) } // When the "std" feature is enabled there should be little to no need to ever use this function, // as `from_slice` covers all use cases (at the expense of being less efficient). /// Decode a value from CBOR data in a mutable slice. /// /// This can be used in analogy to `from_slice`. Unlike `from_slice`, this will use the slice's /// mutability to rearrange data in it in order to resolve indefinite byte or text strings without /// resorting to allocations. pub fn from_mut_slice<'a, T>(slice: &'a mut [u8]) -> Result where T: de::Deserialize<'a>, { let mut deserializer = Deserializer::from_mut_slice(slice); let value = de::Deserialize::deserialize(&mut deserializer)?; deserializer.end()?; Ok(value) } // When the "std" feature is enabled there should be little to no need to ever use this function, // as `from_slice` covers all use cases and is much more reliable (at the expense of being less // efficient). /// Decode a value from CBOR data using a scratch buffer. /// /// Users should generally prefer to use `from_slice` or `from_mut_slice` over this function, /// as decoding may fail when the scratch buffer turns out to be too small. /// /// A realistic use case for this method would be decoding in a `no_std` environment from an /// immutable slice that is too large to copy. pub fn from_slice_with_scratch<'a, 'b, T>(slice: &'a [u8], scratch: &'b mut [u8]) -> Result where T: de::Deserialize<'a>, { let mut deserializer = Deserializer::from_slice_with_scratch(slice, scratch); let value = de::Deserialize::deserialize(&mut deserializer)?; deserializer.end()?; Ok(value) } /// Decodes a value from CBOR data in a reader. /// /// # Examples /// /// Deserialize a `String` /// /// ``` /// # use serde_cbor::de; /// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; /// let value: String = de::from_reader(&v[..]).unwrap(); /// assert_eq!(value, "foobar"); /// ``` /// /// Note that `from_reader` cannot borrow data: /// /// ```compile_fail /// # use serde_cbor::de; /// let v: Vec = vec![0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]; /// let value: &str = de::from_reader(&v[..]).unwrap(); /// assert_eq!(value, "foobar"); /// ``` #[cfg(feature = "std")] pub fn from_reader(reader: R) -> Result where T: de::DeserializeOwned, R: io::Read, { let mut deserializer = Deserializer::from_reader(reader); let value = de::Deserialize::deserialize(&mut deserializer)?; deserializer.end()?; Ok(value) } /// A Serde `Deserialize`r of CBOR data. #[derive(Debug)] pub struct Deserializer { read: R, remaining_depth: u8, accept_named: bool, accept_packed: bool, accept_standard_enums: bool, accept_legacy_enums: bool, } #[cfg(feature = "std")] impl Deserializer> where R: io::Read, { /// Constructs a `Deserializer` which reads from a `Read`er. pub fn from_reader(reader: R) -> Deserializer> { Deserializer::new(IoRead::new(reader)) } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> Deserializer> { /// Constructs a `Deserializer` which reads from a slice. /// /// Borrowed strings and byte slices will be provided when possible. pub fn from_slice(bytes: &'a [u8]) -> Deserializer> { Deserializer::new(SliceRead::new(bytes)) } } impl<'a> Deserializer> { /// Constructs a `Deserializer` which reads from a mutable slice that doubles as its own /// scratch buffer. /// /// Borrowed strings and byte slices will be provided even for indefinite strings. pub fn from_mut_slice(bytes: &'a mut [u8]) -> Deserializer> { Deserializer::new(MutSliceRead::new(bytes)) } } impl<'a, 'b> Deserializer> { #[doc(hidden)] pub fn from_slice_with_scratch( bytes: &'a [u8], scratch: &'b mut [u8], ) -> Deserializer> { Deserializer::new(SliceReadFixed::new(bytes, scratch)) } } impl<'de, R> Deserializer where R: Read<'de>, { /// Constructs a `Deserializer` from one of the possible serde_cbor input sources. /// /// `from_slice` and `from_reader` should normally be used instead of this method. pub fn new(read: R) -> Self { Deserializer { read, remaining_depth: 128, accept_named: true, accept_packed: true, accept_standard_enums: true, accept_legacy_enums: true, } } /// Don't accept named variants and fields. pub fn disable_named_format(mut self) -> Self { self.accept_named = false; self } /// Don't accept numbered variants and fields. pub fn disable_packed_format(mut self) -> Self { self.accept_packed = false; self } /// Don't accept the new enum format used by `serde_cbor` versions >= v0.10. pub fn disable_standard_enums(mut self) -> Self { self.accept_standard_enums = false; self } /// Don't accept the old enum format used by `serde_cbor` versions <= v0.9. pub fn disable_legacy_enums(mut self) -> Self { self.accept_legacy_enums = false; self } /// This method should be called after a value has been deserialized to ensure there is no /// trailing data in the input source. pub fn end(&mut self) -> Result<()> { match self.next()? { Some(_) => Err(self.error(ErrorCode::TrailingData)), None => Ok(()), } } /// Turn a CBOR deserializer into an iterator over values of type T. #[allow(clippy::should_implement_trait)] // Trait doesn't allow unconstrained T. pub fn into_iter(self) -> StreamDeserializer<'de, R, T> where T: de::Deserialize<'de>, { StreamDeserializer { de: self, output: PhantomData, lifetime: PhantomData, } } fn next(&mut self) -> Result> { self.read.next() } fn peek(&mut self) -> Result> { self.read.peek() } fn consume(&mut self) { self.read.discard(); } fn error(&self, reason: ErrorCode) -> Error { let offset = self.read.offset(); Error::syntax(reason, offset) } fn parse_u8(&mut self) -> Result { match self.next()? { Some(byte) => Ok(byte), None => Err(self.error(ErrorCode::EofWhileParsingValue)), } } fn parse_u16(&mut self) -> Result { let mut buf = [0; 2]; self.read .read_into(&mut buf) .map(|()| u16::from_be_bytes(buf)) } fn parse_u32(&mut self) -> Result { let mut buf = [0; 4]; self.read .read_into(&mut buf) .map(|()| u32::from_be_bytes(buf)) } fn parse_u64(&mut self) -> Result { let mut buf = [0; 8]; self.read .read_into(&mut buf) .map(|()| u64::from_be_bytes(buf)) } fn parse_bytes(&mut self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { match self.read.read(len)? { EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf), EitherLifetime::Short(buf) => visitor.visit_bytes(buf), } } fn parse_indefinite_bytes(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { self.read.clear_buffer(); loop { let byte = self.parse_u8()?; let len = match byte { 0x40..=0x57 => byte as usize - 0x40, 0x58 => self.parse_u8()? as usize, 0x59 => self.parse_u16()? as usize, 0x5a => self.parse_u32()? as usize, 0x5b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } len as usize } 0xff => break, _ => return Err(self.error(ErrorCode::UnexpectedCode)), }; self.read.read_to_buffer(len)?; } match self.read.take_buffer() { EitherLifetime::Long(buf) => visitor.visit_borrowed_bytes(buf), EitherLifetime::Short(buf) => visitor.visit_bytes(buf), } } fn convert_str<'a>(buf: &'a [u8], buf_end_offset: u64) -> Result<&'a str> { match str::from_utf8(buf) { Ok(s) => Ok(s), Err(e) => { let shift = buf.len() - e.valid_up_to(); let offset = buf_end_offset - shift as u64; Err(Error::syntax(ErrorCode::InvalidUtf8, offset)) } } } fn parse_str(&mut self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { if let Some(offset) = self.read.offset().checked_add(len as u64) { match self.read.read(len)? { EitherLifetime::Long(buf) => { let s = Self::convert_str(buf, offset)?; visitor.visit_borrowed_str(s) } EitherLifetime::Short(buf) => { let s = Self::convert_str(buf, offset)?; visitor.visit_str(s) } } } else { // An overflow would have occured. Err(Error::syntax( ErrorCode::LengthOutOfRange, self.read.offset(), )) } } fn parse_indefinite_str(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { self.read.clear_buffer(); loop { let byte = self.parse_u8()?; let len = match byte { 0x60..=0x77 => byte as usize - 0x60, 0x78 => self.parse_u8()? as usize, 0x79 => self.parse_u16()? as usize, 0x7a => self.parse_u32()? as usize, 0x7b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } len as usize } 0xff => break, _ => return Err(self.error(ErrorCode::UnexpectedCode)), }; self.read.read_to_buffer(len)?; } let offset = self.read.offset(); match self.read.take_buffer() { EitherLifetime::Long(buf) => { let s = Self::convert_str(buf, offset)?; visitor.visit_borrowed_str(s) } EitherLifetime::Short(buf) => { let s = Self::convert_str(buf, offset)?; visitor.visit_str(s) } } } #[cfg(feature = "tags")] fn handle_tagged_value(&mut self, tag: u64, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|d| { set_tag(Some(tag)); let r = visitor.visit_newtype_struct(d); set_tag(None); r }) } #[cfg(not(feature = "tags"))] fn handle_tagged_value(&mut self, _tag: u64, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|de| de.parse_value(visitor)) } fn recursion_checked(&mut self, f: F) -> Result where F: FnOnce(&mut Deserializer) -> Result, { self.remaining_depth -= 1; if self.remaining_depth == 0 { return Err(self.error(ErrorCode::RecursionLimitExceeded)); } let r = f(self); self.remaining_depth += 1; r } fn parse_array(&mut self, mut len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|de| { let value = visitor.visit_seq(SeqAccess { de, len: &mut len })?; if len != 0 { Err(de.error(ErrorCode::TrailingData)) } else { Ok(value) } }) } fn parse_indefinite_array(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|de| { let value = visitor.visit_seq(IndefiniteSeqAccess { de })?; match de.next()? { Some(0xff) => Ok(value), Some(_) => Err(de.error(ErrorCode::TrailingData)), None => Err(de.error(ErrorCode::EofWhileParsingArray)), } }) } fn parse_map(&mut self, mut len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { let accept_packed = self.accept_packed; let accept_named = self.accept_named; self.recursion_checked(|de| { let value = visitor.visit_map(MapAccess { de, len: &mut len, accept_named, accept_packed, })?; if len != 0 { Err(de.error(ErrorCode::TrailingData)) } else { Ok(value) } }) } fn parse_indefinite_map(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let accept_named = self.accept_named; let accept_packed = self.accept_packed; self.recursion_checked(|de| { let value = visitor.visit_map(IndefiniteMapAccess { de, accept_packed, accept_named, })?; match de.next()? { Some(0xff) => Ok(value), Some(_) => Err(de.error(ErrorCode::TrailingData)), None => Err(de.error(ErrorCode::EofWhileParsingMap)), } }) } fn parse_enum(&mut self, mut len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|de| { let value = visitor.visit_enum(VariantAccess { seq: SeqAccess { de, len: &mut len }, })?; if len != 0 { Err(de.error(ErrorCode::TrailingData)) } else { Ok(value) } }) } fn parse_enum_map(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let accept_named = self.accept_named; let accept_packed = self.accept_packed; self.recursion_checked(|de| { let mut len = 1; let value = visitor.visit_enum(VariantAccessMap { map: MapAccess { de, len: &mut len, accept_packed, accept_named, }, })?; if len != 0 { Err(de.error(ErrorCode::TrailingData)) } else { Ok(value) } }) } fn parse_indefinite_enum(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { self.recursion_checked(|de| { let value = visitor.visit_enum(VariantAccess { seq: IndefiniteSeqAccess { de }, })?; match de.next()? { Some(0xff) => Ok(value), Some(_) => Err(de.error(ErrorCode::TrailingData)), None => Err(de.error(ErrorCode::EofWhileParsingArray)), } }) } fn parse_f16(&mut self) -> Result { Ok(f32::from(f16::from_bits(self.parse_u16()?))) } fn parse_f32(&mut self) -> Result { self.parse_u32().map(|i| f32::from_bits(i)) } fn parse_f64(&mut self) -> Result { self.parse_u64().map(|i| f64::from_bits(i)) } // Don't warn about the `unreachable!` in case // exhaustive integer pattern matching is enabled. #[allow(unreachable_patterns)] fn parse_value(&mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let byte = self.parse_u8()?; match byte { // Major type 0: an unsigned integer 0x00..=0x17 => visitor.visit_u8(byte), 0x18 => { let value = self.parse_u8()?; visitor.visit_u8(value) } 0x19 => { let value = self.parse_u16()?; visitor.visit_u16(value) } 0x1a => { let value = self.parse_u32()?; visitor.visit_u32(value) } 0x1b => { let value = self.parse_u64()?; visitor.visit_u64(value) } 0x1c..=0x1f => Err(self.error(ErrorCode::UnassignedCode)), // Major type 1: a negative integer 0x20..=0x37 => visitor.visit_i8(-1 - (byte - 0x20) as i8), 0x38 => { let value = self.parse_u8()?; visitor.visit_i16(-1 - i16::from(value)) } 0x39 => { let value = self.parse_u16()?; visitor.visit_i32(-1 - i32::from(value)) } 0x3a => { let value = self.parse_u32()?; visitor.visit_i64(-1 - i64::from(value)) } 0x3b => { let value = self.parse_u64()?; if value > i64::max_value() as u64 { return visitor.visit_i128(-1 - i128::from(value)); } visitor.visit_i64(-1 - value as i64) } 0x3c..=0x3f => Err(self.error(ErrorCode::UnassignedCode)), // Major type 2: a byte string 0x40..=0x57 => self.parse_bytes(byte as usize - 0x40, visitor), 0x58 => { let len = self.parse_u8()?; self.parse_bytes(len as usize, visitor) } 0x59 => { let len = self.parse_u16()?; self.parse_bytes(len as usize, visitor) } 0x5a => { let len = self.parse_u32()?; self.parse_bytes(len as usize, visitor) } 0x5b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } self.parse_bytes(len as usize, visitor) } 0x5c..=0x5e => Err(self.error(ErrorCode::UnassignedCode)), 0x5f => self.parse_indefinite_bytes(visitor), // Major type 3: a text string 0x60..=0x77 => self.parse_str(byte as usize - 0x60, visitor), 0x78 => { let len = self.parse_u8()?; self.parse_str(len as usize, visitor) } 0x79 => { let len = self.parse_u16()?; self.parse_str(len as usize, visitor) } 0x7a => { let len = self.parse_u32()?; self.parse_str(len as usize, visitor) } 0x7b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } self.parse_str(len as usize, visitor) } 0x7c..=0x7e => Err(self.error(ErrorCode::UnassignedCode)), 0x7f => self.parse_indefinite_str(visitor), // Major type 4: an array of data items 0x80..=0x97 => self.parse_array(byte as usize - 0x80, visitor), 0x98 => { let len = self.parse_u8()?; self.parse_array(len as usize, visitor) } 0x99 => { let len = self.parse_u16()?; self.parse_array(len as usize, visitor) } 0x9a => { let len = self.parse_u32()?; self.parse_array(len as usize, visitor) } 0x9b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } self.parse_array(len as usize, visitor) } 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)), 0x9f => self.parse_indefinite_array(visitor), // Major type 5: a map of pairs of data items 0xa0..=0xb7 => self.parse_map(byte as usize - 0xa0, visitor), 0xb8 => { let len = self.parse_u8()?; self.parse_map(len as usize, visitor) } 0xb9 => { let len = self.parse_u16()?; self.parse_map(len as usize, visitor) } 0xba => { let len = self.parse_u32()?; self.parse_map(len as usize, visitor) } 0xbb => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } self.parse_map(len as usize, visitor) } 0xbc..=0xbe => Err(self.error(ErrorCode::UnassignedCode)), 0xbf => self.parse_indefinite_map(visitor), // Major type 6: optional semantic tagging of other major types 0xc0..=0xd7 => { let tag = u64::from(byte) - 0xc0; self.handle_tagged_value(tag, visitor) } 0xd8 => { let tag = self.parse_u8()?; self.handle_tagged_value(tag.into(), visitor) } 0xd9 => { let tag = self.parse_u16()?; self.handle_tagged_value(tag.into(), visitor) } 0xda => { let tag = self.parse_u32()?; self.handle_tagged_value(tag.into(), visitor) } 0xdb => { let tag = self.parse_u64()?; self.handle_tagged_value(tag, visitor) } 0xdc..=0xdf => Err(self.error(ErrorCode::UnassignedCode)), // Major type 7: floating-point numbers and other simple data types that need no content 0xe0..=0xf3 => Err(self.error(ErrorCode::UnassignedCode)), 0xf4 => visitor.visit_bool(false), 0xf5 => visitor.visit_bool(true), 0xf6 => visitor.visit_unit(), 0xf7 => visitor.visit_unit(), 0xf8 => Err(self.error(ErrorCode::UnassignedCode)), 0xf9 => { let value = self.parse_f16()?; visitor.visit_f32(value) } 0xfa => { let value = self.parse_f32()?; visitor.visit_f32(value) } 0xfb => { let value = self.parse_f64()?; visitor.visit_f64(value) } 0xfc..=0xfe => Err(self.error(ErrorCode::UnassignedCode)), 0xff => Err(self.error(ErrorCode::UnexpectedCode)), _ => unreachable!(), } } } impl<'de, 'a, R> de::Deserializer<'de> for &'a mut Deserializer where R: Read<'de>, { type Error = Error; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { self.parse_value(visitor) } #[inline] fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.peek()? { Some(0xf6) => { self.consume(); visitor.visit_none() } _ => visitor.visit_some(self), } } #[inline] fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_newtype_struct(self) } // Unit variants are encoded as just the variant identifier. // Tuple variants are encoded as an array of the variant identifier followed by the fields. // Struct variants are encoded as an array of the variant identifier followed by the struct. #[inline] fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { match self.peek()? { Some(byte @ 0x80..=0x9f) => { if !self.accept_legacy_enums { return Err(self.error(ErrorCode::WrongEnumFormat)); } self.consume(); match byte { 0x80..=0x97 => self.parse_enum(byte as usize - 0x80, visitor), 0x98 => { let len = self.parse_u8()?; self.parse_enum(len as usize, visitor) } 0x99 => { let len = self.parse_u16()?; self.parse_enum(len as usize, visitor) } 0x9a => { let len = self.parse_u32()?; self.parse_enum(len as usize, visitor) } 0x9b => { let len = self.parse_u64()?; if len > usize::max_value() as u64 { return Err(self.error(ErrorCode::LengthOutOfRange)); } self.parse_enum(len as usize, visitor) } 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)), 0x9f => self.parse_indefinite_enum(visitor), _ => unreachable!(), } } Some(0xa1) => { if !self.accept_standard_enums { return Err(self.error(ErrorCode::WrongEnumFormat)); } self.consume(); self.parse_enum_map(visitor) } None => Err(self.error(ErrorCode::EofWhileParsingValue)), _ => { if !self.accept_standard_enums && !self.accept_legacy_enums { return Err(self.error(ErrorCode::WrongEnumFormat)); } visitor.visit_enum(UnitVariantAccess { de: self }) } } } #[inline] fn is_human_readable(&self) -> bool { false } serde::forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string unit unit_struct seq tuple tuple_struct map struct identifier ignored_any bytes byte_buf } } impl Deserializer where R: Offset, { /// Return the current offset in the reader #[inline] pub fn byte_offset(&self) -> usize { self.read.byte_offset() } } trait MakeError { fn error(&self, code: ErrorCode) -> Error; } struct SeqAccess<'a, R> { de: &'a mut Deserializer, len: &'a mut usize, } impl<'de, 'a, R> de::SeqAccess<'de> for SeqAccess<'a, R> where R: Read<'de>, { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: de::DeserializeSeed<'de>, { if *self.len == 0 { return Ok(None); } *self.len -= 1; let value = seed.deserialize(&mut *self.de)?; Ok(Some(value)) } fn size_hint(&self) -> Option { Some(*self.len) } } impl<'de, 'a, R> MakeError for SeqAccess<'a, R> where R: Read<'de>, { fn error(&self, code: ErrorCode) -> Error { self.de.error(code) } } struct IndefiniteSeqAccess<'a, R> { de: &'a mut Deserializer, } impl<'de, 'a, R> de::SeqAccess<'de> for IndefiniteSeqAccess<'a, R> where R: Read<'de>, { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: de::DeserializeSeed<'de>, { match self.de.peek()? { Some(0xff) => return Ok(None), Some(_) => {} None => return Err(self.de.error(ErrorCode::EofWhileParsingArray)), } let value = seed.deserialize(&mut *self.de)?; Ok(Some(value)) } } impl<'de, 'a, R> MakeError for IndefiniteSeqAccess<'a, R> where R: Read<'de>, { fn error(&self, code: ErrorCode) -> Error { self.de.error(code) } } struct MapAccess<'a, R> { de: &'a mut Deserializer, len: &'a mut usize, accept_named: bool, accept_packed: bool, } impl<'de, 'a, R> de::MapAccess<'de> for MapAccess<'a, R> where R: Read<'de>, { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: de::DeserializeSeed<'de>, { if *self.len == 0 { return Ok(None); } *self.len -= 1; match self.de.peek()? { Some(_byte @ 0x00..=0x1b) if !self.accept_packed => { return Err(self.de.error(ErrorCode::WrongStructFormat)); } Some(_byte @ 0x60..=0x7f) if !self.accept_named => { return Err(self.de.error(ErrorCode::WrongStructFormat)); } _ => {} }; let value = seed.deserialize(&mut *self.de)?; Ok(Some(value)) } fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, { seed.deserialize(&mut *self.de) } fn size_hint(&self) -> Option { Some(*self.len) } } impl<'de, 'a, R> MakeError for MapAccess<'a, R> where R: Read<'de>, { fn error(&self, code: ErrorCode) -> Error { self.de.error(code) } } struct IndefiniteMapAccess<'a, R> { de: &'a mut Deserializer, accept_packed: bool, accept_named: bool, } impl<'de, 'a, R> de::MapAccess<'de> for IndefiniteMapAccess<'a, R> where R: Read<'de>, { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: de::DeserializeSeed<'de>, { match self.de.peek()? { Some(_byte @ 0x00..=0x1b) if !self.accept_packed => { return Err(self.de.error(ErrorCode::WrongStructFormat)) } Some(_byte @ 0x60..=0x7f) if !self.accept_named => { return Err(self.de.error(ErrorCode::WrongStructFormat)) } Some(0xff) => return Ok(None), Some(_) => {} None => return Err(self.de.error(ErrorCode::EofWhileParsingMap)), } let value = seed.deserialize(&mut *self.de)?; Ok(Some(value)) } fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, { seed.deserialize(&mut *self.de) } } struct UnitVariantAccess<'a, R> { de: &'a mut Deserializer, } impl<'de, 'a, R> de::EnumAccess<'de> for UnitVariantAccess<'a, R> where R: Read<'de>, { type Error = Error; type Variant = UnitVariantAccess<'a, R>; fn variant_seed(self, seed: V) -> Result<(V::Value, UnitVariantAccess<'a, R>)> where V: de::DeserializeSeed<'de>, { let variant = seed.deserialize(&mut *self.de)?; Ok((variant, self)) } } impl<'de, 'a, R> de::VariantAccess<'de> for UnitVariantAccess<'a, R> where R: Read<'de>, { type Error = Error; fn unit_variant(self) -> Result<()> { Ok(()) } fn newtype_variant_seed(self, _seed: T) -> Result where T: de::DeserializeSeed<'de>, { Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"newtype variant", )) } fn tuple_variant(self, _len: usize, _visitor: V) -> Result where V: de::Visitor<'de>, { Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"tuple variant", )) } fn struct_variant(self, _fields: &'static [&'static str], _visitor: V) -> Result where V: de::Visitor<'de>, { Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"struct variant", )) } } struct VariantAccess { seq: T, } impl<'de, T> de::EnumAccess<'de> for VariantAccess where T: de::SeqAccess<'de, Error = Error> + MakeError, { type Error = Error; type Variant = VariantAccess; fn variant_seed(mut self, seed: V) -> Result<(V::Value, VariantAccess)> where V: de::DeserializeSeed<'de>, { let variant = match self.seq.next_element_seed(seed) { Ok(Some(variant)) => variant, Ok(None) => return Err(self.seq.error(ErrorCode::ArrayTooShort)), Err(e) => return Err(e), }; Ok((variant, self)) } } impl<'de, T> de::VariantAccess<'de> for VariantAccess where T: de::SeqAccess<'de, Error = Error> + MakeError, { type Error = Error; fn unit_variant(mut self) -> Result<()> { match self.seq.next_element() { Ok(Some(())) => Ok(()), Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooLong)), Err(e) => Err(e), } } fn newtype_variant_seed(mut self, seed: S) -> Result where S: de::DeserializeSeed<'de>, { match self.seq.next_element_seed(seed) { Ok(Some(variant)) => Ok(variant), Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)), Err(e) => Err(e), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_seq(self.seq) } fn struct_variant(mut self, _fields: &'static [&'static str], visitor: V) -> Result where V: de::Visitor<'de>, { let seed = StructVariantSeed { visitor }; match self.seq.next_element_seed(seed) { Ok(Some(variant)) => Ok(variant), Ok(None) => Err(self.seq.error(ErrorCode::ArrayTooShort)), Err(e) => Err(e), } } } struct StructVariantSeed { visitor: V, } impl<'de, V> de::DeserializeSeed<'de> for StructVariantSeed where V: de::Visitor<'de>, { type Value = V::Value; fn deserialize(self, de: D) -> result::Result where D: de::Deserializer<'de>, { de.deserialize_any(self.visitor) } } /// Iterator that deserializes a stream into multiple CBOR values. /// /// A stream deserializer can be created from any CBOR deserializer using the /// `Deserializer::into_iter` method. /// /// ``` /// # extern crate serde_cbor; /// use serde_cbor::de::Deserializer; /// use serde_cbor::value::Value; /// /// # fn main() { /// let data: Vec = vec![ /// 0x01, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, /// ]; /// let mut it = Deserializer::from_slice(&data[..]).into_iter::(); /// assert_eq!( /// Value::Integer(1), /// it.next().unwrap().unwrap() /// ); /// assert_eq!( /// Value::Text("foobar".to_string()), /// it.next().unwrap().unwrap() /// ); /// # } /// ``` #[derive(Debug)] pub struct StreamDeserializer<'de, R, T> { de: Deserializer, output: PhantomData, lifetime: PhantomData<&'de ()>, } impl<'de, R, T> StreamDeserializer<'de, R, T> where R: Read<'de>, T: de::Deserialize<'de>, { /// Create a new CBOR stream deserializer from one of the possible /// serde_cbor input sources. /// /// Typically it is more convenient to use one of these methods instead: /// /// * `Deserializer::from_slice(...).into_iter()` /// * `Deserializer::from_reader(...).into_iter()` pub fn new(read: R) -> StreamDeserializer<'de, R, T> { StreamDeserializer { de: Deserializer::new(read), output: PhantomData, lifetime: PhantomData, } } } impl<'de, R, T> StreamDeserializer<'de, R, T> where R: Offset, T: de::Deserialize<'de>, { /// Return the current offset in the reader #[inline] pub fn byte_offset(&self) -> usize { self.de.byte_offset() } } impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T> where R: Read<'de>, T: de::Deserialize<'de>, { type Item = Result; fn next(&mut self) -> Option> { match self.de.peek() { Ok(Some(_)) => Some(T::deserialize(&mut self.de)), Ok(None) => None, Err(e) => Some(Err(e)), } } } struct VariantAccessMap { map: T, } impl<'de, T> de::EnumAccess<'de> for VariantAccessMap where T: de::MapAccess<'de, Error = Error> + MakeError, { type Error = Error; type Variant = VariantAccessMap; fn variant_seed(mut self, seed: V) -> Result<(V::Value, VariantAccessMap)> where V: de::DeserializeSeed<'de>, { let variant = match self.map.next_key_seed(seed) { Ok(Some(variant)) => variant, Ok(None) => return Err(self.map.error(ErrorCode::ArrayTooShort)), Err(e) => return Err(e), }; Ok((variant, self)) } } impl<'de, T> de::VariantAccess<'de> for VariantAccessMap where T: de::MapAccess<'de, Error = Error> + MakeError, { type Error = Error; fn unit_variant(mut self) -> Result<()> { match self.map.next_value() { Ok(()) => Ok(()), Err(e) => Err(e), } } fn newtype_variant_seed(mut self, seed: S) -> Result where S: de::DeserializeSeed<'de>, { self.map.next_value_seed(seed) } fn tuple_variant(mut self, _len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { let seed = StructVariantSeed { visitor }; self.map.next_value_seed(seed) } fn struct_variant(mut self, _fields: &'static [&'static str], visitor: V) -> Result where V: de::Visitor<'de>, { let seed = StructVariantSeed { visitor }; self.map.next_value_seed(seed) } } serde_cbor-0.11.2/src/error.rs000064400000000000000000000230210000000000000142550ustar 00000000000000//! When serializing or deserializing CBOR goes wrong. use core::fmt; use core::result; use serde::de; use serde::ser; #[cfg(feature = "std")] use std::error; #[cfg(feature = "std")] use std::io; /// This type represents all possible errors that can occur when serializing or deserializing CBOR /// data. pub struct Error(ErrorImpl); /// Alias for a `Result` with the error type `serde_cbor::Error`. pub type Result = result::Result; /// Categorizes the cause of a `serde_cbor::Error`. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Category { /// The error was caused by a failure to read or write bytes on an IO stream. Io, /// The error was caused by input that was not syntactically valid CBOR. Syntax, /// The error was caused by input data that was semantically incorrect. Data, /// The error was caused by prematurely reaching the end of the input data. Eof, } impl Error { /// The byte offset at which the error occurred. pub fn offset(&self) -> u64 { self.0.offset } pub(crate) fn syntax(code: ErrorCode, offset: u64) -> Error { Error(ErrorImpl { code, offset }) } #[cfg(feature = "std")] pub(crate) fn io(error: io::Error) -> Error { Error(ErrorImpl { code: ErrorCode::Io(error), offset: 0, }) } #[cfg(all(not(feature = "std"), feature = "unsealed_read_write"))] /// Creates an error signalling that the underlying `Read` encountered an I/O error. pub fn io() -> Error { Error(ErrorImpl { code: ErrorCode::Io, offset: 0, }) } #[cfg(feature = "unsealed_read_write")] /// Creates an error signalling that the scratch buffer was too small to fit the data. pub fn scratch_too_small(offset: u64) -> Error { Error(ErrorImpl { code: ErrorCode::ScratchTooSmall, offset, }) } #[cfg(not(feature = "unsealed_read_write"))] pub(crate) fn scratch_too_small(offset: u64) -> Error { Error(ErrorImpl { code: ErrorCode::ScratchTooSmall, offset, }) } #[cfg(feature = "unsealed_read_write")] /// Creates an error with a custom message. /// /// **Note**: When the "std" feature is disabled, the message will be discarded. pub fn message(_msg: T) -> Error { #[cfg(not(feature = "std"))] { Error(ErrorImpl { code: ErrorCode::Message, offset: 0, }) } #[cfg(feature = "std")] { Error(ErrorImpl { code: ErrorCode::Message(_msg.to_string()), offset: 0, }) } } #[cfg(not(feature = "unsealed_read_write"))] pub(crate) fn message(_msg: T) -> Error { #[cfg(not(feature = "std"))] { Error(ErrorImpl { code: ErrorCode::Message, offset: 0, }) } #[cfg(feature = "std")] { Error(ErrorImpl { code: ErrorCode::Message(_msg.to_string()), offset: 0, }) } } #[cfg(feature = "unsealed_read_write")] /// Creates an error signalling that the underlying read /// encountered an end of input. pub fn eof(offset: u64) -> Error { Error(ErrorImpl { code: ErrorCode::EofWhileParsingValue, offset, }) } /// Categorizes the cause of this error. pub fn classify(&self) -> Category { match self.0.code { #[cfg(feature = "std")] ErrorCode::Message(_) => Category::Data, #[cfg(not(feature = "std"))] ErrorCode::Message => Category::Data, #[cfg(feature = "std")] ErrorCode::Io(_) => Category::Io, #[cfg(not(feature = "std"))] ErrorCode::Io => Category::Io, ErrorCode::ScratchTooSmall => Category::Io, ErrorCode::EofWhileParsingValue | ErrorCode::EofWhileParsingArray | ErrorCode::EofWhileParsingMap => Category::Eof, ErrorCode::LengthOutOfRange | ErrorCode::InvalidUtf8 | ErrorCode::UnassignedCode | ErrorCode::UnexpectedCode | ErrorCode::TrailingData | ErrorCode::ArrayTooShort | ErrorCode::ArrayTooLong | ErrorCode::RecursionLimitExceeded | ErrorCode::WrongEnumFormat | ErrorCode::WrongStructFormat => Category::Syntax, } } /// Returns true if this error was caused by a failure to read or write bytes on an IO stream. pub fn is_io(&self) -> bool { match self.classify() { Category::Io => true, _ => false, } } /// Returns true if this error was caused by input that was not syntactically valid CBOR. pub fn is_syntax(&self) -> bool { match self.classify() { Category::Syntax => true, _ => false, } } /// Returns true if this error was caused by data that was semantically incorrect. pub fn is_data(&self) -> bool { match self.classify() { Category::Data => true, _ => false, } } /// Returns true if this error was caused by prematurely reaching the end of the input data. pub fn is_eof(&self) -> bool { match self.classify() { Category::Eof => true, _ => false, } } /// Returns true if this error was caused by the scratch buffer being too small. /// /// Note this being `true` implies that `is_io()` is also `true`. pub fn is_scratch_too_small(&self) -> bool { match self.0.code { ErrorCode::ScratchTooSmall => true, _ => false, } } } #[cfg(feature = "std")] impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match self.0.code { ErrorCode::Io(ref err) => Some(err), _ => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.0.offset == 0 { fmt::Display::fmt(&self.0.code, f) } else { write!(f, "{} at offset {}", self.0.code, self.0.offset) } } } impl fmt::Debug for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, fmt) } } impl de::Error for Error { fn custom(msg: T) -> Error { Error::message(msg) } fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Error { if let de::Unexpected::Unit = unexp { Error::custom(format_args!("invalid type: null, expected {}", exp)) } else { Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) } } } impl ser::Error for Error { fn custom(msg: T) -> Error { Error::message(msg) } } #[cfg(feature = "std")] impl From for Error { fn from(e: io::Error) -> Error { Error::io(e) } } #[cfg(not(feature = "std"))] impl From for Error { fn from(_: core::fmt::Error) -> Error { Error(ErrorImpl { code: ErrorCode::Message, offset: 0, }) } } #[derive(Debug)] struct ErrorImpl { code: ErrorCode, offset: u64, } #[derive(Debug)] pub(crate) enum ErrorCode { #[cfg(feature = "std")] Message(String), #[cfg(not(feature = "std"))] Message, #[cfg(feature = "std")] Io(io::Error), #[allow(unused)] #[cfg(not(feature = "std"))] Io, ScratchTooSmall, EofWhileParsingValue, EofWhileParsingArray, EofWhileParsingMap, LengthOutOfRange, InvalidUtf8, UnassignedCode, UnexpectedCode, TrailingData, ArrayTooShort, ArrayTooLong, RecursionLimitExceeded, WrongEnumFormat, WrongStructFormat, } impl fmt::Display for ErrorCode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { #[cfg(feature = "std")] ErrorCode::Message(ref msg) => f.write_str(msg), #[cfg(not(feature = "std"))] ErrorCode::Message => f.write_str("Unknown error"), #[cfg(feature = "std")] ErrorCode::Io(ref err) => fmt::Display::fmt(err, f), #[cfg(not(feature = "std"))] ErrorCode::Io => f.write_str("Unknown I/O error"), ErrorCode::ScratchTooSmall => f.write_str("Scratch buffer too small"), ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"), ErrorCode::EofWhileParsingArray => f.write_str("EOF while parsing an array"), ErrorCode::EofWhileParsingMap => f.write_str("EOF while parsing a map"), ErrorCode::LengthOutOfRange => f.write_str("length out of range"), ErrorCode::InvalidUtf8 => f.write_str("invalid UTF-8"), ErrorCode::UnassignedCode => f.write_str("unassigned type"), ErrorCode::UnexpectedCode => f.write_str("unexpected code"), ErrorCode::TrailingData => f.write_str("trailing data"), ErrorCode::ArrayTooShort => f.write_str("array too short"), ErrorCode::ArrayTooLong => f.write_str("array too long"), ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"), ErrorCode::WrongEnumFormat => f.write_str("wrong enum format"), ErrorCode::WrongStructFormat => f.write_str("wrong struct format"), } } } serde_cbor-0.11.2/src/lib.rs000064400000000000000000000306360000000000000137040ustar 00000000000000//! CBOR and serialization. //! //! # Usage //! //! Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`: //! ```toml //! [dependencies] //! serde_cbor = "0.10" //! ``` //! //! Storing and loading Rust types is easy and requires only //! minimal modifications to the program code. //! //! ```rust //! use serde_derive::{Deserialize, Serialize}; //! use std::error::Error; //! use std::fs::File; //! //! // Types annotated with `Serialize` can be stored as CBOR. //! // To be able to load them again add `Deserialize`. //! #[derive(Debug, Serialize, Deserialize)] //! struct Mascot { //! name: String, //! species: String, //! year_of_birth: u32, //! } //! //! fn main() -> Result<(), Box> { //! let ferris = Mascot { //! name: "Ferris".to_owned(), //! species: "crab".to_owned(), //! year_of_birth: 2015, //! }; //! //! let ferris_file = File::create("examples/ferris.cbor")?; //! // Write Ferris to the given file. //! // Instead of a file you can use any type that implements `io::Write` //! // like a HTTP body, database connection etc. //! serde_cbor::to_writer(ferris_file, &ferris)?; //! //! let tux_file = File::open("examples/tux.cbor")?; //! // Load Tux from a file. //! // Serde CBOR performs roundtrip serialization meaning that //! // the data will not change in any way. //! let tux: Mascot = serde_cbor::from_reader(tux_file)?; //! //! println!("{:?}", tux); //! // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 } //! //! Ok(()) //! } //! ``` //! //! There are a lot of options available to customize the format. //! To operate on untyped CBOR values have a look at the `Value` type. //! //! # Type-based Serialization and Deserialization //! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and //! from CBOR via the serialization API. To be able to serialize a piece of data, it must implement //! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the //! `serde::Deserialize` trait. Serde provides an annotation to automatically generate the //! code for these traits: `#[derive(Serialize, Deserialize)]`. //! //! The CBOR API also provides an enum `serde_cbor::Value`. //! //! # Packed Encoding //! When serializing structs or enums in CBOR the keys or enum variant names will be serialized //! as string keys to a map. Especially in embedded environments this can increase the file //! size too much. In packed encoding all struct keys, as well as any enum variant that has no data, //! will be serialized as variable sized integers. The first 24 entries in any struct consume only a //! single byte! Packed encoding uses serde's preferred [externally tagged enum //! format](https://serde.rs/enum-representations.html) and therefore serializes enum variant names //! as string keys when that variant contains data. So, in the packed encoding example, `FirstVariant` //! encodes to a single byte, but encoding `SecondVariant` requires 16 bytes. //! //! To serialize a document in this format use `Serializer::new(writer).packed_format()` or //! the shorthand `ser::to_vec_packed`. The deserialization works without any changes. //! //! If you would like to omit the enum variant encoding for all variants, including ones that //! contain data, you can add `legacy_enums()` in addition to `packed_format()`, as can seen //! in the Serialize using minimal encoding example. //! //! # Self describing documents //! In some contexts different formats are used but there is no way to declare the format used //! out of band. For this reason CBOR has a magic number that may be added before any document. //! Self describing documents are created with `serializer.self_describe()`. //! //! # Examples //! Read a CBOR value that is known to be a map of string keys to string values and print it. //! //! ```rust //! use std::collections::BTreeMap; //! use serde_cbor::from_slice; //! //! let slice = b"\xa5aaaAabaBacaCadaDaeaE"; //! let value: BTreeMap = from_slice(slice).unwrap(); //! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"} //! ``` //! //! Read a general CBOR value with an unknown content. //! //! ```rust //! use serde_cbor::from_slice; //! use serde_cbor::value::Value; //! //! let slice = b"\x82\x01\xa1aaab"; //! let value: Value = from_slice(slice).unwrap(); //! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})]) //! ``` //! //! Serialize an object. //! //! ```rust //! use std::collections::BTreeMap; //! use serde_cbor::to_vec; //! //! let mut programming_languages = BTreeMap::new(); //! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]); //! programming_languages.insert("python", vec!["powerful", "friendly", "open"]); //! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]); //! let encoded = to_vec(&programming_languages); //! assert_eq!(encoded.unwrap().len(), 103); //! ``` //! //! Deserializing data in the middle of a slice //! ``` //! # extern crate serde_cbor; //! use serde_cbor::Deserializer; //! //! # fn main() { //! let data: Vec = vec![ //! 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, //! 0x61, 0x72, //! ]; //! let mut deserializer = Deserializer::from_slice(&data); //! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer) //! .unwrap(); //! let rest = &data[deserializer.byte_offset()..]; //! assert_eq!(value, "foobar"); //! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); //! # } //! ``` //! //! Serialize using packed encoding //! //! ```rust //! use serde_derive::{Deserialize, Serialize}; //! use serde_cbor::ser::to_vec_packed; //! use WithTwoVariants::*; //! //! #[derive(Debug, Serialize, Deserialize)] //! enum WithTwoVariants { //! FirstVariant, //! SecondVariant(u8), //! } //! //! let cbor = to_vec_packed(&FirstVariant).unwrap(); //! assert_eq!(cbor.len(), 1); //! //! let cbor = to_vec_packed(&SecondVariant(0)).unwrap(); //! assert_eq!(cbor.len(), 16); // Includes 13 bytes of "SecondVariant" //! ``` //! //! Serialize using minimal encoding //! //! ```rust //! use serde_derive::{Deserialize, Serialize}; //! use serde_cbor::{Result, Serializer, ser::{self, IoWrite}}; //! use WithTwoVariants::*; //! //! fn to_vec_minimal(value: &T) -> Result> //! where //! T: serde::Serialize, //! { //! let mut vec = Vec::new(); //! value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format().legacy_enums())?; //! Ok(vec) //! } //! //! #[derive(Debug, Serialize, Deserialize)] //! enum WithTwoVariants { //! FirstVariant, //! SecondVariant(u8), //! } //! //! let cbor = to_vec_minimal(&FirstVariant).unwrap(); //! assert_eq!(cbor.len(), 1); //! //! let cbor = to_vec_minimal(&SecondVariant(0)).unwrap(); //! assert_eq!(cbor.len(), 3); //! ``` //! //! # `no-std` support //! //! Serde CBOR supports building in a `no_std` context, use the following lines //! in your `Cargo.toml` dependencies: //! ``` toml //! [dependencies] //! serde = { version = "1.0", default-features = false } //! serde_cbor = { version = "0.10", default-features = false } //! ``` //! //! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer] //! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc` //! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust. //! //! [alloc-lib]: https://doc.rust-lang.org/alloc/ //! //! *Note*: to use derive macros in serde you will need to declare `serde` //! dependency like so: //! ``` toml //! serde = { version = "1.0", default-features = false, features = ["derive"] } //! ``` //! //! Serialize an object with `no_std` and without `alloc`. //! ``` rust //! # #[macro_use] extern crate serde_derive; //! # fn main() -> Result<(), serde_cbor::Error> { //! use serde::Serialize; //! use serde_cbor::Serializer; //! use serde_cbor::ser::SliceWrite; //! //! #[derive(Serialize)] //! struct User { //! user_id: u32, //! password_hash: [u8; 4], //! } //! //! let mut buf = [0u8; 100]; //! let writer = SliceWrite::new(&mut buf[..]); //! let mut ser = Serializer::new(writer); //! let user = User { //! user_id: 42, //! password_hash: [1, 2, 3, 4], //! }; //! user.serialize(&mut ser)?; //! let writer = ser.into_inner(); //! let size = writer.bytes_written(); //! let expected = [ //! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, //! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, //! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 //! ]; //! assert_eq!(&buf[..size], expected); //! # Ok(()) //! # } //! ``` //! //! Deserialize an object. //! ``` rust //! # #[macro_use] extern crate serde_derive; //! # fn main() -> Result<(), serde_cbor::Error> { //! #[derive(Debug, PartialEq, Deserialize)] //! struct User { //! user_id: u32, //! password_hash: [u8; 4], //! } //! //! let value = [ //! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, //! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, //! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 //! ]; //! //! // from_slice_with_scratch will not alter input data, use it whenever you //! // borrow from somewhere else. //! // You will have to size your scratch according to the input data you //! // expect. //! use serde_cbor::de::from_slice_with_scratch; //! let mut scratch = [0u8; 32]; //! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?; //! assert_eq!(user, User { //! user_id: 42, //! password_hash: [1, 2, 3, 4], //! }); //! //! let mut value = [ //! 0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d, //! 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, //! 0x68, 0x84, 0x1, 0x2, 0x3, 0x4 //! ]; //! //! // from_mut_slice will move data around the input slice, you may only use it //! // on data you may own or can modify. //! use serde_cbor::de::from_mut_slice; //! let user: User = from_mut_slice(&mut value[..])?; //! assert_eq!(user, User { //! user_id: 42, //! password_hash: [1, 2, 3, 4], //! }); //! # Ok(()) //! # } //! ``` //! //! # Limitations //! //! While Serde CBOR strives to support all features of Serde and CBOR //! there are a few limitations. //! //! * [Tags] are ignored during deserialization and can't be emitted during //! serialization. This is because Serde has no concept of tagged //! values. See: [#3] //! * Unknown [simple values] cause an `UnassignedCode` error. //! The simple values *False* and *True* are recognized and parsed as bool. //! *Null* and *Undefined* are both deserialized as *unit*. //! The *unit* type is serialized as *Null*. See: [#86] //! * [128-bit integers] can't be directly encoded in CBOR. If you need them //! store them as a byte string. See: [#77] //! //! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4 //! [#3]: https://github.com/pyfisch/cbor/issues/3 //! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5 //! [#86]: https://github.com/pyfisch/cbor/issues/86 //! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html //! [#77]: https://github.com/pyfisch/cbor/issues/77 #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] // When we are running tests in no_std mode we need to explicitly link std, because `cargo test` // will not work without it. #[cfg(all(not(feature = "std"), test))] extern crate std; #[cfg(feature = "alloc")] extern crate alloc; pub mod de; pub mod error; mod read; pub mod ser; pub mod tags; mod write; #[cfg(feature = "std")] pub mod value; // Re-export the [items recommended by serde](https://serde.rs/conventions.html). #[doc(inline)] pub use crate::de::{Deserializer, StreamDeserializer}; #[doc(inline)] pub use crate::error::{Error, Result}; #[doc(inline)] pub use crate::ser::Serializer; // Convenience functions for serialization and deserialization. // These functions are only available in `std` mode. #[cfg(feature = "std")] #[doc(inline)] pub use crate::de::from_reader; #[cfg(any(feature = "std", feature = "alloc"))] #[doc(inline)] pub use crate::de::from_slice; #[cfg(any(feature = "std", feature = "alloc"))] #[doc(inline)] pub use crate::ser::to_vec; #[cfg(feature = "std")] #[doc(inline)] pub use crate::ser::to_writer; // Re-export the value type like serde_json #[cfg(feature = "std")] #[doc(inline)] pub use crate::value::Value; serde_cbor-0.11.2/src/read.rs000064400000000000000000000435440000000000000140530ustar 00000000000000#[cfg(feature = "alloc")] use alloc::{vec, vec::Vec}; #[cfg(feature = "std")] use core::cmp; use core::mem; #[cfg(feature = "std")] use std::io::{self, Read as StdRead}; use crate::error::{Error, ErrorCode, Result}; #[cfg(not(feature = "unsealed_read_write"))] /// Trait used by the deserializer for iterating over input. /// /// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound /// to allow objects outside of this crate to implement this trait. pub trait Read<'de>: private::Sealed { #[doc(hidden)] /// Read n bytes from the input. /// /// Implementations that can are asked to return a slice with a Long lifetime that outlives the /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can /// return it with a Short lifetime that just lives for the time of read's mutable borrow of /// the reader. /// /// This may, as a side effect, clear the reader's scratch buffer (as the provided /// implementation does). // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and // downgrates that reference to an immutable one that outlives the result (protecting the // scratch buffer from changes), but alas, that can't be expressed (yet?). fn read<'a>(&'a mut self, n: usize) -> Result> { self.clear_buffer(); self.read_to_buffer(n)?; Ok(self.take_buffer()) } #[doc(hidden)] fn next(&mut self) -> Result>; #[doc(hidden)] fn peek(&mut self) -> Result>; #[doc(hidden)] fn clear_buffer(&mut self); #[doc(hidden)] fn read_to_buffer(&mut self, n: usize) -> Result<()>; #[doc(hidden)] fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; #[doc(hidden)] fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; #[doc(hidden)] fn discard(&mut self); #[doc(hidden)] fn offset(&self) -> u64; } #[cfg(feature = "unsealed_read_write")] /// Trait used by the deserializer for iterating over input. pub trait Read<'de> { /// Read n bytes from the input. /// /// Implementations that can are asked to return a slice with a Long lifetime that outlives the /// decoder, but others (eg. ones that need to allocate the data into a temporary buffer) can /// return it with a Short lifetime that just lives for the time of read's mutable borrow of /// the reader. /// /// This may, as a side effect, clear the reader's scratch buffer (as the provided /// implementation does). // A more appropriate lifetime setup for this (that would allow the Deserializer::convert_str // to stay a function) would be something like `fn read<'a, 'r: 'a>(&'a mut 'r immut self, ...) -> ... // EitherLifetime<'r, 'de>>`, which borrows self mutably for the duration of the function and // downgrates that reference to an immutable one that outlives the result (protecting the // scratch buffer from changes), but alas, that can't be expressed (yet?). fn read<'a>(&'a mut self, n: usize) -> Result> { self.clear_buffer(); self.read_to_buffer(n)?; Ok(self.take_buffer()) } /// Read the next byte from the input, if any. fn next(&mut self) -> Result>; /// Peek at the next byte of the input, if any. This does not advance the reader, so the result /// of this function will remain the same until a read or clear occurs. fn peek(&mut self) -> Result>; /// Clear the underlying scratch buffer fn clear_buffer(&mut self); /// Append n bytes from the reader to the reader's scratch buffer (without clearing it) fn read_to_buffer(&mut self, n: usize) -> Result<()>; /// Read out everything accumulated in the reader's scratch buffer. This may, as a side effect, /// clear it. fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de>; /// Read from the input until `buf` is full or end of input is encountered. fn read_into(&mut self, buf: &mut [u8]) -> Result<()>; /// Discard any data read by `peek`. fn discard(&mut self); /// Returns the offset from the start of the reader. fn offset(&self) -> u64; } /// Represents a reader that can return its current position pub trait Offset { fn byte_offset(&self) -> usize; } /// Represents a buffer with one of two lifetimes. pub enum EitherLifetime<'short, 'long> { /// The short lifetime Short(&'short [u8]), /// The long lifetime Long(&'long [u8]), } #[cfg(not(feature = "unsealed_read_write"))] mod private { pub trait Sealed {} } /// CBOR input source that reads from a std::io input stream. #[cfg(feature = "std")] #[derive(Debug)] pub struct IoRead where R: io::Read, { reader: OffsetReader, scratch: Vec, ch: Option, } #[cfg(feature = "std")] impl IoRead where R: io::Read, { /// Creates a new CBOR input source to read from a std::io input stream. pub fn new(reader: R) -> IoRead { IoRead { reader: OffsetReader { reader, offset: 0 }, scratch: vec![], ch: None, } } #[inline] fn next_inner(&mut self) -> Result> { let mut buf = [0; 1]; loop { match self.reader.read(&mut buf) { Ok(0) => return Ok(None), Ok(_) => return Ok(Some(buf[0])), Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => return Err(Error::io(e)), } } } } #[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] impl private::Sealed for IoRead where R: io::Read {} #[cfg(feature = "std")] impl<'de, R> Read<'de> for IoRead where R: io::Read, { #[inline] fn next(&mut self) -> Result> { match self.ch.take() { Some(ch) => Ok(Some(ch)), None => self.next_inner(), } } #[inline] fn peek(&mut self) -> Result> { match self.ch { Some(ch) => Ok(Some(ch)), None => { self.ch = self.next_inner()?; Ok(self.ch) } } } fn read_to_buffer(&mut self, mut n: usize) -> Result<()> { // defend against malicious input pretending to be huge strings by limiting growth self.scratch.reserve(cmp::min(n, 16 * 1024)); if n == 0 { return Ok(()); } if let Some(ch) = self.ch.take() { self.scratch.push(ch); n -= 1; } // n == 0 is OK here and needs no further special treatment let transfer_result = { // Prepare for take() (which consumes its reader) by creating a reference adaptor // that'll only live in this block let reference = self.reader.by_ref(); // Append the first n bytes of the reader to the scratch vector (or up to // an error or EOF indicated by a shorter read) let mut taken = reference.take(n as u64); taken.read_to_end(&mut self.scratch) }; match transfer_result { Ok(r) if r == n => Ok(()), Ok(_) => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.offset(), )), Err(e) => Err(Error::io(e)), } } fn clear_buffer(&mut self) { self.scratch.clear(); } fn take_buffer<'a>(&'a mut self) -> EitherLifetime<'a, 'de> { EitherLifetime::Short(&self.scratch) } fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { self.reader.read_exact(buf).map_err(|e| { if e.kind() == io::ErrorKind::UnexpectedEof { Error::syntax(ErrorCode::EofWhileParsingValue, self.offset()) } else { Error::io(e) } }) } #[inline] fn discard(&mut self) { self.ch = None; } fn offset(&self) -> u64 { self.reader.offset } } #[cfg(feature = "std")] impl Offset for IoRead where R: std::io::Read, { fn byte_offset(&self) -> usize { self.offset() as usize } } #[cfg(feature = "std")] #[derive(Debug)] struct OffsetReader { reader: R, offset: u64, } #[cfg(feature = "std")] impl io::Read for OffsetReader where R: io::Read, { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { let r = self.reader.read(buf); if let Ok(count) = r { self.offset += count as u64; } r } } /// A CBOR input source that reads from a slice of bytes. #[cfg(any(feature = "std", feature = "alloc"))] #[derive(Debug)] pub struct SliceRead<'a> { slice: &'a [u8], scratch: Vec, index: usize, } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> SliceRead<'a> { /// Creates a CBOR input source to read from a slice of bytes. pub fn new(slice: &'a [u8]) -> SliceRead<'a> { SliceRead { slice, scratch: vec![], index: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> Offset for SliceRead<'a> { #[inline] fn byte_offset(&self) -> usize { self.index } } #[cfg(all( any(feature = "std", feature = "alloc"), not(feature = "unsealed_read_write") ))] impl<'a> private::Sealed for SliceRead<'a> {} #[cfg(any(feature = "std", feature = "alloc"))] impl<'a> Read<'a> for SliceRead<'a> { #[inline] fn next(&mut self) -> Result> { Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.scratch.clear(); } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.scratch.extend_from_slice(slice); self.index = end; Ok(()) } #[inline] fn read<'b>(&'b mut self, n: usize) -> Result> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.index = end; Ok(EitherLifetime::Long(slice)) } fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { EitherLifetime::Short(&self.scratch) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { self.index as u64 } } /// A CBOR input source that reads from a slice of bytes using a fixed size scratch buffer. /// /// [`SliceRead`](struct.SliceRead.html) and [`MutSliceRead`](struct.MutSliceRead.html) are usually /// preferred over this, as they can handle indefinite length items. #[derive(Debug)] pub struct SliceReadFixed<'a, 'b> { slice: &'a [u8], scratch: &'b mut [u8], index: usize, scratch_index: usize, } impl<'a, 'b> SliceReadFixed<'a, 'b> { /// Creates a CBOR input source to read from a slice of bytes, backed by a scratch buffer. pub fn new(slice: &'a [u8], scratch: &'b mut [u8]) -> SliceReadFixed<'a, 'b> { SliceReadFixed { slice, scratch, index: 0, scratch_index: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } fn scratch_end(&self, n: usize) -> Result { match self.scratch_index.checked_add(n) { Some(end) if end <= self.scratch.len() => Ok(end), _ => Err(Error::scratch_too_small(self.index as u64)), } } } #[cfg(not(feature = "unsealed_read_write"))] impl<'a, 'b> private::Sealed for SliceReadFixed<'a, 'b> {} impl<'a, 'b> Read<'a> for SliceReadFixed<'a, 'b> { #[inline] fn next(&mut self) -> Result> { Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.scratch_index = 0; } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; let scratch_end = self.scratch_end(n)?; let slice = &self.slice[self.index..end]; self.scratch[self.scratch_index..scratch_end].copy_from_slice(&slice); self.index = end; self.scratch_index = scratch_end; Ok(()) } fn read<'c>(&'c mut self, n: usize) -> Result> { let end = self.end(n)?; let slice = &self.slice[self.index..end]; self.index = end; Ok(EitherLifetime::Long(slice)) } fn take_buffer<'c>(&'c mut self) -> EitherLifetime<'c, 'a> { EitherLifetime::Short(&self.scratch[0..self.scratch_index]) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { self.index as u64 } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'b> Offset for SliceReadFixed<'a, 'b> { #[inline] fn byte_offset(&self) -> usize { self.index } } /// A CBOR input source that reads from a slice of bytes, and can move data around internally to /// reassemble indefinite strings without the need of an allocated scratch buffer. #[derive(Debug)] pub struct MutSliceRead<'a> { /// A complete view of the reader's data. It is promised that bytes before buffer_end are not /// mutated any more. slice: &'a mut [u8], /// Read cursor position in slice index: usize, /// Number of bytes already discarded from the slice before: usize, /// End of the buffer area that contains all bytes read_into_buffer. This is always <= index. buffer_end: usize, } impl<'a> MutSliceRead<'a> { /// Creates a CBOR input source to read from a slice of bytes. pub fn new(slice: &'a mut [u8]) -> MutSliceRead<'a> { MutSliceRead { slice, index: 0, before: 0, buffer_end: 0, } } fn end(&self, n: usize) -> Result { match self.index.checked_add(n) { Some(end) if end <= self.slice.len() => Ok(end), _ => Err(Error::syntax( ErrorCode::EofWhileParsingValue, self.slice.len() as u64, )), } } } #[cfg(not(feature = "unsealed_read_write"))] impl<'a> private::Sealed for MutSliceRead<'a> {} impl<'a> Read<'a> for MutSliceRead<'a> { #[inline] fn next(&mut self) -> Result> { // This is duplicated from SliceRead, can that be eased? Ok(if self.index < self.slice.len() { let ch = self.slice[self.index]; self.index += 1; Some(ch) } else { None }) } #[inline] fn peek(&mut self) -> Result> { // This is duplicated from SliceRead, can that be eased? Ok(if self.index < self.slice.len() { Some(self.slice[self.index]) } else { None }) } fn clear_buffer(&mut self) { self.slice = &mut mem::replace(&mut self.slice, &mut [])[self.index..]; self.before += self.index; self.index = 0; self.buffer_end = 0; } fn read_to_buffer(&mut self, n: usize) -> Result<()> { let end = self.end(n)?; debug_assert!( self.buffer_end <= self.index, "MutSliceRead invariant violated: scratch buffer exceeds index" ); self.slice[self.buffer_end..end].rotate_left(self.index - self.buffer_end); self.buffer_end += n; self.index = end; Ok(()) } fn take_buffer<'b>(&'b mut self) -> EitherLifetime<'b, 'a> { let (left, right) = mem::replace(&mut self.slice, &mut []).split_at_mut(self.index); self.slice = right; self.before += self.index; self.index = 0; let left = &left[..self.buffer_end]; self.buffer_end = 0; EitherLifetime::Long(left) } #[inline] fn read_into(&mut self, buf: &mut [u8]) -> Result<()> { // This is duplicated from SliceRead, can that be eased? let end = self.end(buf.len())?; buf.copy_from_slice(&self.slice[self.index..end]); self.index = end; Ok(()) } #[inline] fn discard(&mut self) { self.index += 1; } fn offset(&self) -> u64 { (self.before + self.index) as u64 } } serde_cbor-0.11.2/src/ser.rs000064400000000000000000000447270000000000000137350ustar 00000000000000//! Serialize a Rust data structure to CBOR data. #[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(feature = "std")] pub use crate::write::IoWrite; pub use crate::write::{SliceWrite, Write}; use crate::error::{Error, Result}; use half::f16; use serde::ser::{self, Serialize}; #[cfg(feature = "std")] use std::io; use crate::tags::{get_tag, CBOR_NEWTYPE_NAME}; /// Serializes a value to a vector. #[cfg(any(feature = "std", feature = "alloc"))] pub fn to_vec(value: &T) -> Result> where T: ser::Serialize, { let mut vec = Vec::new(); value.serialize(&mut Serializer::new(&mut vec))?; Ok(vec) } /// Serializes a value to a vector in packed format. #[cfg(feature = "std")] pub fn to_vec_packed(value: &T) -> Result> where T: ser::Serialize, { let mut vec = Vec::new(); value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format())?; Ok(vec) } /// Serializes a value to a writer. #[cfg(feature = "std")] pub fn to_writer(writer: W, value: &T) -> Result<()> where W: io::Write, T: ser::Serialize, { value.serialize(&mut Serializer::new(&mut IoWrite::new(writer))) } /// A structure for serializing Rust values to CBOR. #[derive(Debug)] pub struct Serializer { writer: W, packed: bool, enum_as_map: bool, } impl Serializer where W: Write, { /// Creates a new CBOR serializer. /// /// `to_vec` and `to_writer` should normally be used instead of this method. #[inline] pub fn new(writer: W) -> Self { Serializer { writer, packed: false, enum_as_map: true, } } /// Choose concise/packed format for serializer. /// /// In the packed format enum variant names and field names /// are replaced with numeric indizes to conserve space. pub fn packed_format(mut self) -> Self { self.packed = true; self } /// Enable old enum format used by `serde_cbor` versions <= v0.9. /// /// The `legacy_enums` option determines how enums are encoded. /// /// This makes no difference when encoding and decoding enums using /// this crate, but it shows up when decoding to a `Value` or decoding /// in other languages. /// /// # Examples /// /// Given the following enum /// /// ```rust /// enum Enum { /// Unit, /// NewType(i32), /// Tuple(String, bool), /// Struct{ x: i32, y: i32 }, /// } /// ``` /// we will give the `Value` with the same encoding for each case using /// JSON notation. /// /// ## Default encodings /// /// * `Enum::Unit` encodes as `"Unit"` /// * `Enum::NewType(10)` encodes as `{"NewType": 10}` /// * `Enum::Tuple("x", true)` encodes as `{"Tuple": ["x", true]}` /// /// ## Legacy encodings /// /// * `Enum::Unit` encodes as `"Unit"` /// * `Enum::NewType(10)` encodes as `["NewType", 10]` /// * `Enum::Tuple("x", true)` encodes as `["Tuple", "x", true]` /// * `Enum::Struct{ x: 5, y: -5 }` encodes as `["Struct", {"x": 5, "y": -5}]` pub fn legacy_enums(mut self) -> Self { self.enum_as_map = false; self } /// Writes a CBOR self-describe tag to the stream. /// /// Tagging allows a decoder to distinguish different file formats based on their content /// without further information. #[inline] pub fn self_describe(&mut self) -> Result<()> { let mut buf = [6 << 5 | 25, 0, 0]; (&mut buf[1..]).copy_from_slice(&55799u16.to_be_bytes()); self.writer.write_all(&buf).map_err(|e| e.into()) } /// Unwrap the `Writer` from the `Serializer`. #[inline] pub fn into_inner(self) -> W { self.writer } #[inline] fn write_u8(&mut self, major: u8, value: u8) -> Result<()> { if value <= 0x17 { self.writer.write_all(&[major << 5 | value]) } else { let buf = [major << 5 | 24, value]; self.writer.write_all(&buf) } .map_err(|e| e.into()) } #[inline] fn write_u16(&mut self, major: u8, value: u16) -> Result<()> { if value <= u16::from(u8::max_value()) { self.write_u8(major, value as u8) } else { let mut buf = [major << 5 | 25, 0, 0]; (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); self.writer.write_all(&buf).map_err(|e| e.into()) } } #[inline] fn write_u32(&mut self, major: u8, value: u32) -> Result<()> { if value <= u32::from(u16::max_value()) { self.write_u16(major, value as u16) } else { let mut buf = [major << 5 | 26, 0, 0, 0, 0]; (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); self.writer.write_all(&buf).map_err(|e| e.into()) } } #[inline] fn write_u64(&mut self, major: u8, value: u64) -> Result<()> { if value <= u64::from(u32::max_value()) { self.write_u32(major, value as u32) } else { let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0]; (&mut buf[1..]).copy_from_slice(&value.to_be_bytes()); self.writer.write_all(&buf).map_err(|e| e.into()) } } #[inline] fn serialize_collection<'a>( &'a mut self, major: u8, len: Option, ) -> Result> { let needs_eof = match len { Some(len) => { self.write_u64(major, len as u64)?; false } None => { self.writer .write_all(&[major << 5 | 31]) .map_err(|e| e.into())?; true } }; Ok(CollectionSerializer { ser: self, needs_eof, }) } } impl<'a, W> ser::Serializer for &'a mut Serializer where W: Write, { type Ok = (); type Error = Error; type SerializeSeq = CollectionSerializer<'a, W>; type SerializeTuple = &'a mut Serializer; type SerializeTupleStruct = &'a mut Serializer; type SerializeTupleVariant = &'a mut Serializer; type SerializeMap = CollectionSerializer<'a, W>; type SerializeStruct = StructSerializer<'a, W>; type SerializeStructVariant = StructSerializer<'a, W>; #[inline] fn serialize_bool(self, value: bool) -> Result<()> { let value = if value { 0xf5 } else { 0xf4 }; self.writer.write_all(&[value]).map_err(|e| e.into()) } #[inline] fn serialize_i8(self, value: i8) -> Result<()> { if value < 0 { self.write_u8(1, -(value + 1) as u8) } else { self.write_u8(0, value as u8) } } #[inline] fn serialize_i16(self, value: i16) -> Result<()> { if value < 0 { self.write_u16(1, -(value + 1) as u16) } else { self.write_u16(0, value as u16) } } #[inline] fn serialize_i32(self, value: i32) -> Result<()> { if value < 0 { self.write_u32(1, -(value + 1) as u32) } else { self.write_u32(0, value as u32) } } #[inline] fn serialize_i64(self, value: i64) -> Result<()> { if value < 0 { self.write_u64(1, -(value + 1) as u64) } else { self.write_u64(0, value as u64) } } #[inline] fn serialize_i128(self, value: i128) -> Result<()> { if value < 0 { if -(value + 1) > i128::from(u64::max_value()) { return Err(Error::message("The number can't be stored in CBOR")); } self.write_u64(1, -(value + 1) as u64) } else { if value > i128::from(u64::max_value()) { return Err(Error::message("The number can't be stored in CBOR")); } self.write_u64(0, value as u64) } } #[inline] fn serialize_u8(self, value: u8) -> Result<()> { self.write_u8(0, value) } #[inline] fn serialize_u16(self, value: u16) -> Result<()> { self.write_u16(0, value) } #[inline] fn serialize_u32(self, value: u32) -> Result<()> { self.write_u32(0, value) } #[inline] fn serialize_u64(self, value: u64) -> Result<()> { self.write_u64(0, value) } #[inline] fn serialize_u128(self, value: u128) -> Result<()> { if value > u128::from(u64::max_value()) { return Err(Error::message("The number can't be stored in CBOR")); } self.write_u64(0, value as u64) } #[inline] #[allow(clippy::float_cmp)] fn serialize_f32(self, value: f32) -> Result<()> { if value.is_infinite() { if value.is_sign_positive() { self.writer.write_all(&[0xf9, 0x7c, 0x00]) } else { self.writer.write_all(&[0xf9, 0xfc, 0x00]) } } else if value.is_nan() { self.writer.write_all(&[0xf9, 0x7e, 0x00]) } else if f32::from(f16::from_f32(value)) == value { let mut buf = [0xf9, 0, 0]; (&mut buf[1..]).copy_from_slice(&f16::from_f32(value).to_bits().to_be_bytes()); self.writer.write_all(&buf) } else { let mut buf = [0xfa, 0, 0, 0, 0]; (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes()); self.writer.write_all(&buf) } .map_err(|e| e.into()) } #[inline] #[allow(clippy::float_cmp)] fn serialize_f64(self, value: f64) -> Result<()> { if !value.is_finite() || f64::from(value as f32) == value { self.serialize_f32(value as f32) } else { let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0]; (&mut buf[1..]).copy_from_slice(&value.to_bits().to_be_bytes()); self.writer.write_all(&buf).map_err(|e| e.into()) } } #[inline] fn serialize_char(self, value: char) -> Result<()> { // A char encoded as UTF-8 takes 4 bytes at most. let mut buf = [0; 4]; self.serialize_str(value.encode_utf8(&mut buf)) } #[inline] fn serialize_str(self, value: &str) -> Result<()> { self.write_u64(3, value.len() as u64)?; self.writer .write_all(value.as_bytes()) .map_err(|e| e.into()) } #[inline] fn serialize_bytes(self, value: &[u8]) -> Result<()> { self.write_u64(2, value.len() as u64)?; self.writer.write_all(value).map_err(|e| e.into()) } #[inline] fn serialize_unit(self) -> Result<()> { self.serialize_none() } #[inline] fn serialize_some(self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(self) } #[inline] fn serialize_none(self) -> Result<()> { self.writer.write_all(&[0xf6]).map_err(|e| e.into()) } #[inline] fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { self.serialize_unit() } #[inline] fn serialize_unit_variant( self, _name: &'static str, variant_index: u32, variant: &'static str, ) -> Result<()> { if self.packed { self.serialize_u32(variant_index) } else { self.serialize_str(variant) } } #[inline] fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { if name == CBOR_NEWTYPE_NAME { for tag in get_tag().into_iter() { self.write_u64(6, tag)?; } } value.serialize(self) } #[inline] fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result<()> where T: ?Sized + ser::Serialize, { if self.enum_as_map { self.write_u64(5, 1u64)?; variant.serialize(&mut *self)?; } else { self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; self.serialize_unit_variant(name, variant_index, variant)?; } value.serialize(self) } #[inline] fn serialize_seq(self, len: Option) -> Result> { self.serialize_collection(4, len) } #[inline] fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer> { self.write_u64(4, len as u64)?; Ok(self) } #[inline] fn serialize_tuple_struct( self, _name: &'static str, len: usize, ) -> Result<&'a mut Serializer> { self.serialize_tuple(len) } #[inline] fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result<&'a mut Serializer> { if self.enum_as_map { self.write_u64(5, 1u64)?; variant.serialize(&mut *self)?; self.serialize_tuple(len) } else { self.write_u64(4, (len + 1) as u64)?; self.serialize_unit_variant(name, variant_index, variant)?; Ok(self) } } #[inline] fn serialize_map(self, len: Option) -> Result> { self.serialize_collection(5, len) } #[cfg(not(feature = "std"))] fn collect_str(self, value: &T) -> Result<()> where T: core::fmt::Display, { use crate::write::FmtWrite; use core::fmt::Write; let mut w = FmtWrite::new(&mut self.writer); write!(w, "{}", value)?; Ok(()) } #[inline] fn serialize_struct(self, _name: &'static str, len: usize) -> Result> { self.write_u64(5, len as u64)?; Ok(StructSerializer { ser: self, idx: 0 }) } #[inline] fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result> { if self.enum_as_map { self.write_u64(5, 1u64)?; } else { self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; } self.serialize_unit_variant(name, variant_index, variant)?; self.serialize_struct(name, len) } #[inline] fn is_human_readable(&self) -> bool { false } } impl<'a, W> ser::SerializeTuple for &'a mut Serializer where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut **self) } #[inline] fn end(self) -> Result<()> { Ok(()) } } impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut **self) } #[inline] fn end(self) -> Result<()> { Ok(()) } } impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut **self) } #[inline] fn end(self) -> Result<()> { Ok(()) } } #[doc(hidden)] pub struct StructSerializer<'a, W> { ser: &'a mut Serializer, idx: u32, } impl<'a, W> StructSerializer<'a, W> where W: Write, { #[inline] fn serialize_field_inner(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { if self.ser.packed { self.idx.serialize(&mut *self.ser)?; } else { key.serialize(&mut *self.ser)?; } value.serialize(&mut *self.ser)?; self.idx += 1; Ok(()) } #[inline] fn skip_field_inner(&mut self, _: &'static str) -> Result<()> { self.idx += 1; Ok(()) } #[inline] fn end_inner(self) -> Result<()> { Ok(()) } } impl<'a, W> ser::SerializeStruct for StructSerializer<'a, W> where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.serialize_field_inner(key, value) } #[inline] fn skip_field(&mut self, key: &'static str) -> Result<()> { self.skip_field_inner(key) } #[inline] fn end(self) -> Result<()> { self.end_inner() } } impl<'a, W> ser::SerializeStructVariant for StructSerializer<'a, W> where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.serialize_field_inner(key, value) } #[inline] fn skip_field(&mut self, key: &'static str) -> Result<()> { self.skip_field_inner(key) } #[inline] fn end(self) -> Result<()> { self.end_inner() } } #[doc(hidden)] pub struct CollectionSerializer<'a, W> { ser: &'a mut Serializer, needs_eof: bool, } impl<'a, W> CollectionSerializer<'a, W> where W: Write, { #[inline] fn end_inner(self) -> Result<()> { if self.needs_eof { self.ser.writer.write_all(&[0xff]).map_err(|e| e.into()) } else { Ok(()) } } } impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W> where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut *self.ser) } #[inline] fn end(self) -> Result<()> { self.end_inner() } } impl<'a, W> ser::SerializeMap for CollectionSerializer<'a, W> where W: Write, { type Ok = (); type Error = Error; #[inline] fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { key.serialize(&mut *self.ser) } #[inline] fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut *self.ser) } #[inline] fn end(self) -> Result<()> { self.end_inner() } } serde_cbor-0.11.2/src/tags.rs000064400000000000000000000146560000000000000141000ustar 00000000000000//! Support for cbor tags use core::fmt; use core::marker::PhantomData; use serde::de::{ Deserialize, Deserializer, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, Visitor, }; use serde::forward_to_deserialize_any; use serde::ser::{Serialize, Serializer}; /// signals that a newtype is from a CBOR tag pub(crate) const CBOR_NEWTYPE_NAME: &str = "\0cbor_tag"; /// A value that is optionally tagged with a cbor tag /// /// this only serves as an intermediate helper for tag serialization or deserialization pub struct Tagged { /// cbor tag pub tag: Option, /// value pub value: T, } impl Tagged { /// Create a new tagged value pub fn new(tag: Option, value: T) -> Self { Self { tag, value } } } impl Serialize for Tagged { fn serialize(&self, s: S) -> Result { set_tag(self.tag); let r = s.serialize_newtype_struct(CBOR_NEWTYPE_NAME, &self.value); set_tag(None); r } } fn untagged(value: T) -> Tagged { Tagged::new(None, value) } macro_rules! delegate { ($name: ident, $type: ty) => { fn $name(self, v: $type) -> Result { T::deserialize(v.into_deserializer()).map(untagged) } }; } struct EnumDeserializer(A); impl<'de, A> Deserializer<'de> for EnumDeserializer where A: EnumAccess<'de>, { type Error = A::Error; fn deserialize_any>(self, visitor: V) -> Result { visitor.visit_enum(self.0) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } struct NoneDeserializer(PhantomData); impl<'de, E> Deserializer<'de> for NoneDeserializer where E: serde::de::Error, { type Error = E; fn deserialize_any>(self, visitor: V) -> Result { visitor.visit_none() } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } struct BytesDeserializer<'a, E>(&'a [u8], PhantomData); impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> where E: serde::de::Error, { type Error = E; fn deserialize_any>(self, visitor: V) -> Result { visitor.visit_bytes(self.0) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } /// A visitor that intercepts *just* visit_newtype_struct and passes through everything else. struct MaybeTaggedVisitor(PhantomData); impl<'de, T: Deserialize<'de>> Visitor<'de> for MaybeTaggedVisitor { type Value = Tagged; fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str("a cbor tag newtype") } delegate!(visit_bool, bool); delegate!(visit_i8, i8); delegate!(visit_i16, i16); delegate!(visit_i32, i32); delegate!(visit_i64, i64); delegate!(visit_u8, u8); delegate!(visit_u16, u16); delegate!(visit_u32, u32); delegate!(visit_u64, u64); delegate!(visit_f32, f32); delegate!(visit_f64, f64); delegate!(visit_char, char); delegate!(visit_str, &str); delegate!(visit_borrowed_str, &'de str); #[cfg(feature = "std")] delegate!(visit_byte_buf, Vec); #[cfg(feature = "std")] delegate!(visit_string, String); fn visit_bytes(self, value: &[u8]) -> Result { T::deserialize(BytesDeserializer(value, PhantomData)).map(untagged) } fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result { T::deserialize(serde::de::value::BorrowedBytesDeserializer::new(value)).map(untagged) } fn visit_unit(self) -> Result { T::deserialize(().into_deserializer()).map(untagged) } fn visit_none(self) -> Result { T::deserialize(NoneDeserializer(PhantomData)).map(untagged) } fn visit_some>(self, deserializer: D) -> Result { T::deserialize(deserializer).map(untagged) } fn visit_seq>(self, seq: A) -> Result { T::deserialize(serde::de::value::SeqAccessDeserializer::new(seq)).map(untagged) } fn visit_map>(self, map: V) -> Result { T::deserialize(serde::de::value::MapAccessDeserializer::new(map)).map(untagged) } fn visit_enum>(self, data: A) -> Result { T::deserialize(EnumDeserializer(data)).map(untagged) } fn visit_newtype_struct>( self, deserializer: D, ) -> Result { let t = get_tag(); T::deserialize(deserializer).map(|v| Tagged::new(t, v)) } } impl<'de, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for Tagged { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_any(MaybeTaggedVisitor::(PhantomData)) } } /// function to get the current cbor tag /// /// The only place where it makes sense to call this function is within visit_newtype_struct of a serde visitor. /// This is a low level API. In most cases it is preferable to use Tagged pub fn current_cbor_tag() -> Option { get_tag() } #[cfg(feature = "tags")] pub(crate) fn set_tag(value: Option) { CBOR_TAG.with(|f| *f.borrow_mut() = value); } #[cfg(feature = "tags")] pub(crate) fn get_tag() -> Option { CBOR_TAG.with(|f| *f.borrow()) } #[cfg(not(feature = "tags"))] pub(crate) fn set_tag(_value: Option) {} #[cfg(not(feature = "tags"))] pub(crate) fn get_tag() -> Option { None } #[cfg(feature = "tags")] use std::cell::RefCell; #[cfg(feature = "tags")] thread_local!(static CBOR_TAG: RefCell> = RefCell::new(None)); serde_cbor-0.11.2/src/value/de.rs000064400000000000000000000110150000000000000146300ustar 00000000000000use std::collections::BTreeMap; use std::fmt; use crate::value::Value; use serde::de; impl<'de> de::Deserialize<'de> for Value { #[inline] fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { struct ValueVisitor; impl<'de> de::Visitor<'de> for ValueVisitor { type Value = Value; fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str("any valid CBOR value") } #[inline] fn visit_str(self, value: &str) -> Result where E: de::Error, { self.visit_string(String::from(value)) } #[inline] fn visit_string(self, value: String) -> Result where E: de::Error, { Ok(Value::Text(value)) } #[inline] fn visit_bytes(self, v: &[u8]) -> Result where E: de::Error, { self.visit_byte_buf(v.to_owned()) } #[inline] fn visit_byte_buf(self, v: Vec) -> Result where E: de::Error, { Ok(Value::Bytes(v)) } #[inline] fn visit_u64(self, v: u64) -> Result where E: de::Error, { Ok(Value::Integer(v.into())) } #[inline] fn visit_i64(self, v: i64) -> Result where E: de::Error, { Ok(Value::Integer(v.into())) } #[inline] fn visit_i128(self, v: i128) -> Result where E: de::Error, { Ok(Value::Integer(v)) } #[inline] fn visit_bool(self, v: bool) -> Result where E: de::Error, { Ok(Value::Bool(v)) } #[inline] fn visit_none(self) -> Result where E: de::Error, { self.visit_unit() } #[inline] fn visit_unit(self) -> Result where E: de::Error, { Ok(Value::Null) } #[inline] fn visit_seq(self, mut visitor: V) -> Result where V: de::SeqAccess<'de>, { let mut vec = Vec::new(); while let Some(elem) = visitor.next_element()? { vec.push(elem); } Ok(Value::Array(vec)) } #[inline] fn visit_map(self, mut visitor: V) -> Result where V: de::MapAccess<'de>, { let mut values = BTreeMap::new(); while let Some((key, value)) = visitor.next_entry()? { values.insert(key, value); } Ok(Value::Map(values)) } #[inline] fn visit_f64(self, v: f64) -> Result where E: de::Error, { Ok(Value::Float(v)) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { let tag = crate::tags::get_tag(); let inner = deserializer.deserialize_any(self); match tag { Some(tag) => inner.map(|v| Value::Tag(tag, Box::new(v))), None => inner, } } } deserializer.deserialize_any(ValueVisitor) } } /// Convert a `serde_cbor::Value` into a type `T` #[allow(clippy::needless_pass_by_value)] pub fn from_value(value: Value) -> Result where T: de::DeserializeOwned, { // TODO implement in a way that doesn't require // roundtrip through buffer (i.e. by implementing // `serde::de::Deserializer` for `Value` and then doing // `T::deserialize(value)`). let buf = crate::to_vec(&value)?; crate::from_slice(buf.as_slice()) } serde_cbor-0.11.2/src/value/mod.rs000064400000000000000000000116200000000000000150210ustar 00000000000000//! CBOR values, keys and serialization routines. mod de; mod ser; use std::cmp::{Ord, Ordering, PartialOrd}; use std::collections::BTreeMap; #[doc(inline)] pub use self::de::from_value; #[doc(inline)] pub use self::ser::to_value; /// The `Value` enum, a loosely typed way of representing any valid CBOR value. /// /// Maps are sorted according to the canonical ordering /// described in [RFC 7049 bis]. /// Therefore values are unambiguously serialized /// to a canonical form of CBOR from the same RFC. /// /// [RFC 7049 bis]: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-2 #[derive(Clone, Debug)] pub enum Value { /// Represents the absence of a value or the value undefined. Null, /// Represents a boolean value. Bool(bool), /// Integer CBOR numbers. /// /// The biggest value that can be represented is 2^64 - 1. /// While the smallest value is -2^64. /// Values outside this range can't be serialized /// and will cause an error. Integer(i128), /// Represents a floating point value. Float(f64), /// Represents a byte string. Bytes(Vec), /// Represents an UTF-8 encoded string. Text(String), /// Represents an array of values. Array(Vec), /// Represents a map. /// /// Maps are also called tables, dictionaries, hashes, or objects (in JSON). /// While any value can be used as a CBOR key /// it is better to use only one type of key in a map /// to avoid ambiguity. /// If floating point values are used as keys they are compared bit-by-bit for equality. /// If arrays or maps are used as keys the comparisons /// to establish canonical order may be slow and therefore insertion /// and retrieval of values will be slow too. Map(BTreeMap), /// Represents a tagged value Tag(u64, Box), // The hidden variant allows the enum to be extended // with variants for tags and simple values. #[doc(hidden)] __Hidden, } impl PartialEq for Value { fn eq(&self, other: &Value) -> bool { self.cmp(other) == Ordering::Equal } } impl Eq for Value {} impl PartialOrd for Value { fn partial_cmp(&self, other: &Value) -> Option { Some(self.cmp(other)) } } impl Ord for Value { fn cmp(&self, other: &Value) -> Ordering { // Determine the canonical order of two values: // 1. Smaller major type sorts first. // 2. Shorter sequence sorts first. // 3. Compare integers by magnitude. // 4. Compare byte and text sequences lexically. // 5. Compare the serializations of both types. (expensive) use self::Value::*; if self.major_type() != other.major_type() { return self.major_type().cmp(&other.major_type()); } match (self, other) { (Integer(a), Integer(b)) => a.abs().cmp(&b.abs()), (Bytes(a), Bytes(b)) if a.len() != b.len() => a.len().cmp(&b.len()), (Text(a), Text(b)) if a.len() != b.len() => a.len().cmp(&b.len()), (Array(a), Array(b)) if a.len() != b.len() => a.len().cmp(&b.len()), (Map(a), Map(b)) if a.len() != b.len() => a.len().cmp(&b.len()), (Bytes(a), Bytes(b)) => a.cmp(b), (Text(a), Text(b)) => a.cmp(b), (a, b) => { let a = crate::to_vec(a).expect("self is serializable"); let b = crate::to_vec(b).expect("other is serializable"); a.cmp(&b) } } } } macro_rules! impl_from { ($variant:path, $for_type:ty) => { impl From<$for_type> for Value { fn from(v: $for_type) -> Value { $variant(v.into()) } } }; } impl_from!(Value::Bool, bool); impl_from!(Value::Integer, i8); impl_from!(Value::Integer, i16); impl_from!(Value::Integer, i32); impl_from!(Value::Integer, i64); // i128 omitted because not all numbers fit in CBOR serialization impl_from!(Value::Integer, u8); impl_from!(Value::Integer, u16); impl_from!(Value::Integer, u32); impl_from!(Value::Integer, u64); // u128 omitted because not all numbers fit in CBOR serialization impl_from!(Value::Float, f32); impl_from!(Value::Float, f64); impl_from!(Value::Bytes, Vec); impl_from!(Value::Text, String); // TODO: figure out if these impls should be more generic or removed. impl_from!(Value::Array, Vec); impl_from!(Value::Map, BTreeMap); impl Value { fn major_type(&self) -> u8 { use self::Value::*; match self { Null => 7, Bool(_) => 7, Integer(v) => { if *v >= 0 { 0 } else { 1 } } Tag(_, _) => 6, Float(_) => 7, Bytes(_) => 2, Text(_) => 3, Array(_) => 4, Map(_) => 5, __Hidden => unreachable!(), } } } serde_cbor-0.11.2/src/value/ser.rs000064400000000000000000000256670000000000000150530ustar 00000000000000// Copyright 2017 Serde Developers // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::collections::BTreeMap; use crate::error::Error; use serde::{self, Serialize}; use crate::tags::Tagged; use crate::value::Value; impl serde::Serialize for Value { #[inline] fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { match *self { Value::Integer(v) => serializer.serialize_i128(v), Value::Bytes(ref v) => serializer.serialize_bytes(&v), Value::Text(ref v) => serializer.serialize_str(&v), Value::Array(ref v) => v.serialize(serializer), Value::Map(ref v) => v.serialize(serializer), Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer), Value::Float(v) => serializer.serialize_f64(v), Value::Bool(v) => serializer.serialize_bool(v), Value::Null => serializer.serialize_unit(), Value::__Hidden => unreachable!(), } } } struct Serializer; impl serde::Serializer for Serializer { type Ok = Value; type Error = Error; type SerializeSeq = SerializeVec; type SerializeTuple = SerializeVec; type SerializeTupleStruct = SerializeVec; type SerializeTupleVariant = SerializeTupleVariant; type SerializeMap = SerializeMap; type SerializeStruct = SerializeMap; type SerializeStructVariant = SerializeStructVariant; #[inline] fn serialize_bool(self, value: bool) -> Result { Ok(Value::Bool(value)) } #[inline] fn serialize_i8(self, value: i8) -> Result { self.serialize_i64(i64::from(value)) } #[inline] fn serialize_i16(self, value: i16) -> Result { self.serialize_i64(i64::from(value)) } #[inline] fn serialize_i32(self, value: i32) -> Result { self.serialize_i64(i64::from(value)) } #[inline] fn serialize_i64(self, value: i64) -> Result { self.serialize_i128(i128::from(value)) } fn serialize_i128(self, value: i128) -> Result { Ok(Value::Integer(value)) } #[inline] fn serialize_u8(self, value: u8) -> Result { self.serialize_u64(u64::from(value)) } #[inline] fn serialize_u16(self, value: u16) -> Result { self.serialize_u64(u64::from(value)) } #[inline] fn serialize_u32(self, value: u32) -> Result { self.serialize_u64(u64::from(value)) } #[inline] fn serialize_u64(self, value: u64) -> Result { Ok(Value::Integer(value.into())) } #[inline] fn serialize_f32(self, value: f32) -> Result { self.serialize_f64(f64::from(value)) } #[inline] fn serialize_f64(self, value: f64) -> Result { Ok(Value::Float(value)) } #[inline] fn serialize_char(self, value: char) -> Result { let mut s = String::new(); s.push(value); self.serialize_str(&s) } #[inline] fn serialize_str(self, value: &str) -> Result { Ok(Value::Text(value.to_owned())) } fn serialize_bytes(self, value: &[u8]) -> Result { Ok(Value::Bytes(value.to_vec())) } #[inline] fn serialize_unit(self) -> Result { Ok(Value::Null) } #[inline] fn serialize_unit_struct(self, _name: &'static str) -> Result { self.serialize_unit() } #[inline] fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> Result { self.serialize_str(variant) } #[inline] fn serialize_newtype_struct( self, _name: &'static str, value: &T, ) -> Result where T: Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: Serialize, { let mut values = BTreeMap::new(); values.insert(Value::from(variant.to_owned()), to_value(&value)?); Ok(Value::Map(values)) } #[inline] fn serialize_none(self) -> Result { self.serialize_unit() } #[inline] fn serialize_some(self, value: &T) -> Result where T: Serialize, { value.serialize(self) } fn serialize_seq(self, len: Option) -> Result { Ok(SerializeVec { vec: Vec::with_capacity(len.unwrap_or(0)), }) } fn serialize_tuple(self, len: usize) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_struct( self, _name: &'static str, len: usize, ) -> Result { self.serialize_tuple(len) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(SerializeTupleVariant { name: String::from(variant), vec: Vec::with_capacity(len), }) } fn serialize_map(self, _len: Option) -> Result { Ok(SerializeMap { map: BTreeMap::new(), next_key: None, }) } fn serialize_struct( self, _name: &'static str, len: usize, ) -> Result { self.serialize_map(Some(len)) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, _len: usize, ) -> Result { Ok(SerializeStructVariant { name: String::from(variant), map: BTreeMap::new(), }) } #[inline] fn is_human_readable(&self) -> bool { false } } pub struct SerializeVec { vec: Vec, } pub struct SerializeTupleVariant { name: String, vec: Vec, } pub struct SerializeMap { map: BTreeMap, next_key: Option, } pub struct SerializeStructVariant { name: String, map: BTreeMap, } impl serde::ser::SerializeSeq for SerializeVec { type Ok = Value; type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> where T: Serialize, { self.vec.push(to_value(&value)?); Ok(()) } fn end(self) -> Result { Ok(Value::Array(self.vec)) } } impl serde::ser::SerializeTuple for SerializeVec { type Ok = Value; type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> where T: Serialize, { serde::ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { serde::ser::SerializeSeq::end(self) } } impl serde::ser::SerializeTupleStruct for SerializeVec { type Ok = Value; type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> where T: Serialize, { serde::ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { serde::ser::SerializeSeq::end(self) } } impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { type Ok = Value; type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> where T: Serialize, { self.vec.push(to_value(&value)?); Ok(()) } fn end(self) -> Result { let mut object = BTreeMap::new(); object.insert(Value::from(self.name), Value::Array(self.vec)); Ok(Value::Map(object)) } } impl serde::ser::SerializeMap for SerializeMap { type Ok = Value; type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<(), Error> where T: Serialize, { self.next_key = Some(to_value(&key)?); Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<(), Error> where T: Serialize, { let key = self.next_key.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let key = key.expect("serialize_value called before serialize_key"); self.map.insert(key, to_value(&value)?); Ok(()) } fn end(self) -> Result { Ok(Value::Map(self.map)) } } impl serde::ser::SerializeStruct for SerializeMap { type Ok = Value; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where T: Serialize, { serde::ser::SerializeMap::serialize_key(self, key)?; serde::ser::SerializeMap::serialize_value(self, value) } fn end(self) -> Result { serde::ser::SerializeMap::end(self) } } impl serde::ser::SerializeStructVariant for SerializeStructVariant { type Ok = Value; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where T: Serialize, { self.map .insert(Value::from(String::from(key)), to_value(&value)?); Ok(()) } fn end(self) -> Result { let mut object = BTreeMap::new(); object.insert(Value::from(self.name), Value::Map(self.map)); Ok(Value::Map(object)) } } /// Convert a `T` into `serde_cbor::Value` which is an enum that can represent /// any valid CBOR data. /// /// ```rust /// extern crate serde; /// /// #[macro_use] /// extern crate serde_derive; /// extern crate serde_cbor; /// /// use std::error::Error; /// /// #[derive(Serialize)] /// struct User { /// fingerprint: String, /// location: String, /// } /// /// fn main() { /// let u = User { /// fingerprint: "0xF9BA143B95FF6D82".to_owned(), /// location: "Menlo Park, CA".to_owned(), /// }; /// /// let v = serde_cbor::value::to_value(u).unwrap(); /// } /// ``` #[allow(clippy::needless_pass_by_value)] // Taking by value is more friendly to iterator adapters, option and result pub fn to_value(value: T) -> Result where T: Serialize, { value.serialize(Serializer) } serde_cbor-0.11.2/src/write.rs000064400000000000000000000117510000000000000142650ustar 00000000000000#[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(not(feature = "std"))] use core::fmt; #[cfg(feature = "std")] use std::io; use crate::error; #[cfg(not(feature = "unsealed_read_write"))] /// A sink for serialized CBOR. /// /// This trait is similar to the [`Write`]() trait in the standard library, /// but has a smaller and more general API. /// /// Any object implementing `std::io::Write` /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements /// this trait for the underlying object. pub trait Write: private::Sealed { /// The type of error returned when a write operation fails. #[doc(hidden)] type Error: Into; /// Attempts to write an entire buffer into this write. #[doc(hidden)] fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; } #[cfg(feature = "unsealed_read_write")] /// A sink for serialized CBOR. /// /// This trait is similar to the [`Write`]() trait in the standard library, /// but has a smaller and more general API. /// /// Any object implementing `std::io::Write` /// can be wrapped in an [`IoWrite`](../write/struct.IoWrite.html) that implements /// this trait for the underlying object. /// /// This trait is sealed by default, enabling the `unsealed_read_write` feature removes this bound /// to allow objects outside of this crate to implement this trait. pub trait Write { /// The type of error returned when a write operation fails. type Error: Into; /// Attempts to write an entire buffer into this write. fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>; } #[cfg(not(feature = "unsealed_read_write"))] mod private { pub trait Sealed {} } impl Write for &mut W where W: Write, { type Error = W::Error; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { (*self).write_all(buf) } } #[cfg(not(feature = "unsealed_read_write"))] impl private::Sealed for &mut W where W: Write {} #[cfg(feature = "std")] /// A wrapper for types that implement /// [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html) to implement the local /// [`Write`](trait.Write.html) trait. #[derive(Debug)] pub struct IoWrite(W); #[cfg(feature = "std")] impl IoWrite { /// Wraps an `io::Write` writer to make it compatible with [`Write`](trait.Write.html) pub fn new(w: W) -> IoWrite { IoWrite(w) } } #[cfg(feature = "std")] impl Write for IoWrite { type Error = io::Error; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { self.0.write_all(buf) } } #[cfg(all(feature = "std", not(feature = "unsealed_read_write")))] impl private::Sealed for IoWrite where W: io::Write {} #[cfg(any(feature = "std", feature = "alloc"))] impl Write for Vec { type Error = error::Error; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { self.extend_from_slice(buf); Ok(()) } } #[cfg(all( any(feature = "std", feature = "alloc"), not(feature = "unsealed_read_write") ))] impl private::Sealed for Vec {} #[cfg(not(feature = "std"))] #[derive(Debug)] pub struct FmtWrite<'a, W: Write>(&'a mut W); #[cfg(not(feature = "std"))] impl<'a, W: Write> FmtWrite<'a, W> { /// Wraps an `fmt::Write` writer to make it compatible with [`Write`](trait.Write.html) pub fn new(w: &'a mut W) -> FmtWrite<'a, W> { FmtWrite(w) } } #[cfg(not(feature = "std"))] impl<'a, W: Write> fmt::Write for FmtWrite<'a, W> { fn write_str(&mut self, s: &str) -> fmt::Result { self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error) } } #[cfg(all(not(feature = "std"), not(feature = "unsealed_read_write")))] impl<'a, W> private::Sealed for FmtWrite<'a, W> where W: Write {} /// Implements [`Write`](trait.Write.html) for mutable byte slices (`&mut [u8]`). /// /// Returns an error if the value to serialize is too large to fit in the slice. #[derive(Debug)] pub struct SliceWrite<'a> { slice: &'a mut [u8], index: usize, } impl<'a> SliceWrite<'a> { /// Wraps a mutable slice so it can be used as a `Write`. pub fn new(slice: &'a mut [u8]) -> SliceWrite<'a> { SliceWrite { slice, index: 0 } } /// Returns the number of bytes written to the underlying slice. pub fn bytes_written(&self) -> usize { self.index } /// Returns the underlying slice. pub fn into_inner(self) -> &'a mut [u8] { self.slice } } impl<'a> Write for SliceWrite<'a> { type Error = error::Error; fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { if self.slice.len() - self.index < buf.len() { // This buffer will not fit in our slice return Err(error::Error::scratch_too_small(self.index as u64)); } let end = self.index + buf.len(); self.slice[self.index..end].copy_from_slice(buf); self.index = end; Ok(()) } } #[cfg(not(feature = "unsealed_read_write"))] impl<'a> private::Sealed for SliceWrite<'a> {} serde_cbor-0.11.2/tests/bennofs.rs000064400000000000000000000026000000000000000151310ustar 00000000000000#[macro_use] extern crate serde_derive; use serde::Serialize; use serde_cbor::ser::SliceWrite; use serde_cbor::{self, Serializer}; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Example { foo: Foo, payload: u8, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Foo { x: u8, color: Color, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Color { Red, Blue, Yellow(u8), } const EXAMPLE: Example = Example { foo: Foo { x: 0xAA, color: Color::Yellow(40), }, payload: 0xCC, }; #[cfg(feature = "std")] mod std_tests { use super::*; #[test] fn test() { let serialized = serde_cbor::ser::to_vec_packed(&EXAMPLE).expect("bennofs 1"); println!("{:?}", serialized); let deserialized: Example = serde_cbor::from_slice(&serialized).expect("bennofs 2"); assert_eq!(EXAMPLE, deserialized); } } #[test] fn test() { let mut slice = [0u8; 64]; let writer = SliceWrite::new(&mut slice); let mut serializer = Serializer::new(writer).packed_format(); EXAMPLE.serialize(&mut serializer).unwrap(); let writer = serializer.into_inner(); let end = writer.bytes_written(); let slice = writer.into_inner(); let deserialized: Example = serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap(); assert_eq!(EXAMPLE, deserialized); } serde_cbor-0.11.2/tests/canonical.rs000064400000000000000000000047170000000000000154410ustar 00000000000000#[cfg(feature = "std")] mod std_tests { use serde_cbor::value::Value; #[test] fn integer_canonical_sort_order() { let expected = [ 0, 23, 24, 255, 256, 65535, 65536, 4294967295, -1, -24, -25, -256, -257, -65536, -65537, -4294967296, ] .iter() .map(|i| Value::Integer(*i)) .collect::>(); let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } #[test] fn string_canonical_sort_order() { let expected = ["", "a", "b", "aa"] .iter() .map(|s| Value::Text(s.to_string())) .collect::>(); let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } #[test] fn bytes_canonical_sort_order() { let expected = vec![vec![], vec![0u8], vec![1u8], vec![0u8, 0u8]] .into_iter() .map(|v| Value::Bytes(v)) .collect::>(); let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } #[test] fn simple_data_canonical_sort_order() { let expected = vec![Value::Bool(false), Value::Bool(true), Value::Null]; let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } #[test] fn major_type_canonical_sort_order() { let expected = vec![ Value::Integer(0), Value::Integer(-1), Value::Bytes(vec![]), Value::Text("".to_string()), Value::Null, ]; let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } #[test] fn test_rfc_example() { // See: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-4.10 let expected = vec![ Value::Integer(10), Value::Integer(100), Value::Integer(-1), Value::Text("z".to_owned()), Value::Text("aa".to_owned()), Value::Array(vec![Value::Integer(100)]), Value::Array(vec![Value::Integer(-1)]), Value::Bool(false), ]; let mut sorted = expected.clone(); sorted.sort(); assert_eq!(expected, sorted); } } serde_cbor-0.11.2/tests/crash.cbor000064400000000000000000000002760000000000000151070ustar 00000000000000ŽSSSSSSSSSSSSSSŗbbbb{’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’9@ŚbŠ ŽL:¹¹ 9īŚZ serde_cbor-0.11.2/tests/de.rs000064400000000000000000000577100000000000000141030ustar 00000000000000#[macro_use] extern crate serde_derive; use serde_cbor; use serde_cbor::de; #[test] fn test_str() { let s: &str = de::from_slice_with_scratch(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap(); assert_eq!(s, "foobar"); } #[test] fn test_bytes() { let s: &[u8] = de::from_slice_with_scratch(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap(); assert_eq!(s, b"foobar"); } #[test] fn test_int() { let num: i64 = de::from_slice_with_scratch(&[0x39, 0x07, 0xde], &mut []).unwrap(); assert_eq!(num, -2015); } #[test] fn test_float() { let float: f64 = de::from_slice_with_scratch(b"\xfa\x47\xc3\x50\x00", &mut []).unwrap(); assert_eq!(float, 100000.0); } #[test] fn test_indefinite_object() { #[derive(Debug, Deserialize, PartialEq)] struct Foo { a: u64, b: [u64; 2], } let expected = Foo { a: 1, b: [2, 3] }; let actual: Foo = de::from_slice_with_scratch(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff", &mut []).unwrap(); assert_eq!(expected, actual); } #[cfg(feature = "std")] mod std_tests { use std::collections::BTreeMap; use serde::de as serde_de; use serde_cbor::value::Value; use serde_cbor::{de, error, to_vec, Deserializer}; #[test] fn test_string1() { let value: error::Result = de::from_slice(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); assert_eq!(value.unwrap(), Value::Text("foobar".to_owned())); } #[test] fn test_string2() { let value: error::Result = de::from_slice(&[ 0x71, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65, 0x6c, 0x6c, 0x65, 0x72, ]); assert_eq!(value.unwrap(), Value::Text("I met a traveller".to_owned())); } #[test] fn test_string3() { let slice = b"\x78\x2fI met a traveller from an antique land who said"; let value: error::Result = de::from_slice(slice); assert_eq!( value.unwrap(), Value::Text("I met a traveller from an antique land who said".to_owned()) ); } #[test] fn test_byte_string() { let value: error::Result = de::from_slice(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); assert_eq!(value.unwrap(), Value::Bytes(b"foobar".to_vec())); } #[test] fn test_numbers1() { let value: error::Result = de::from_slice(&[0x00]); assert_eq!(value.unwrap(), Value::Integer(0)); } #[test] fn test_numbers2() { let value: error::Result = de::from_slice(&[0x1a, 0x00, 0xbc, 0x61, 0x4e]); assert_eq!(value.unwrap(), Value::Integer(12345678)); } #[test] fn test_numbers3() { let value: error::Result = de::from_slice(&[0x39, 0x07, 0xde]); assert_eq!(value.unwrap(), Value::Integer(-2015)); } #[test] fn test_bool() { let value: error::Result = de::from_slice(b"\xf4"); assert_eq!(value.unwrap(), Value::Bool(false)); } #[test] fn test_trailing_bytes() { let value: error::Result = de::from_slice(b"\xf4trailing"); assert!(value.is_err()); } #[test] fn test_list1() { let value: error::Result = de::from_slice(b"\x83\x01\x02\x03"); assert_eq!( value.unwrap(), Value::Array(vec![ Value::Integer(1), Value::Integer(2), Value::Integer(3) ]) ); } #[test] fn test_list2() { let value: error::Result = de::from_slice(b"\x82\x01\x82\x02\x81\x03"); assert_eq!( value.unwrap(), Value::Array(vec![ Value::Integer(1), Value::Array(vec![ Value::Integer(2), Value::Array(vec![Value::Integer(3)]) ]) ]) ); } #[test] fn test_object() { let value: error::Result = de::from_slice(b"\xa5aaaAabaBacaCadaDaeaE"); let mut object = BTreeMap::new(); object.insert(Value::Text("a".to_owned()), Value::Text("A".to_owned())); object.insert(Value::Text("b".to_owned()), Value::Text("B".to_owned())); object.insert(Value::Text("c".to_owned()), Value::Text("C".to_owned())); object.insert(Value::Text("d".to_owned()), Value::Text("D".to_owned())); object.insert(Value::Text("e".to_owned()), Value::Text("E".to_owned())); assert_eq!(value.unwrap(), Value::Map(object)); } #[test] fn test_indefinite_object() { let value: error::Result = de::from_slice(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff"); let mut object = BTreeMap::new(); object.insert(Value::Text("a".to_owned()), Value::Integer(1)); object.insert( Value::Text("b".to_owned()), Value::Array(vec![Value::Integer(2), Value::Integer(3)]), ); assert_eq!(value.unwrap(), Value::Map(object)); } #[test] fn test_indefinite_list() { let value: error::Result = de::from_slice(b"\x9f\x01\x02\x03\xff"); assert_eq!( value.unwrap(), Value::Array(vec![ Value::Integer(1), Value::Integer(2), Value::Integer(3) ]) ); } #[test] fn test_indefinite_string() { let value: error::Result = de::from_slice(b"\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff"); assert_eq!( value.unwrap(), Value::Text("Mary Had a Little Lamb".to_owned()) ); } #[test] fn test_indefinite_byte_string() { let value: error::Result = de::from_slice(b"\x5f\x42\x01\x23\x42\x45\x67\xff"); assert_eq!(value.unwrap(), Value::Bytes(b"\x01#Eg".to_vec())); } #[test] fn test_multiple_indefinite_strings() { let input = b"\x82\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff\x5f\x42\x01\x23\x42\x45\x67\xff"; _test_multiple_indefinite_strings(de::from_slice(input)); _test_multiple_indefinite_strings(de::from_mut_slice(input.to_vec().as_mut())); let mut buf = [0u8; 64]; _test_multiple_indefinite_strings(de::from_slice_with_scratch(input, &mut buf)); } fn _test_multiple_indefinite_strings(value: error::Result) { // This assures that buffer rewinding in infinite buffers works as intended. assert_eq!( value.unwrap(), Value::Array(vec![ Value::Text("Mary Had a Little Lamb".to_owned()), Value::Bytes(b"\x01#Eg".to_vec()) ]) ); } #[test] fn test_float() { let value: error::Result = de::from_slice(b"\xfa\x47\xc3\x50\x00"); assert_eq!(value.unwrap(), Value::Float(100000.0)); } #[test] fn test_self_describing() { let value: error::Result = de::from_slice(&[0xd9, 0xd9, 0xf7, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); let expected = Value::Text("foobar".to_owned()); let strip_tags = |x: Value| { if let Value::Tag(_, inner) = x { *inner } else { x } }; assert_eq!(strip_tags(value.unwrap()), expected); } #[test] fn test_f16() { let mut x: Value = de::from_slice(&[0xf9, 0x41, 0x00]).unwrap(); assert_eq!(x, Value::Float(2.5)); x = de::from_slice(&[0xf9, 0x41, 0x90]).unwrap(); assert_eq!(x, Value::Float(2.78125)); x = de::from_slice(&[0xf9, 0x50, 0x90]).unwrap(); assert_eq!(x, Value::Float(36.5)); x = de::from_slice(&[0xf9, 0xd0, 0x90]).unwrap(); assert_eq!(x, Value::Float(-36.5)); } #[test] fn test_crazy_list() { let slice = b"\x88\x1b\x00\x00\x00\x1c\xbe\x99\x1d\xc7\x3b\x00\x7a\xcf\x51\xdc\x51\x70\xdb\x3a\x1b\x3a\x06\xdd\xf5\xf6\xf7\xfb\x41\x76\x5e\xb1\xf8\x00\x00\x00\xf9\x7c\x00"; let value: Vec = de::from_slice(slice).unwrap(); assert_eq!( value, vec![ Value::Integer(123456789959), Value::Integer(-34567897654325468), Value::Integer(-456787678), Value::Bool(true), Value::Null, Value::Null, Value::Float(23456543.5), Value::Float(::std::f64::INFINITY) ] ); } #[test] fn test_nan() { let value: f64 = de::from_slice(b"\xf9\x7e\x00").unwrap(); assert!(value.is_nan()); } #[test] fn test_32f16() { let value: f32 = de::from_slice(b"\xf9\x50\x00").unwrap(); assert_eq!(value, 32.0f32); } #[test] // The file was reported as not working by user kie0tauB // but it parses to a cbor value. fn test_kietaub_file() { let file = include_bytes!("kietaub.cbor"); let value_result: error::Result = de::from_slice(file); value_result.unwrap(); } #[test] fn test_option_roundtrip() { let obj1 = Some(10u32); let v = to_vec(&obj1).unwrap(); let obj2: Result, _> = serde_cbor::de::from_reader(&v[..]); println!("{:?}", obj2); assert_eq!(obj1, obj2.unwrap()); } #[test] fn test_option_none_roundtrip() { let obj1 = None; let v = to_vec(&obj1).unwrap(); println!("{:?}", v); let obj2: Result, _> = serde_cbor::de::from_reader(&v[..]); assert_eq!(obj1, obj2.unwrap()); } #[test] fn test_variable_length_map() { let slice = b"\xbf\x67\x6d\x65\x73\x73\x61\x67\x65\x64\x70\x6f\x6e\x67\xff"; let value: Value = de::from_slice(slice).unwrap(); let mut map = BTreeMap::new(); map.insert( Value::Text("message".to_string()), Value::Text("pong".to_string()), ); assert_eq!(value, Value::Map(map)) } #[test] fn test_object_determinism_roundtrip() { let expected = b"\xa2aa\x01ab\x82\x02\x03"; // 0.1% chance of not catching failure for _ in 0..10 { assert_eq!( &to_vec(&de::from_slice::(expected).unwrap()).unwrap(), expected ); } } #[test] fn stream_deserializer() { let slice = b"\x01\x66foobar"; let mut it = Deserializer::from_slice(slice).into_iter::(); assert_eq!(Value::Integer(1), it.next().unwrap().unwrap()); assert_eq!( Value::Text("foobar".to_string()), it.next().unwrap().unwrap() ); assert!(it.next().is_none()); } #[test] fn stream_deserializer_eof() { let slice = b"\x01\x66foob"; let mut it = Deserializer::from_slice(slice).into_iter::(); assert_eq!(Value::Integer(1), it.next().unwrap().unwrap()); assert!(it.next().unwrap().unwrap_err().is_eof()); } #[test] fn stream_deserializer_eof_in_indefinite() { let slice = b"\x7f\x65Mary \x64Had \x62a \x60\x67Little \x60\x64Lamb\xff"; let indices: &[usize] = &[ 2, // announcement but no data 10, // mid-buffer EOF 12, // neither new element nor end marker ]; for end_of_slice in indices { let mut it = Deserializer::from_slice(&slice[..*end_of_slice]).into_iter::(); assert!(it.next().unwrap().unwrap_err().is_eof()); let mut mutcopy = slice[..*end_of_slice].to_vec(); let mut it = Deserializer::from_mut_slice(mutcopy.as_mut()).into_iter::(); assert!(it.next().unwrap().unwrap_err().is_eof()); let mut buf = [0u8; 64]; let mut it = Deserializer::from_slice_with_scratch(&slice[..*end_of_slice], &mut buf) .into_iter::(); assert!(it.next().unwrap().unwrap_err().is_eof()); } } #[test] fn crash() { let file = include_bytes!("crash.cbor"); let value_result: error::Result = de::from_slice(file); assert_eq!( value_result.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); } fn from_slice_stream<'a, T>(slice: &'a [u8]) -> error::Result<(&'a [u8], T)> where T: serde_de::Deserialize<'a>, { let mut deserializer = Deserializer::from_slice(slice); let value = serde_de::Deserialize::deserialize(&mut deserializer)?; let rest = &slice[deserializer.byte_offset()..]; Ok((rest, value)) } #[test] fn test_slice_offset() { let v: Vec = vec![ 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, ]; let (rest, value): (&[u8], String) = from_slice_stream(&v[..]).unwrap(); assert_eq!(value, "foobar"); assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap(); assert_eq!(value, "foobar"); assert_eq!(rest, &[]); } #[derive(Debug, Copy, Clone)] struct Options { standard: bool, legacy: bool, packed: bool, named: bool, } impl Default for Options { fn default() -> Self { Options { standard: true, legacy: true, packed: true, named: true, } } } impl Options { fn no_standard(self) -> Self { Options { standard: false, ..self } } fn no_legacy(self) -> Self { Options { legacy: false, ..self } } fn no_packed(self) -> Self { Options { packed: false, ..self } } fn no_named(self) -> Self { Options { named: false, ..self } } } fn from_slice_stream_options<'a, T>( slice: &'a [u8], options: Options, ) -> error::Result<(&'a [u8], T)> where T: serde_de::Deserialize<'a>, { let deserializer = Deserializer::from_slice(slice); let deserializer = if !options.packed { deserializer.disable_packed_format() } else { deserializer }; let deserializer = if !options.named { deserializer.disable_named_format() } else { deserializer }; let deserializer = if !options.standard { deserializer.disable_standard_enums() } else { deserializer }; let mut deserializer = if !options.legacy { deserializer.disable_legacy_enums() } else { deserializer }; let value = serde_de::Deserialize::deserialize(&mut deserializer)?; let rest = &slice[deserializer.byte_offset()..]; Ok((rest, value)) } #[test] fn test_deserializer_enums() { #[derive(Debug, PartialEq, Deserialize)] enum Enum { Unit, NewType(i32), Tuple(String, bool), Struct { x: i32, y: i32 }, } // This is the format used in serde >= 0.10 // // Serialization of Enum::NewType(10) let v: Vec = vec![ 0xa1, // map 1pair 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType 0x1a, // u32 0x00, 0x00, 0x00, 0x0a, // 10 (dec) ]; let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); assert_eq!(value, Enum::NewType(10)); let (_rest, value): (&[u8], Enum) = from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap(); assert_eq!(value, Enum::NewType(10)); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_standard()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); // Serialization of Enum::Unit let v: Vec = vec![ 0x64, 0x55, 0x6e, 0x69, 0x74, // utf8 string: Unit ]; let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); assert_eq!(value, Enum::Unit); let (_rest, value): (&[u8], Enum) = from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap(); assert_eq!(value, Enum::Unit); let (_rest, value): (&[u8], Enum) = from_slice_stream_options(&v[..], Options::default().no_standard()).unwrap(); assert_eq!(value, Enum::Unit); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_legacy().no_standard()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); // This is the format used in serde <= 0.9 let v: Vec = vec![ 0x82, // array 2 items 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType 0x1a, // u32 0x00, 0x00, 0x00, 0x0a, // 10 (dec) ]; let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); assert_eq!(value, Enum::NewType(10)); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_legacy()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_standard()); assert_eq!(value.unwrap().1, Enum::NewType(10)); let value: error::Result<(&[u8], Enum)> = from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); } #[test] fn test_packed_deserialization() { #[derive(Debug, PartialEq, Deserialize)] struct User { user_id: u32, password_hash: [u8; 4], } // unpacked let v: Vec = vec![ 0xa2, // map 2pair 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id 0x0a, // integer: 10 // utf8 string: password_hash 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] ]; let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let (_rest, value): (&[u8], User) = from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let value: error::Result<(&[u8], User)> = from_slice_stream_options(&v[..], Options::default().no_named()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); // unpacked - indefinite length let v: Vec = vec![ 0xbf, // map to be followed by a break 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id 0x0a, // integer: 10 // utf8 string: password_hash 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] 0xff, // break ]; let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let (_rest, value): (&[u8], User) = from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let value: error::Result<(&[u8], User)> = from_slice_stream_options(&v[..], Options::default().no_named()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); // packed let v: Vec = vec![ 0xa2, // map 2pair 0x00, // index 0 0x0a, // integer: 10 0x01, // index 1 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] ]; let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let (_rest, value): (&[u8], User) = from_slice_stream_options(&v[..], Options::default().no_named()).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let value: error::Result<(&[u8], User)> = from_slice_stream_options(&v[..], Options::default().no_packed()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); // packed - indefinite length let v: Vec = vec![ 0xbf, // map, to be followed by a break 0x00, // index 0 0x0a, // integer: 10 0x01, // index 1 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] 0xff, // break ]; let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let (_rest, value): (&[u8], User) = from_slice_stream_options(&v[..], Options::default().no_named()).unwrap(); assert_eq!( value, User { user_id: 10, password_hash: [1, 2, 3, 4], } ); let value: error::Result<(&[u8], User)> = from_slice_stream_options(&v[..], Options::default().no_packed()); assert_eq!( value.unwrap_err().classify(), serde_cbor::error::Category::Syntax ); } use serde_cbor::{de::from_slice, ser::to_vec_packed}; use std::net::{IpAddr, Ipv4Addr}; #[test] fn test_ipaddr_deserialization() { let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let buf = to_vec_packed(&ip).unwrap(); let deserialized_ip = from_slice::(&buf).unwrap(); assert_eq!(ip, deserialized_ip); let buf = to_vec(&ip).unwrap(); let deserialized_ip = from_slice::(&buf).unwrap(); assert_eq!(ip, deserialized_ip); } #[test] fn attempt_stack_overflow() { // Create a tag 17, followed by 999 more tag 17: // 17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(... // This causes deep recursion in the decoder and may // exhaust the stack and therfore result in a stack overflow. let input = vec![0xd1; 1000]; let err = serde_cbor::from_slice::(&input).expect_err("recursion limit"); assert!(err.is_syntax()); } } serde_cbor-0.11.2/tests/enum.rs000064400000000000000000000174630000000000000144600ustar 00000000000000use serde::Serialize; use serde_cbor; use serde_cbor::ser::{Serializer, SliceWrite}; #[macro_use] extern crate serde_derive; #[test] fn test_simple_data_enum_roundtrip() { #[derive(Debug, Serialize, Deserialize, PartialEq)] enum DataEnum { A(u32), B(f32), } let a = DataEnum::A(42); let mut slice = [0u8; 64]; let writer = SliceWrite::new(&mut slice); let mut serializer = Serializer::new(writer); a.serialize(&mut serializer).unwrap(); let writer = serializer.into_inner(); let end = writer.bytes_written(); let slice = writer.into_inner(); let deserialized: DataEnum = serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap(); assert_eq!(a, deserialized); } #[cfg(feature = "std")] mod std_tests { use std::collections::BTreeMap; use serde_cbor::ser::{IoWrite, Serializer}; use serde_cbor::value::Value; use serde_cbor::{from_slice, to_vec}; pub fn to_vec_legacy(value: &T) -> serde_cbor::Result> where T: serde::ser::Serialize, { let mut vec = Vec::new(); value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).legacy_enums())?; Ok(vec) } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] enum Enum { A, B, } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] struct EnumStruct { e: Enum, } #[test] fn test_enum() { let enum_struct = EnumStruct { e: Enum::B }; let raw = &to_vec(&enum_struct).unwrap(); println!("raw enum {:?}", raw); let re: EnumStruct = from_slice(raw).unwrap(); assert_eq!(enum_struct, re); } #[repr(u16)] #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] enum ReprEnum { A, B, } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] struct ReprEnumStruct { e: ReprEnum, } #[test] fn test_repr_enum() { let repr_enum_struct = ReprEnumStruct { e: ReprEnum::B }; let re: ReprEnumStruct = from_slice(&to_vec(&repr_enum_struct).unwrap()).unwrap(); assert_eq!(repr_enum_struct, re); } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] enum DataEnum { A(u32), B(bool, u8), C { x: u8, y: String }, } #[test] fn test_data_enum() { let data_enum_a = DataEnum::A(4); let re_a: DataEnum = from_slice(&to_vec(&data_enum_a).unwrap()).unwrap(); assert_eq!(data_enum_a, re_a); let data_enum_b = DataEnum::B(true, 42); let re_b: DataEnum = from_slice(&to_vec(&data_enum_b).unwrap()).unwrap(); assert_eq!(data_enum_b, re_b); let data_enum_c = DataEnum::C { x: 3, y: "foo".to_owned(), }; println!("{:?}", &to_vec(&data_enum_c).unwrap()); let re_c: DataEnum = from_slice(&to_vec(&data_enum_c).unwrap()).unwrap(); assert_eq!(data_enum_c, re_c); } #[test] fn test_serialize() { assert_eq!(to_vec_legacy(&Enum::A).unwrap(), &[97, 65]); assert_eq!(to_vec_legacy(&Enum::B).unwrap(), &[97, 66]); assert_eq!( to_vec_legacy(&DataEnum::A(42)).unwrap(), &[130, 97, 65, 24, 42] ); assert_eq!( to_vec_legacy(&DataEnum::B(true, 9)).unwrap(), &[131, 97, 66, 245, 9] ); } #[test] fn test_newtype_struct() { #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct Newtype(u8); assert_eq!(to_vec(&142u8).unwrap(), to_vec(&Newtype(142u8)).unwrap()); assert_eq!(from_slice::(&[24, 142]).unwrap(), Newtype(142)); } #[derive(Deserialize, PartialEq, Debug)] enum Foo { #[serde(rename = "require")] Require, } #[test] fn test_variable_length_array() { let slice = b"\x9F\x67\x72\x65\x71\x75\x69\x72\x65\xFF"; let value: Vec = from_slice(slice).unwrap(); assert_eq!(value, [Foo::Require]); } #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Bar { Empty, Number(i32), Flag(String, bool), Point { x: i32, y: i32 }, } #[test] fn test_enum_as_map() { // unit variants serialize like bare strings let empty_s = to_vec_legacy(&Bar::Empty).unwrap(); let empty_str_s = to_vec_legacy(&"Empty").unwrap(); assert_eq!(empty_s, empty_str_s); // tuple-variants serialize like ["", values..] let number_s = to_vec_legacy(&Bar::Number(42)).unwrap(); let number_vec = vec![Value::Text("Number".to_string()), Value::Integer(42)]; let number_vec_s = to_vec_legacy(&number_vec).unwrap(); assert_eq!(number_s, number_vec_s); let flag_s = to_vec_legacy(&Bar::Flag("foo".to_string(), true)).unwrap(); let flag_vec = vec![ Value::Text("Flag".to_string()), Value::Text("foo".to_string()), Value::Bool(true), ]; let flag_vec_s = to_vec_legacy(&flag_vec).unwrap(); assert_eq!(flag_s, flag_vec_s); // struct-variants serialize like ["", {struct..}] let point_s = to_vec_legacy(&Bar::Point { x: 5, y: -5 }).unwrap(); let mut struct_map = BTreeMap::new(); struct_map.insert(Value::Text("x".to_string()), Value::Integer(5)); struct_map.insert(Value::Text("y".to_string()), Value::Integer(-5)); let point_vec = vec![ Value::Text("Point".to_string()), Value::Map(struct_map.clone()), ]; let point_vec_s = to_vec_legacy(&point_vec).unwrap(); assert_eq!(point_s, point_vec_s); // enum_as_map matches serde_json's default serialization for enums. // unit variants still serialize like bare strings let empty_s = to_vec(&Bar::Empty).unwrap(); assert_eq!(empty_s, empty_str_s); // 1-element tuple variants serialize like {"": value} let number_s = to_vec(&Bar::Number(42)).unwrap(); let mut number_map = BTreeMap::new(); number_map.insert("Number", 42); let number_map_s = to_vec(&number_map).unwrap(); assert_eq!(number_s, number_map_s); // multi-element tuple variants serialize like {"": [values..]} let flag_s = to_vec(&Bar::Flag("foo".to_string(), true)).unwrap(); let mut flag_map = BTreeMap::new(); flag_map.insert( "Flag", vec![Value::Text("foo".to_string()), Value::Bool(true)], ); let flag_map_s = to_vec(&flag_map).unwrap(); assert_eq!(flag_s, flag_map_s); // struct-variants serialize like {"", {struct..}} let point_s = to_vec(&Bar::Point { x: 5, y: -5 }).unwrap(); let mut point_map = BTreeMap::new(); point_map.insert("Point", Value::Map(struct_map)); let point_map_s = to_vec(&point_map).unwrap(); assert_eq!(point_s, point_map_s); // deserialization of all encodings should just work let empty_str_ds = from_slice(&empty_str_s).unwrap(); assert_eq!(Bar::Empty, empty_str_ds); let number_vec_ds = from_slice(&number_vec_s).unwrap(); assert_eq!(Bar::Number(42), number_vec_ds); let number_map_ds = from_slice(&number_map_s).unwrap(); assert_eq!(Bar::Number(42), number_map_ds); let flag_vec_ds = from_slice(&flag_vec_s).unwrap(); assert_eq!(Bar::Flag("foo".to_string(), true), flag_vec_ds); let flag_map_ds = from_slice(&flag_map_s).unwrap(); assert_eq!(Bar::Flag("foo".to_string(), true), flag_map_ds); let point_vec_ds = from_slice(&point_vec_s).unwrap(); assert_eq!(Bar::Point { x: 5, y: -5 }, point_vec_ds); let point_map_ds = from_slice(&point_map_s).unwrap(); assert_eq!(Bar::Point { x: 5, y: -5 }, point_map_ds); } } serde_cbor-0.11.2/tests/kietaub.cbor000064400000000000000000000003240000000000000154250ustar 00000000000000¢gchanges‚„jup_context˜ldown_context€dflaghline_numenodes‚†¤file€„jup_context„ldown_context€dflaghline_numenodes–que de moment parce  ldependencies€serde_cbor-0.11.2/tests/ser.rs000064400000000000000000000171260000000000000143010ustar 00000000000000use serde::Serialize; use serde_cbor::ser::{Serializer, SliceWrite}; #[test] fn test_str() { serialize_and_compare("foobar", b"ffoobar"); } #[test] fn test_list() { serialize_and_compare(&[1, 2, 3], b"\x83\x01\x02\x03"); } #[test] fn test_float() { serialize_and_compare(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a"); } #[test] fn test_integer() { // u8 serialize_and_compare(24, b"\x18\x18"); // i8 serialize_and_compare(-5, b"\x24"); // i16 serialize_and_compare(-300, b"\x39\x01\x2b"); // i32 serialize_and_compare(-23567997, b"\x3a\x01\x67\x9e\x7c"); // u64 serialize_and_compare(::core::u64::MAX, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); } fn serialize_and_compare(value: T, expected: &[u8]) { let mut slice = [0u8; 64]; let writer = SliceWrite::new(&mut slice); let mut serializer = Serializer::new(writer); value.serialize(&mut serializer).unwrap(); let writer = serializer.into_inner(); let end = writer.bytes_written(); let slice = writer.into_inner(); assert_eq!(&slice[..end], expected); } #[cfg(feature = "std")] mod std_tests { use serde::Serializer; use serde_cbor::ser; use serde_cbor::{from_slice, to_vec}; use std::collections::BTreeMap; #[test] fn test_string() { let value = "foobar".to_owned(); assert_eq!(&to_vec(&value).unwrap()[..], b"ffoobar"); } #[test] fn test_list() { let value = vec![1, 2, 3]; assert_eq!(&to_vec(&value).unwrap()[..], b"\x83\x01\x02\x03"); } #[test] fn test_object() { let mut object = BTreeMap::new(); object.insert("a".to_owned(), "A".to_owned()); object.insert("b".to_owned(), "B".to_owned()); object.insert("c".to_owned(), "C".to_owned()); object.insert("d".to_owned(), "D".to_owned()); object.insert("e".to_owned(), "E".to_owned()); let vec = to_vec(&object).unwrap(); let test_object = from_slice(&vec[..]).unwrap(); assert_eq!(object, test_object); } #[test] fn test_object_list_keys() { let mut object = BTreeMap::new(); object.insert(vec![0i64], ()); object.insert(vec![100i64], ()); object.insert(vec![-1i64], ()); object.insert(vec![-2i64], ()); object.insert(vec![0i64, 0i64], ()); object.insert(vec![0i64, -1i64], ()); let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap(); assert_eq!( vec![ 166, 129, 0, 246, 129, 24, 100, 246, 129, 32, 246, 129, 33, 246, 130, 0, 0, 246, 130, 0, 32, 246 ], vec ); let test_object = from_slice(&vec[..]).unwrap(); assert_eq!(object, test_object); } #[test] fn test_object_object_keys() { use std::iter::FromIterator; let mut object = BTreeMap::new(); let keys = vec![ vec!["a"], vec!["b"], vec!["c"], vec!["d"], vec!["aa"], vec!["a", "aa"], ] .into_iter() .map(|v| BTreeMap::from_iter(v.into_iter().map(|s| (s.to_owned(), ())))); for key in keys { object.insert(key, ()); } let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap(); assert_eq!( vec![ 166, 161, 97, 97, 246, 246, 161, 97, 98, 246, 246, 161, 97, 99, 246, 246, 161, 97, 100, 246, 246, 161, 98, 97, 97, 246, 246, 162, 97, 97, 246, 98, 97, 97, 246, 246 ], vec ); let test_object = from_slice(&vec[..]).unwrap(); assert_eq!(object, test_object); } #[test] fn test_float() { let vec = to_vec(&12.3f64).unwrap(); assert_eq!(vec, b"\xfb@(\x99\x99\x99\x99\x99\x9a"); } #[test] fn test_f32() { let vec = to_vec(&4000.5f32).unwrap(); assert_eq!(vec, b"\xfa\x45\x7a\x08\x00"); } #[test] fn test_infinity() { let vec = to_vec(&::std::f64::INFINITY).unwrap(); assert_eq!(vec, b"\xf9|\x00"); } #[test] fn test_neg_infinity() { let vec = to_vec(&::std::f64::NEG_INFINITY).unwrap(); assert_eq!(vec, b"\xf9\xfc\x00"); } #[test] fn test_nan() { let vec = to_vec(&::std::f32::NAN).unwrap(); assert_eq!(vec, b"\xf9\x7e\x00"); } #[test] fn test_integer() { // u8 let vec = to_vec(&24).unwrap(); assert_eq!(vec, b"\x18\x18"); // i8 let vec = to_vec(&-5).unwrap(); assert_eq!(vec, b"\x24"); // i16 let vec = to_vec(&-300).unwrap(); assert_eq!(vec, b"\x39\x01\x2b"); // i32 let vec = to_vec(&-23567997).unwrap(); assert_eq!(vec, b"\x3a\x01\x67\x9e\x7c"); // u64 let vec = to_vec(&::std::u64::MAX).unwrap(); assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); } #[test] fn test_self_describing() { let mut vec = Vec::new(); { let mut serializer = ser::Serializer::new(&mut vec); serializer.self_describe().unwrap(); serializer.serialize_u64(9).unwrap(); } assert_eq!(vec, b"\xd9\xd9\xf7\x09"); } #[test] fn test_ip_addr() { use std::net::Ipv4Addr; let addr = Ipv4Addr::new(8, 8, 8, 8); let vec = to_vec(&addr).unwrap(); println!("{:?}", vec); assert_eq!(vec.len(), 5); let test_addr: Ipv4Addr = from_slice(&vec).unwrap(); assert_eq!(addr, test_addr); } /// Test all of CBOR's fixed-length byte string types #[test] fn test_byte_string() { // Very short byte strings have 1-byte headers let short = vec![0, 1, 2, 255]; let mut short_s = Vec::new(); serde_cbor::Serializer::new(&mut short_s) .serialize_bytes(&short) .unwrap(); assert_eq!(&short_s[..], [0x44, 0, 1, 2, 255]); // byte strings > 23 bytes have 2-byte headers let medium = vec![ 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 255, ]; let mut medium_s = Vec::new(); serde_cbor::Serializer::new(&mut medium_s) .serialize_bytes(&medium) .unwrap(); assert_eq!( &medium_s[..], [ 0x58, 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 255 ] ); // byte strings > 256 bytes have 3-byte headers let long_vec = (0..256).map(|i| (i & 0xFF) as u8).collect::>(); let mut long_s = Vec::new(); serde_cbor::Serializer::new(&mut long_s) .serialize_bytes(&long_vec) .unwrap(); assert_eq!(&long_s[0..3], [0x59, 1, 0]); assert_eq!(&long_s[3..], &long_vec[..]); // byte strings > 2^16 bytes have 5-byte headers let very_long_vec = (0..65536).map(|i| (i & 0xFF) as u8).collect::>(); let mut very_long_s = Vec::new(); serde_cbor::Serializer::new(&mut very_long_s) .serialize_bytes(&very_long_vec) .unwrap(); assert_eq!(&very_long_s[0..5], [0x5a, 0, 1, 0, 0]); assert_eq!(&very_long_s[5..], &very_long_vec[..]); // byte strings > 2^32 bytes have 9-byte headers, but they take too much RAM // to test in Travis. } #[test] fn test_half() { let vec = to_vec(&42.5f32).unwrap(); assert_eq!(vec, b"\xF9\x51\x50"); assert_eq!(from_slice::(&vec[..]).unwrap(), 42.5f32); } } serde_cbor-0.11.2/tests/std_types.rs000064400000000000000000000146440000000000000155300ustar 00000000000000#[macro_use] extern crate serde_derive; #[cfg(feature = "std")] mod std_tests { use std::u8; use serde_cbor::de::from_mut_slice; use serde_cbor::ser::{to_vec, to_vec_packed}; use serde_cbor::{from_reader, from_slice}; fn to_binary(s: &'static str) -> Vec { assert!(s.len() % 2 == 0); let mut b = Vec::with_capacity(s.len() / 2); for i in 0..s.len() / 2 { b.push(u8::from_str_radix(&s[i * 2..(i + 1) * 2], 16).unwrap()); } b } macro_rules! testcase { ($name:ident, f64, $expr:expr, $s:expr) => { #[test] fn $name() { let expr: f64 = $expr; let mut serialized = to_binary($s); assert_eq!(to_vec(&expr).unwrap(), serialized); let parsed: f64 = from_slice(&serialized[..]).unwrap(); if !expr.is_nan() { assert_eq!(expr, parsed); } else { assert!(parsed.is_nan()) } let parsed: f64 = from_reader(&mut &serialized[..]).unwrap(); if !expr.is_nan() { assert_eq!(expr, parsed); } else { assert!(parsed.is_nan()) } let parsed: f64 = from_mut_slice(&mut serialized[..]).unwrap(); if !expr.is_nan() { assert_eq!(expr, parsed); } else { assert!(parsed.is_nan()) } } }; ($name:ident, $ty:ty, $expr:expr, $s:expr) => { #[test] fn $name() { let expr: $ty = $expr; let mut serialized = to_binary($s); assert_eq!( to_vec(&expr).expect("ser1 works"), serialized, "serialization differs" ); let parsed: $ty = from_slice(&serialized[..]).expect("de1 works"); assert_eq!(parsed, expr, "parsed result differs"); let packed = &to_vec_packed(&expr).expect("serializing packed")[..]; let parsed_from_packed: $ty = from_slice(packed).expect("parsing packed"); assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); let parsed: $ty = from_reader(&mut &serialized[..]).unwrap(); assert_eq!(parsed, expr, "parsed result differs"); let mut packed = to_vec_packed(&expr).expect("serializing packed"); let parsed_from_packed: $ty = from_reader(&mut &packed[..]).expect("parsing packed"); assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); let parsed: $ty = from_mut_slice(&mut serialized[..]).unwrap(); assert_eq!(parsed, expr, "parsed result differs"); let parsed_from_packed: $ty = from_mut_slice(&mut packed[..]).expect("parsing packed"); assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); } }; } testcase!(test_bool_false, bool, false, "f4"); testcase!(test_bool_true, bool, true, "f5"); testcase!(test_isize_neg_256, isize, -256, "38ff"); testcase!(test_isize_neg_257, isize, -257, "390100"); testcase!(test_isize_255, isize, 255, "18ff"); testcase!(test_i8_5, i8, 5, "05"); testcase!(test_i8_23, i8, 23, "17"); testcase!(test_i8_24, i8, 24, "1818"); testcase!(test_i8_neg_128, i8, -128, "387f"); testcase!(test_u32_98745874, u32, 98745874, "1a05e2be12"); testcase!(test_f32_1234_point_5, f32, 1234.5, "fa449a5000"); testcase!(test_f64_12345_point_6, f64, 12345.6, "fb40c81ccccccccccd"); testcase!(test_f64_nan, f64, ::std::f64::NAN, "f97e00"); testcase!(test_f64_infinity, f64, ::std::f64::INFINITY, "f97c00"); testcase!(test_f64_neg_infinity, f64, -::std::f64::INFINITY, "f9fc00"); testcase!(test_char_null, char, '\x00', "6100"); testcase!(test_char_broken_heart, char, 'šŸ’”', "64f09f9294"); testcase!( test_str_pangram_de, String, "aâø↓é".to_owned(), "6a61c3a2c3b8e28693c3a9" ); testcase!(test_unit, (), (), "f6"); #[derive(Debug, PartialEq, Deserialize, Serialize)] struct UnitStruct; testcase!(test_unit_struct, UnitStruct, UnitStruct, "f6"); #[derive(Debug, PartialEq, Deserialize, Serialize)] struct NewtypeStruct(bool); testcase!( test_newtype_struct, NewtypeStruct, NewtypeStruct(true), "f5" ); testcase!(test_option_none, Option, None, "f6"); testcase!(test_option_some, Option, Some(42), "182a"); #[derive(Debug, PartialEq, Deserialize, Serialize)] struct Person { name: String, year_of_birth: u16, profession: Option, } testcase!(test_person_struct, Person, Person { name: "Grace Hopper".to_string(), year_of_birth: 1906, profession: Some("computer scientist".to_string()), }, "a3646e616d656c477261636520486f707065726d796561725f6f665f62697274681907726a70726f66657373696f6e72636f6d707574657220736369656e74697374"); #[derive(Debug, PartialEq, Deserialize, Serialize)] struct OptionalPerson { name: String, #[serde(skip_serializing_if = "Option::is_none")] year_of_birth: Option, profession: Option, } testcase!(test_optional_person_struct, OptionalPerson, OptionalPerson { name: "Grace Hopper".to_string(), year_of_birth: None, profession: Some("computer scientist".to_string()), }, "a2646e616d656c477261636520486f707065726a70726f66657373696f6e72636f6d707574657220736369656e74697374"); #[derive(Debug, PartialEq, Deserialize, Serialize)] enum Color { Red, Blue, Yellow, Other(u64), Alpha(u64, u8), } testcase!(test_color_enum, Color, Color::Blue, "64426c7565"); testcase!( test_color_enum_transparent, Color, Color::Other(42), "a1654f74686572182a" ); testcase!( test_color_enum_with_alpha, Color, Color::Alpha(234567, 60), "a165416c706861821a00039447183c" ); testcase!(test_i128_a, i128, -1i128, "20"); testcase!( test_i128_b, i128, -18446744073709551616i128, "3BFFFFFFFFFFFFFFFF" ); testcase!(test_u128, u128, 17, "11"); } serde_cbor-0.11.2/tests/tags.rs000064400000000000000000000026750000000000000144510ustar 00000000000000#[cfg(feature = "tags")] mod tagtests { use serde_cbor::value::Value; use serde_cbor::{from_slice, to_vec}; fn decode_hex(s: &str) -> std::result::Result, std::num::ParseIntError> { (0..s.len()) .step_by(2) .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) .collect() } // get bytes from http://cbor.me/ trees fn parse_cbor_me(example: &str) -> std::result::Result, std::num::ParseIntError> { let hex = example .split("\n") .flat_map(|line| line.split("#").take(1)) .collect::>() .join("") .replace(" ", ""); decode_hex(&hex) } #[test] fn tagged_cbor_roundtrip() { let data = r#" C1 # tag(1) 82 # array(2) C2 # tag(2) 63 # text(3) 666F6F # "foo" C3 # tag(3) A1 # map(1) C4 # tag(4) 61 # text(1) 61 # "a" C5 # tag(5) 61 # text(1) 62 # "b" "#; let bytes1 = parse_cbor_me(&data).unwrap(); let value1: Value = from_slice(&bytes1).unwrap(); let bytes2 = to_vec(&value1).unwrap(); let value2: Value = from_slice(&bytes2).unwrap(); assert_eq!(bytes1, bytes2); assert_eq!(value1, value2); } } serde_cbor-0.11.2/tests/value.rs000064400000000000000000000053100000000000000146140ustar 00000000000000#[macro_use] extern crate serde_derive; #[cfg(feature = "std")] mod std_tests { use serde_cbor; use std::collections::BTreeMap; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] struct TupleStruct(String, i32, u64); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] struct UnitStruct; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] struct Struct<'a> { tuple_struct: TupleStruct, tuple: (String, f32, f64), map: BTreeMap, bytes: &'a [u8], array: Vec, unit_array: Vec, } use serde_cbor::value::Value; use std::iter::FromIterator; #[test] fn serde() { let tuple_struct = TupleStruct(format!("test"), -60, 3000); let tuple = (format!("hello"), -50.0040957, -12.094635556478); let map = BTreeMap::from_iter( [ (format!("key1"), format!("value1")), (format!("key2"), format!("value2")), (format!("key3"), format!("value3")), (format!("key4"), format!("value4")), ] .iter() .cloned(), ); let bytes = b"test byte string"; let array = vec![format!("one"), format!("two"), format!("three")]; let unit_array = vec![UnitStruct, UnitStruct, UnitStruct]; let data = Struct { tuple_struct, tuple, map, bytes, array, unit_array, }; let value = serde_cbor::value::to_value(data.clone()).unwrap(); println!("{:?}", value); let data_ser = serde_cbor::to_vec(&value).unwrap(); let data_de_value: Value = serde_cbor::from_slice(&data_ser).unwrap(); fn as_object(value: &Value) -> &BTreeMap { if let Value::Map(ref v) = value { return v; } panic!() } for ((k1, v1), (k2, v2)) in as_object(&value) .iter() .zip(as_object(&data_de_value).iter()) { assert_eq!(k1, k2); assert_eq!(v1, v2); } assert_eq!(value, data_de_value); } #[derive(Debug, Deserialize, Serialize)] struct SmallStruct { spam: u32, eggs: u32, } #[test] fn small_struct() { // Test whether the packed format works. // Field names should not be serialized, // instead field indizes are serialized. let value = SmallStruct { spam: 17, eggs: 42 }; let data = serde_cbor::ser::to_vec_packed(&value).unwrap(); let reference = b"\xa2\x00\x11\x01\x18\x2a"; assert_eq!(data, reference); } }