├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── coverage.yml │ └── ci.yml ├── .editorconfig ├── Cargo.toml ├── LICENSE-MIT ├── README.md ├── src ├── error.rs ├── encapsulation.rs ├── lib.rs ├── size.rs ├── de.rs └── ser.rs ├── benches └── bench.rs ├── LICENSE-APACHE └── tests └── test.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | ignore: 12 | - dependency-name: dtolnay/rust-toolchain 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | # double whitespace at end of line denotes a line break in Markdown 13 | trim_trailing_whitespace = false 14 | 15 | [*.{yml,yaml}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [master] 4 | pull_request: 5 | 6 | name: Code Coverage 7 | 8 | jobs: 9 | coverage: 10 | name: coverage 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: dtolnay/rust-toolchain@nightly 15 | - uses: taiki-e/install-action@cargo-llvm-cov 16 | - run: cargo llvm-cov --doctests --lcov --output-path lcov.info 17 | - uses: codecov/codecov-action@v3 18 | with: 19 | files: lcov.info 20 | fail_ci_if_error: true 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cdr" 3 | version = "0.2.4" 4 | authors = ["Katsutoshi Horie "] 5 | description = """ 6 | A serialization/deserialization implementation of Common Data Representation 7 | """ 8 | documentation = "https://docs.rs/cdr" 9 | homepage = "https://github.com/hrektts/cdr-rs" 10 | repository = "https://github.com/hrektts/cdr-rs" 11 | readme = "README.md" 12 | keywords = ["encode", "decode", "serialize", "deserialize"] 13 | categories = ["encoding", "network-programming"] 14 | license = "MIT/Apache-2.0" 15 | edition = "2021" 16 | rust-version = "1.60.0" 17 | 18 | [dependencies] 19 | byteorder = "1.4.3" 20 | serde = "1.0.164" 21 | thiserror = "1.0.40" 22 | 23 | [dev-dependencies] 24 | bincode = "1.3.3" 25 | criterion = "0.5.1" 26 | serde_derive = "1.0.164" 27 | 28 | [[bench]] 29 | name = "bench" 30 | harness = false 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | name: Test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: dtolnay/rust-toolchain@nightly 16 | - run: cargo test 17 | 18 | format: 19 | name: Format 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: dtolnay/rust-toolchain@nightly 24 | with: 25 | components: rustfmt 26 | - run: cargo fmt -- --check 27 | 28 | clippy: 29 | name: Clippy 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: dtolnay/rust-toolchain@nightly 34 | with: 35 | components: clippy 36 | - run: cargo clippy --all-targets 37 | 38 | msrv: 39 | name: MSRV 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | - uses: dtolnay/rust-toolchain@master 44 | with: 45 | toolchain: "1.60.0" 46 | - run: cargo check --lib 47 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Katsutoshi Horie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cdr-rs 2 | 3 | A serialization/deserialization implementation for Common Data Representation in Rust. 4 | 5 | [![CI](https://github.com/hrektts/cdr-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/hrektts/cdr-rs/actions/workflows/ci.yml) 6 | [![Crates.io](https://img.shields.io/crates/v/cdr.svg?maxAge=2592000)](https://crates.io/crates/cdr) 7 | [![Docs.rs](https://docs.rs/cdr/badge.svg)](https://docs.rs/cdr) 8 | 9 | ## Usage 10 | 11 | Add this to your Cargo.toml: 12 | 13 | ``` toml 14 | [dependencies] 15 | cdr = "0.2.4" 16 | ``` 17 | 18 | ## License 19 | 20 | This project is licensed under either of 21 | 22 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 23 | [http://www.apache.org/licenses/LICENSE-2.0)](http://www.apache.org/licenses/LICENSE-2.0)) 24 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or 25 | [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) 26 | 27 | at your option. 28 | 29 | ### Contribution 30 | 31 | Unless you explicitly state otherwise, any contribution intentionally submitted 32 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 33 | dual licensed as above, without any additional terms or conditions. 34 | 35 | ## References 36 | 37 | * [Common Object Request Broker Architecture (CORBA) Specification, Version 3.3](http://www.omg.org/spec/CORBA/3.3/), Part 2: CORBA Interoperability 38 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use std::{fmt, io, str::Utf8Error}; 2 | 3 | /// Convenient wrapper around `std::Result`. 4 | pub type Result = std::result::Result; 5 | 6 | /// The Error type. 7 | #[derive(Debug, thiserror::Error)] 8 | pub enum Error { 9 | #[error("{0}")] 10 | Message(String), 11 | 12 | #[error("{0}")] 13 | Io(#[from] io::Error), 14 | 15 | #[error("does not support the serde::Deserializer::deserialize_any method")] 16 | DeserializeAnyNotSupported, 17 | 18 | #[error("expected 0 or 1, found {0}")] 19 | InvalidBoolEncoding(u8), 20 | 21 | #[error("expected char of width 1, found {0}")] 22 | InvalidChar(char), 23 | 24 | #[error("char is not valid UTF-8")] 25 | InvalidCharEncoding, 26 | 27 | #[error("encapsulation is not valid")] 28 | InvalidEncapsulation, 29 | 30 | #[error("{0}")] 31 | InvalidUtf8Encoding(#[source] Utf8Error), 32 | 33 | #[error("each character must have a length of 1, given \"{0}\"")] 34 | InvalidString(String), 35 | 36 | #[error("sequence is too long")] 37 | NumberOutOfRange, 38 | 39 | #[error("sequences must have a knowable size ahead of time")] 40 | SequenceMustHaveLength, 41 | 42 | #[error("the size limit has been reached")] 43 | SizeLimit, 44 | 45 | #[error("unsupported type")] 46 | TypeNotSupported, 47 | } 48 | 49 | impl serde::de::Error for Error { 50 | fn custom(msg: T) -> Self 51 | where 52 | T: fmt::Display, 53 | { 54 | Self::Message(msg.to_string()) 55 | } 56 | } 57 | 58 | impl serde::ser::Error for Error { 59 | fn custom(msg: T) -> Self 60 | where 61 | T: fmt::Display, 62 | { 63 | Self::Message(msg.to_string()) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/encapsulation.rs: -------------------------------------------------------------------------------- 1 | use byteorder::{BigEndian, ByteOrder, LittleEndian}; 2 | 3 | pub const ENCAPSULATION_HEADER_SIZE: u64 = 4; 4 | 5 | /// Data encapsulation scheme identifiers. 6 | pub trait Encapsulation { 7 | type E: ByteOrder; 8 | const ID: [u8; 2]; 9 | const OPTION: [u8; 2] = [0; 2]; 10 | } 11 | 12 | /// OMG CDR big-endian encapsulation. 13 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 14 | pub enum CdrBe {} 15 | 16 | impl Encapsulation for CdrBe { 17 | type E = BigEndian; 18 | const ID: [u8; 2] = [0, 0]; 19 | } 20 | 21 | /// OMG CDR little-endian encapsulation. 22 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 23 | pub enum CdrLe {} 24 | 25 | impl Encapsulation for CdrLe { 26 | type E = LittleEndian; 27 | const ID: [u8; 2] = [0, 1]; 28 | } 29 | 30 | /// ParameterList encapsulated using OMG CDR big-endian encapsulation. 31 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 32 | pub enum PlCdrBe {} 33 | 34 | impl Encapsulation for PlCdrBe { 35 | type E = BigEndian; 36 | const ID: [u8; 2] = [0, 2]; 37 | } 38 | 39 | /// ParameterList encapsulated using OMG CDR little-endian encapsulation. 40 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 41 | pub enum PlCdrLe {} 42 | 43 | impl Encapsulation for PlCdrLe { 44 | type E = LittleEndian; 45 | const ID: [u8; 2] = [0, 3]; 46 | } 47 | 48 | #[cfg(test)] 49 | mod tests { 50 | use super::*; 51 | 52 | #[test] 53 | fn test_constant() { 54 | assert_eq!( 55 | ENCAPSULATION_HEADER_SIZE, 56 | (CdrBe::ID.len() + CdrBe::OPTION.len()) as u64 57 | ); 58 | assert_eq!( 59 | ENCAPSULATION_HEADER_SIZE, 60 | (CdrLe::ID.len() + CdrLe::OPTION.len()) as u64 61 | ); 62 | assert_eq!( 63 | ENCAPSULATION_HEADER_SIZE, 64 | (PlCdrBe::ID.len() + PlCdrBe::OPTION.len()) as u64 65 | ); 66 | assert_eq!( 67 | ENCAPSULATION_HEADER_SIZE, 68 | (PlCdrLe::ID.len() + PlCdrLe::OPTION.len()) as u64 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A serialization/deserialization implementation for Common Data 2 | //! Representation. 3 | //! 4 | //! # Examples 5 | //! 6 | //! ```rust 7 | //! use cdr::{CdrBe, Infinite}; 8 | //! use serde_derive::{Deserialize, Serialize}; 9 | //! 10 | //! #[derive(Deserialize, Serialize, PartialEq)] 11 | //! struct Point { 12 | //! x: f64, 13 | //! y: f64, 14 | //! } 15 | //! 16 | //! #[derive(Deserialize, Serialize, PartialEq)] 17 | //! struct Polygon(Vec); 18 | //! 19 | //! let triangle = Polygon(vec![ 20 | //! Point { x: -1.0, y: -1.0 }, 21 | //! Point { x: 1.0, y: -1.0 }, 22 | //! Point { x: 0.0, y: 0.73 }, 23 | //! ]); 24 | //! 25 | //! let encoded = cdr::serialize::<_, _, CdrBe>(&triangle, Infinite).unwrap(); 26 | //! let decoded = cdr::deserialize::(&encoded[..]).unwrap(); 27 | //! 28 | //! assert!(triangle == decoded); 29 | //! ``` 30 | 31 | #![deny(warnings, clippy::all)] 32 | 33 | pub use byteorder::{BigEndian, LittleEndian}; 34 | 35 | pub mod de; 36 | #[doc(inline)] 37 | pub use crate::de::Deserializer; 38 | 39 | mod encapsulation; 40 | pub use crate::encapsulation::{CdrBe, CdrLe, Encapsulation, PlCdrBe, PlCdrLe}; 41 | 42 | mod error; 43 | pub use crate::error::{Error, Result}; 44 | 45 | pub mod ser; 46 | #[doc(inline)] 47 | pub use crate::ser::Serializer; 48 | 49 | pub mod size; 50 | use std::io::{Read, Write}; 51 | 52 | #[doc(inline)] 53 | pub use crate::size::{Bounded, Infinite, SizeLimit}; 54 | 55 | /// Returns the size that an object would be if serialized with a encapsulation. 56 | pub fn calc_serialized_size(value: &T) -> u64 57 | where 58 | T: serde::Serialize + ?Sized, 59 | { 60 | size::calc_serialized_data_size(value) + encapsulation::ENCAPSULATION_HEADER_SIZE 61 | } 62 | 63 | /// Given a maximum size limit, check how large an object would be if it were 64 | /// to be serialized with a encapsulation. 65 | pub fn calc_serialized_size_bounded(value: &T, max: u64) -> Result 66 | where 67 | T: serde::Serialize + ?Sized, 68 | { 69 | use crate::encapsulation::ENCAPSULATION_HEADER_SIZE; 70 | 71 | if max < ENCAPSULATION_HEADER_SIZE { 72 | Err(Error::SizeLimit) 73 | } else { 74 | size::calc_serialized_data_size_bounded(value, max) 75 | .map(|size| size + ENCAPSULATION_HEADER_SIZE) 76 | } 77 | } 78 | 79 | /// Serializes a serializable object into a `Vec` of bytes with the 80 | /// encapsulation. 81 | pub fn serialize(value: &T, size_limit: S) -> Result> 82 | where 83 | T: serde::Serialize + ?Sized, 84 | S: SizeLimit, 85 | C: Encapsulation, 86 | { 87 | let mut writer = match size_limit.limit() { 88 | Some(limit) => { 89 | let actual_size = calc_serialized_size_bounded(value, limit)?; 90 | Vec::with_capacity(actual_size as usize) 91 | } 92 | None => { 93 | let size = calc_serialized_size(value) as usize; 94 | Vec::with_capacity(size) 95 | } 96 | }; 97 | 98 | serialize_into::<_, _, _, C>(&mut writer, value, Infinite)?; 99 | Ok(writer) 100 | } 101 | 102 | /// Serializes an object directly into a `Write` with the encapsulation. 103 | pub fn serialize_into(writer: W, value: &T, size_limit: S) -> Result<()> 104 | where 105 | W: Write, 106 | T: serde::ser::Serialize + ?Sized, 107 | S: SizeLimit, 108 | C: Encapsulation, 109 | { 110 | if let Some(limit) = size_limit.limit() { 111 | calc_serialized_size_bounded(value, limit)?; 112 | } 113 | 114 | let mut serializer = Serializer::<_, C::E>::new(writer); 115 | 116 | serde::Serialize::serialize(&C::ID, &mut serializer)?; 117 | serde::Serialize::serialize(&C::OPTION, &mut serializer)?; 118 | serializer.reset_pos(); 119 | serde::Serialize::serialize(value, &mut serializer) 120 | } 121 | 122 | /// Deserializes a slice of bytes into an object. 123 | pub fn deserialize<'de, T>(bytes: &[u8]) -> Result 124 | where 125 | T: serde::Deserialize<'de>, 126 | { 127 | deserialize_from::<_, _, _>(bytes, Infinite) 128 | } 129 | 130 | /// Deserializes an object directly from a `Read`. 131 | pub fn deserialize_from<'de, R, T, S>(reader: R, size_limit: S) -> Result 132 | where 133 | R: Read, 134 | T: serde::Deserialize<'de>, 135 | S: SizeLimit, 136 | { 137 | use crate::encapsulation::ENCAPSULATION_HEADER_SIZE; 138 | 139 | let mut deserializer = Deserializer::<_, S, BigEndian>::new(reader, size_limit); 140 | 141 | let v: [u8; ENCAPSULATION_HEADER_SIZE as usize] = 142 | serde::Deserialize::deserialize(&mut deserializer)?; 143 | deserializer.reset_pos(); 144 | match v[1] { 145 | 0 | 2 => serde::Deserialize::deserialize(&mut deserializer), 146 | 1 | 3 => serde::Deserialize::deserialize( 147 | &mut Into::>::into(deserializer), 148 | ), 149 | _ => Err(Error::InvalidEncapsulation), 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /benches/bench.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings, clippy::all)] 2 | 3 | use cdr::{BigEndian, CdrBe, Infinite}; 4 | use criterion::{criterion_group, criterion_main, Criterion}; 5 | use serde_derive::{Deserialize, Serialize}; 6 | 7 | // cf. https://polysync.io/download/polysync-safety_and_serialization.pdf 8 | #[repr(C)] 9 | #[derive(Serialize, Deserialize)] 10 | struct LidarPointsMsg { 11 | msg_info: MsgInfo, 12 | points: Vec, 13 | } 14 | 15 | #[repr(C)] 16 | #[derive(Serialize, Deserialize)] 17 | struct MsgInfo { 18 | kind: u64, 19 | timestamp: u64, 20 | guid: u64, 21 | } 22 | 23 | #[repr(C)] 24 | #[derive(Serialize, Deserialize, Clone)] 25 | struct LidarPoint { 26 | position: [f32; 3], 27 | intensity: u8, 28 | } 29 | 30 | fn compose_lidar_points_msg() -> LidarPointsMsg { 31 | let msg_info = MsgInfo { 32 | kind: 1, 33 | timestamp: 3, 34 | guid: 5, 35 | }; 36 | let points = vec![ 37 | LidarPoint { 38 | position: [ 39 | std::f32::EPSILON, 40 | std::f32::EPSILON * 1., 41 | std::f32::EPSILON * 2., 42 | ], 43 | intensity: 7, 44 | }; 45 | 10_000 46 | ]; 47 | LidarPointsMsg { msg_info, points } 48 | } 49 | 50 | fn lidar_point_msg(b: &mut Criterion) { 51 | let msg = compose_lidar_points_msg(); 52 | b.bench_function("lidar point msg", |b| { 53 | b.iter(|| { 54 | let encoded = cdr::serialize::<_, _, CdrBe>(&msg, Infinite).unwrap(); 55 | let _decoded = cdr::deserialize::(&encoded).unwrap(); 56 | }); 57 | }); 58 | } 59 | 60 | fn lidar_point_msg_without_encapsulation(b: &mut Criterion) { 61 | let msg = compose_lidar_points_msg(); 62 | b.bench_function("lidar point msg without encapsulation", |b| { 63 | b.iter(|| { 64 | let encoded = cdr::ser::serialize_data::<_, _, BigEndian>(&msg, Infinite).unwrap(); 65 | let _decoded = 66 | cdr::de::deserialize_data::(&encoded).unwrap(); 67 | }); 68 | }); 69 | } 70 | 71 | fn lidar_point_msg_bincode(b: &mut Criterion) { 72 | let msg = compose_lidar_points_msg(); 73 | b.bench_function("lidar point msg bincode", |b| { 74 | b.iter(|| { 75 | let encoded = bincode::serialize(&msg).unwrap(); 76 | let _decoded = bincode::deserialize::(&encoded).unwrap(); 77 | }); 78 | }); 79 | } 80 | 81 | const MSG: &str = r#"What's he that wishes so? 82 | My cousin Westmoreland? No, my fair cousin: 83 | If we are mark'd to die, we are enow 84 | To do our country loss; and if to live, 85 | The fewer men, the greater share of honour. 86 | God's will! I pray thee, wish not one man more. 87 | By Jove, I am not covetous for gold, 88 | Nor care I who doth feed upon my cost; 89 | It yearns me not if men my garments wear; 90 | Such outward things dwell not in my desires: 91 | But if it be a sin to covet honour, 92 | I am the most offending soul alive. 93 | No, faith, my coz, wish not a man from England: 94 | God's peace! I would not lose so great an honour 95 | As one man more, methinks, would share from me 96 | For the best hope I have. O, do not wish one more! 97 | Rather proclaim it, Westmoreland, through my host, 98 | That he which hath no stomach to this fight, 99 | Let him depart; his passport shall be made 100 | And crowns for convoy put into his purse: 101 | We would not die in that man's company 102 | That fears his fellowship to die with us. 103 | This day is called the feast of Crispian: 104 | He that outlives this day, and comes safe home, 105 | Will stand a tip-toe when the day is named, 106 | And rouse him at the name of Crispian. 107 | He that shall live this day, and see old age, 108 | Will yearly on the vigil feast his neighbours, 109 | And say 'To-morrow is Saint Crispian:' 110 | Then will he strip his sleeve and show his scars. 111 | And say 'These wounds I had on Crispin's day.' 112 | Old men forget: yet all shall be forgot, 113 | But he'll remember with advantages 114 | What feats he did that day: then shall our names. 115 | Familiar in his mouth as household words 116 | Harry the king, Bedford and Exeter, 117 | Warwick and Talbot, Salisbury and Gloucester, 118 | Be in their flowing cups freshly remember'd. 119 | This story shall the good man teach his son; 120 | And Crispin Crispian shall ne'er go by, 121 | From this day to the ending of the world, 122 | But we in it shall be remember'd; 123 | We few, we happy few, we band of brothers; 124 | For he to-day that sheds his blood with me 125 | Shall be my brother; be he ne'er so vile, 126 | This day shall gentle his condition: 127 | And gentlemen in England now a-bed 128 | Shall think themselves accursed they were not here, 129 | And hold their manhoods cheap whiles any speaks 130 | That fought with us upon Saint Crispin's day. 131 | "#; 132 | 133 | fn string_msg(b: &mut Criterion) { 134 | b.bench_function("string msg", |b| { 135 | b.iter(|| { 136 | let encoded = cdr::serialize::<_, _, CdrBe>(MSG, Infinite).unwrap(); 137 | let _decoded = cdr::deserialize::(&encoded).unwrap(); 138 | }); 139 | }); 140 | } 141 | 142 | fn string_msg_without_encapsulation(b: &mut Criterion) { 143 | b.bench_function("string msg without encapsulation", |b| { 144 | b.iter(|| { 145 | let encoded = cdr::ser::serialize_data::<_, _, BigEndian>(MSG, Infinite).unwrap(); 146 | let _decoded = cdr::de::deserialize_data::(&encoded).unwrap(); 147 | }); 148 | }); 149 | } 150 | 151 | fn string_msg_bincode(b: &mut Criterion) { 152 | b.bench_function("string msg bincode", |b| { 153 | b.iter(|| { 154 | let encoded = bincode::serialize(MSG).unwrap(); 155 | let _decoded = bincode::deserialize::(&encoded).unwrap(); 156 | }); 157 | }); 158 | } 159 | 160 | criterion_group!( 161 | benches, 162 | lidar_point_msg, 163 | lidar_point_msg_without_encapsulation, 164 | lidar_point_msg_bincode, 165 | string_msg, 166 | string_msg_without_encapsulation, 167 | string_msg_bincode 168 | ); 169 | criterion_main!(benches); 170 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 Katsutoshi Horie 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/size.rs: -------------------------------------------------------------------------------- 1 | //! Measuring the size of (de)serialized data. 2 | 3 | use serde::ser; 4 | 5 | use crate::error::{Error, Result}; 6 | 7 | /// Limits on the number of bytes that can be read or written. 8 | pub trait SizeLimit { 9 | fn add(&mut self, n: u64) -> Result<()>; 10 | fn limit(&self) -> Option; 11 | } 12 | 13 | /// A `SizeLimit` that restricts serialized or deserialized messages so that 14 | /// they do not exceed a certain byte length. 15 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 16 | pub struct Bounded(pub u64); 17 | 18 | impl SizeLimit for Bounded { 19 | #[inline] 20 | fn add(&mut self, n: u64) -> Result<()> { 21 | if self.0 >= n { 22 | self.0 -= n; 23 | Ok(()) 24 | } else { 25 | Err(Error::SizeLimit) 26 | } 27 | } 28 | 29 | #[inline] 30 | fn limit(&self) -> Option { 31 | Some(self.0) 32 | } 33 | } 34 | 35 | /// A `SizeLimit` without a limit. 36 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 37 | pub struct Infinite; 38 | 39 | impl SizeLimit for Infinite { 40 | #[inline] 41 | fn add(&mut self, _n: u64) -> Result<()> { 42 | Ok(()) 43 | } 44 | 45 | #[inline] 46 | fn limit(&self) -> Option { 47 | None 48 | } 49 | } 50 | 51 | struct Counter { 52 | total: u64, 53 | limit: Option, 54 | } 55 | 56 | impl SizeLimit for Counter { 57 | fn add(&mut self, n: u64) -> Result<()> { 58 | self.total += n; 59 | if let Some(limit) = self.limit { 60 | if self.total > limit { 61 | return Err(Error::SizeLimit); 62 | } 63 | } 64 | Ok(()) 65 | } 66 | 67 | fn limit(&self) -> Option { 68 | unreachable!(); 69 | } 70 | } 71 | 72 | struct SizeChecker { 73 | counter: S, 74 | pos: usize, 75 | } 76 | 77 | impl SizeChecker 78 | where 79 | S: SizeLimit, 80 | { 81 | fn add_padding_of(&mut self) -> Result<()> { 82 | let alignment = std::mem::size_of::(); 83 | let rem_mask = alignment - 1; // mask like 0x0, 0x1, 0x3, 0x7 84 | match self.pos & rem_mask { 85 | 0 => Ok(()), 86 | n @ 1..=7 => { 87 | let amt = alignment - n; 88 | self.add_size(amt as u64) 89 | } 90 | _ => unreachable!(), 91 | } 92 | } 93 | 94 | fn add_size(&mut self, size: u64) -> Result<()> { 95 | self.pos += size as usize; 96 | self.counter.add(size) 97 | } 98 | 99 | fn add_usize_as_u32(&mut self, v: usize) -> Result<()> { 100 | if v > std::u32::MAX as usize { 101 | return Err(Error::NumberOutOfRange); 102 | } 103 | 104 | ser::Serializer::serialize_u32(self, v as u32) 105 | } 106 | 107 | fn add_value(&mut self, _v: T) -> Result<()> { 108 | self.add_padding_of::()?; 109 | self.add_size(std::mem::size_of::() as u64) 110 | } 111 | } 112 | 113 | macro_rules! impl_serialize_value { 114 | ($ser_method:ident($ty:ty)) => { 115 | fn $ser_method(self, v: $ty) -> Result { 116 | self.add_value(v) 117 | } 118 | }; 119 | } 120 | 121 | impl<'a, S> ser::Serializer for &'a mut SizeChecker 122 | where 123 | S: SizeLimit, 124 | { 125 | type Error = Error; 126 | type Ok = (); 127 | type SerializeMap = SizeCompound<'a, S>; 128 | type SerializeSeq = SizeCompound<'a, S>; 129 | type SerializeStruct = SizeCompound<'a, S>; 130 | type SerializeStructVariant = SizeCompound<'a, S>; 131 | type SerializeTuple = SizeCompound<'a, S>; 132 | type SerializeTupleStruct = SizeCompound<'a, S>; 133 | type SerializeTupleVariant = SizeCompound<'a, S>; 134 | 135 | impl_serialize_value! { serialize_i8(i8) } 136 | 137 | impl_serialize_value! { serialize_i16(i16) } 138 | 139 | impl_serialize_value! { serialize_i32(i32) } 140 | 141 | impl_serialize_value! { serialize_i64(i64) } 142 | 143 | impl_serialize_value! { serialize_u8(u8) } 144 | 145 | impl_serialize_value! { serialize_u16(u16) } 146 | 147 | impl_serialize_value! { serialize_u32(u32) } 148 | 149 | impl_serialize_value! { serialize_u64(u64) } 150 | 151 | impl_serialize_value! { serialize_f32(f32) } 152 | 153 | impl_serialize_value! { serialize_f64(f64) } 154 | 155 | fn serialize_bool(self, _v: bool) -> Result { 156 | self.add_value(0u8) 157 | } 158 | 159 | fn serialize_char(self, _v: char) -> Result { 160 | self.add_size(1) 161 | } 162 | 163 | fn serialize_str(self, v: &str) -> Result { 164 | self.add_value(0_u32)?; 165 | self.add_size(v.len() as u64 + 1) // adds the length 1 of a terminating character 166 | } 167 | 168 | fn serialize_bytes(self, v: &[u8]) -> Result { 169 | self.add_value(0_u32)?; 170 | self.add_size(v.len() as u64) 171 | } 172 | 173 | fn serialize_none(self) -> Result { 174 | Err(Error::TypeNotSupported) 175 | } 176 | 177 | fn serialize_some(self, _v: &T) -> Result 178 | where 179 | T: ser::Serialize + ?Sized, 180 | { 181 | Err(Error::TypeNotSupported) 182 | } 183 | 184 | fn serialize_unit(self) -> Result { 185 | Ok(()) 186 | } 187 | 188 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 189 | Ok(()) 190 | } 191 | 192 | fn serialize_unit_variant( 193 | self, 194 | _name: &'static str, 195 | variant_index: u32, 196 | _variant: &'static str, 197 | ) -> Result { 198 | self.serialize_u32(variant_index) 199 | } 200 | 201 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result 202 | where 203 | T: ser::Serialize + ?Sized, 204 | { 205 | value.serialize(self) 206 | } 207 | 208 | fn serialize_newtype_variant( 209 | self, 210 | _name: &'static str, 211 | variant_index: u32, 212 | _variant: &'static str, 213 | value: &T, 214 | ) -> Result 215 | where 216 | T: ser::Serialize + ?Sized, 217 | { 218 | self.serialize_u32(variant_index)?; 219 | value.serialize(self) 220 | } 221 | 222 | fn serialize_seq(self, len: Option) -> Result { 223 | let len = len.ok_or(Error::SequenceMustHaveLength)?; 224 | self.add_usize_as_u32(len)?; 225 | Ok(SizeCompound { ser: self }) 226 | } 227 | 228 | fn serialize_tuple(self, _len: usize) -> Result { 229 | Ok(SizeCompound { ser: self }) 230 | } 231 | 232 | fn serialize_tuple_struct( 233 | self, 234 | _name: &'static str, 235 | _len: usize, 236 | ) -> Result { 237 | Ok(SizeCompound { ser: self }) 238 | } 239 | 240 | fn serialize_tuple_variant( 241 | self, 242 | _name: &'static str, 243 | variant_index: u32, 244 | _variant: &'static str, 245 | _len: usize, 246 | ) -> Result { 247 | self.serialize_u32(variant_index)?; 248 | Ok(SizeCompound { ser: self }) 249 | } 250 | 251 | fn serialize_map(self, _len: Option) -> Result { 252 | Err(Error::TypeNotSupported) 253 | } 254 | 255 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 256 | Ok(SizeCompound { ser: self }) 257 | } 258 | 259 | fn serialize_struct_variant( 260 | self, 261 | _name: &'static str, 262 | variant_index: u32, 263 | _variant: &'static str, 264 | _len: usize, 265 | ) -> Result { 266 | self.serialize_u32(variant_index)?; 267 | Ok(SizeCompound { ser: self }) 268 | } 269 | 270 | fn is_human_readable(&self) -> bool { 271 | false 272 | } 273 | } 274 | 275 | #[doc(hidden)] 276 | pub struct SizeCompound<'a, S: 'a> { 277 | ser: &'a mut SizeChecker, 278 | } 279 | 280 | impl<'a, S> ser::SerializeSeq for SizeCompound<'a, S> 281 | where 282 | S: SizeLimit, 283 | { 284 | type Error = Error; 285 | type Ok = (); 286 | 287 | #[inline] 288 | fn serialize_element(&mut self, value: &T) -> Result<()> 289 | where 290 | T: ser::Serialize + ?Sized, 291 | { 292 | value.serialize(&mut *self.ser) 293 | } 294 | 295 | #[inline] 296 | fn end(self) -> Result<()> { 297 | Ok(()) 298 | } 299 | } 300 | 301 | impl<'a, S> ser::SerializeTuple for SizeCompound<'a, S> 302 | where 303 | S: SizeLimit, 304 | { 305 | type Error = Error; 306 | type Ok = (); 307 | 308 | #[inline] 309 | fn serialize_element(&mut self, value: &T) -> Result<()> 310 | where 311 | T: ser::Serialize + ?Sized, 312 | { 313 | value.serialize(&mut *self.ser) 314 | } 315 | 316 | #[inline] 317 | fn end(self) -> Result<()> { 318 | Ok(()) 319 | } 320 | } 321 | 322 | impl<'a, S> ser::SerializeTupleStruct for SizeCompound<'a, S> 323 | where 324 | S: SizeLimit, 325 | { 326 | type Error = Error; 327 | type Ok = (); 328 | 329 | #[inline] 330 | fn serialize_field(&mut self, value: &T) -> Result<()> 331 | where 332 | T: ser::Serialize + ?Sized, 333 | { 334 | value.serialize(&mut *self.ser) 335 | } 336 | 337 | #[inline] 338 | fn end(self) -> Result<()> { 339 | Ok(()) 340 | } 341 | } 342 | 343 | impl<'a, S> ser::SerializeTupleVariant for SizeCompound<'a, S> 344 | where 345 | S: SizeLimit, 346 | { 347 | type Error = Error; 348 | type Ok = (); 349 | 350 | #[inline] 351 | fn serialize_field(&mut self, value: &T) -> Result<()> 352 | where 353 | T: ser::Serialize + ?Sized, 354 | { 355 | value.serialize(&mut *self.ser) 356 | } 357 | 358 | #[inline] 359 | fn end(self) -> Result<()> { 360 | Ok(()) 361 | } 362 | } 363 | 364 | impl<'a, S> ser::SerializeMap for SizeCompound<'a, S> 365 | where 366 | S: SizeLimit, 367 | { 368 | type Error = Error; 369 | type Ok = (); 370 | 371 | #[inline] 372 | fn serialize_key(&mut self, key: &T) -> Result<()> 373 | where 374 | T: ser::Serialize + ?Sized, 375 | { 376 | key.serialize(&mut *self.ser) 377 | } 378 | 379 | #[inline] 380 | fn serialize_value(&mut self, value: &T) -> Result<()> 381 | where 382 | T: ser::Serialize + ?Sized, 383 | { 384 | value.serialize(&mut *self.ser) 385 | } 386 | 387 | #[inline] 388 | fn end(self) -> Result<()> { 389 | Ok(()) 390 | } 391 | } 392 | 393 | impl<'a, S> ser::SerializeStruct for SizeCompound<'a, S> 394 | where 395 | S: SizeLimit, 396 | { 397 | type Error = Error; 398 | type Ok = (); 399 | 400 | #[inline] 401 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 402 | where 403 | T: ser::Serialize + ?Sized, 404 | { 405 | value.serialize(&mut *self.ser) 406 | } 407 | 408 | #[inline] 409 | fn end(self) -> Result<()> { 410 | Ok(()) 411 | } 412 | } 413 | 414 | impl<'a, S> ser::SerializeStructVariant for SizeCompound<'a, S> 415 | where 416 | S: SizeLimit, 417 | { 418 | type Error = Error; 419 | type Ok = (); 420 | 421 | #[inline] 422 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 423 | where 424 | T: ser::Serialize + ?Sized, 425 | { 426 | value.serialize(&mut *self.ser) 427 | } 428 | 429 | #[inline] 430 | fn end(self) -> Result<()> { 431 | Ok(()) 432 | } 433 | } 434 | 435 | /// Returns the size that an object would be if serialized. 436 | pub fn calc_serialized_data_size(value: &T) -> u64 437 | where 438 | T: ser::Serialize + ?Sized, 439 | { 440 | let mut checker = SizeChecker { 441 | counter: Counter { 442 | total: 0, 443 | limit: None, 444 | }, 445 | pos: 0, 446 | }; 447 | 448 | value.serialize(&mut checker).ok(); 449 | checker.counter.total 450 | } 451 | 452 | /// Given a maximum size limit, check how large an object would be if it were 453 | /// to be serialized. 454 | pub fn calc_serialized_data_size_bounded(value: &T, max: u64) -> Result 455 | where 456 | T: ser::Serialize + ?Sized, 457 | { 458 | let mut checker = SizeChecker { 459 | counter: Bounded(max), 460 | pos: 0, 461 | }; 462 | 463 | match value.serialize(&mut checker) { 464 | Ok(_) => Ok(max - checker.counter.0), 465 | Err(e) => Err(e), 466 | } 467 | } 468 | -------------------------------------------------------------------------------- /src/de.rs: -------------------------------------------------------------------------------- 1 | //! Deserializing CDR into Rust data types. 2 | 3 | use std::{self, io::Read, marker::PhantomData}; 4 | 5 | use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt}; 6 | use serde::de::{self, IntoDeserializer}; 7 | 8 | use crate::{ 9 | error::{Error, Result}, 10 | size::{Infinite, SizeLimit}, 11 | }; 12 | 13 | /// A deserializer that reads bytes from a buffer. 14 | pub struct Deserializer { 15 | reader: R, 16 | size_limit: S, 17 | pos: u64, 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Deserializer 22 | where 23 | R: Read, 24 | S: SizeLimit, 25 | E: ByteOrder, 26 | { 27 | pub fn new(reader: R, size_limit: S) -> Self { 28 | Self { 29 | reader, 30 | size_limit, 31 | pos: 0, 32 | phantom: PhantomData, 33 | } 34 | } 35 | 36 | fn read_padding_of(&mut self) -> Result<()> { 37 | // Calculate the required padding to align with 1-byte, 2-byte, 4-byte, 8-byte 38 | // boundaries Instead of using the slow modulo operation '%', the faster 39 | // bit-masking is used 40 | let alignment = std::mem::size_of::(); 41 | let rem_mask = alignment - 1; // mask like 0x0, 0x1, 0x3, 0x7 42 | let mut padding: [u8; 8] = [0; 8]; 43 | match (self.pos as usize) & rem_mask { 44 | 0 => Ok(()), 45 | n @ 1..=7 => { 46 | let amt = alignment - n; 47 | self.read_size(amt as u64)?; 48 | self.reader 49 | .read_exact(&mut padding[..amt]) 50 | .map_err(Into::into) 51 | } 52 | _ => unreachable!(), 53 | } 54 | } 55 | 56 | fn read_size(&mut self, size: u64) -> Result<()> { 57 | self.pos += size; 58 | self.size_limit.add(size) 59 | } 60 | 61 | fn read_size_of(&mut self) -> Result<()> { 62 | self.read_size(std::mem::size_of::() as u64) 63 | } 64 | 65 | fn read_string(&mut self) -> Result { 66 | String::from_utf8(self.read_bytes().map(|mut v| { 67 | v.pop(); // removes a terminating null character 68 | v 69 | })?) 70 | .map_err(|e| Error::InvalidUtf8Encoding(e.utf8_error())) 71 | } 72 | 73 | fn read_bytes(&mut self) -> Result> { 74 | let len: u32 = de::Deserialize::deserialize(&mut *self)?; 75 | let mut buf = vec![0_u8; len as usize]; 76 | self.read_size(u64::from(len))?; 77 | self.reader.read_exact(&mut buf[..])?; 78 | Ok(buf) 79 | } 80 | 81 | pub(crate) fn reset_pos(&mut self) { 82 | self.pos = 0; 83 | } 84 | } 85 | 86 | macro_rules! impl_deserialize_value { 87 | ($de_method:ident<$ty:ty> = $visitor_method:ident ($reader_method:ident)) => { 88 | fn $de_method(self, visitor: V) -> Result 89 | where 90 | V: de::Visitor<'de>, 91 | { 92 | self.read_padding_of::<$ty>()?; 93 | self.read_size_of::<$ty>()?; 94 | visitor.$visitor_method(self.reader.$reader_method::()?) 95 | } 96 | }; 97 | } 98 | 99 | impl<'de, 'a, R, S, E> de::Deserializer<'de> for &'a mut Deserializer 100 | where 101 | R: Read, 102 | S: SizeLimit, 103 | E: ByteOrder, 104 | { 105 | type Error = Error; 106 | 107 | impl_deserialize_value!(deserialize_i16 = visit_i16(read_i16)); 108 | 109 | impl_deserialize_value!(deserialize_i32 = visit_i32(read_i32)); 110 | 111 | impl_deserialize_value!(deserialize_i64 = visit_i64(read_i64)); 112 | 113 | impl_deserialize_value!(deserialize_u16 = visit_u16(read_u16)); 114 | 115 | impl_deserialize_value!(deserialize_u32 = visit_u32(read_u32)); 116 | 117 | impl_deserialize_value!(deserialize_u64 = visit_u64(read_u64)); 118 | 119 | impl_deserialize_value!(deserialize_f32 = visit_f32(read_f32)); 120 | 121 | impl_deserialize_value!(deserialize_f64 = visit_f64(read_f64)); 122 | 123 | fn deserialize_any(self, _visitor: V) -> Result 124 | where 125 | V: de::Visitor<'de>, 126 | { 127 | Err(Error::DeserializeAnyNotSupported) 128 | } 129 | 130 | fn deserialize_bool(self, visitor: V) -> Result 131 | where 132 | V: de::Visitor<'de>, 133 | { 134 | let value: u8 = de::Deserialize::deserialize(self)?; 135 | match value { 136 | 1 => visitor.visit_bool(true), 137 | 0 => visitor.visit_bool(false), 138 | value => Err(Error::InvalidBoolEncoding(value)), 139 | } 140 | } 141 | 142 | fn deserialize_i8(self, visitor: V) -> Result 143 | where 144 | V: de::Visitor<'de>, 145 | { 146 | self.read_size_of::()?; 147 | visitor.visit_i8(self.reader.read_i8()?) 148 | } 149 | 150 | fn deserialize_u8(self, visitor: V) -> Result 151 | where 152 | V: de::Visitor<'de>, 153 | { 154 | self.read_size_of::()?; 155 | visitor.visit_u8(self.reader.read_u8()?) 156 | } 157 | 158 | fn deserialize_char(self, visitor: V) -> Result 159 | where 160 | V: de::Visitor<'de>, 161 | { 162 | let mut buf = [0u8; 4]; 163 | self.reader.read_exact(&mut buf[..1])?; 164 | 165 | if utf8_char_width(buf[0]) != 1 { 166 | Err(Error::InvalidCharEncoding) 167 | } else { 168 | self.read_size(1)?; 169 | visitor.visit_char(buf[0] as char) 170 | } 171 | } 172 | 173 | fn deserialize_str(self, visitor: V) -> Result 174 | where 175 | V: de::Visitor<'de>, 176 | { 177 | visitor.visit_str(&self.read_string()?) 178 | } 179 | 180 | fn deserialize_string(self, visitor: V) -> Result 181 | where 182 | V: de::Visitor<'de>, 183 | { 184 | visitor.visit_string(self.read_string()?) 185 | } 186 | 187 | fn deserialize_bytes(self, visitor: V) -> Result 188 | where 189 | V: de::Visitor<'de>, 190 | { 191 | visitor.visit_bytes(&self.read_bytes()?) 192 | } 193 | 194 | fn deserialize_byte_buf(self, visitor: V) -> Result 195 | where 196 | V: de::Visitor<'de>, 197 | { 198 | visitor.visit_byte_buf(self.read_bytes()?) 199 | } 200 | 201 | fn deserialize_option(self, _visitor: V) -> Result 202 | where 203 | V: de::Visitor<'de>, 204 | { 205 | Err(Error::TypeNotSupported) 206 | } 207 | 208 | fn deserialize_unit(self, visitor: V) -> Result 209 | where 210 | V: de::Visitor<'de>, 211 | { 212 | visitor.visit_unit() 213 | } 214 | 215 | fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result 216 | where 217 | V: de::Visitor<'de>, 218 | { 219 | visitor.visit_unit() 220 | } 221 | 222 | fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result 223 | where 224 | V: de::Visitor<'de>, 225 | { 226 | visitor.visit_newtype_struct(self) 227 | } 228 | 229 | fn deserialize_seq(self, visitor: V) -> Result 230 | where 231 | V: de::Visitor<'de>, 232 | { 233 | let len: u32 = de::Deserialize::deserialize(&mut *self)?; 234 | self.deserialize_tuple(len as usize, visitor) 235 | } 236 | 237 | fn deserialize_tuple(self, len: usize, visitor: V) -> Result 238 | where 239 | V: de::Visitor<'de>, 240 | { 241 | struct Access<'a, R, S, E> 242 | where 243 | R: Read + 'a, 244 | S: SizeLimit + 'a, 245 | E: ByteOrder + 'a, 246 | { 247 | deserializer: &'a mut Deserializer, 248 | len: usize, 249 | } 250 | 251 | impl<'de, 'a, R, S, E> de::SeqAccess<'de> for Access<'a, R, S, E> 252 | where 253 | R: Read + 'a, 254 | S: SizeLimit, 255 | E: ByteOrder, 256 | { 257 | type Error = Error; 258 | 259 | fn next_element_seed(&mut self, seed: T) -> Result> 260 | where 261 | T: de::DeserializeSeed<'de>, 262 | { 263 | if self.len > 0 { 264 | self.len -= 1; 265 | let value = de::DeserializeSeed::deserialize(seed, &mut *self.deserializer)?; 266 | Ok(Some(value)) 267 | } else { 268 | Ok(None) 269 | } 270 | } 271 | 272 | fn size_hint(&self) -> Option { 273 | Some(self.len) 274 | } 275 | } 276 | 277 | visitor.visit_seq(Access { 278 | deserializer: self, 279 | len, 280 | }) 281 | } 282 | 283 | fn deserialize_tuple_struct( 284 | self, 285 | _name: &'static str, 286 | len: usize, 287 | visitor: V, 288 | ) -> Result 289 | where 290 | V: de::Visitor<'de>, 291 | { 292 | self.deserialize_tuple(len, visitor) 293 | } 294 | 295 | fn deserialize_map(self, _visitor: V) -> Result 296 | where 297 | V: de::Visitor<'de>, 298 | { 299 | Err(Error::TypeNotSupported) 300 | } 301 | 302 | fn deserialize_struct( 303 | self, 304 | _name: &'static str, 305 | fields: &'static [&'static str], 306 | visitor: V, 307 | ) -> Result 308 | where 309 | V: de::Visitor<'de>, 310 | { 311 | self.deserialize_tuple(fields.len(), visitor) 312 | } 313 | 314 | fn deserialize_enum( 315 | self, 316 | _name: &'static str, 317 | _variants: &'static [&'static str], 318 | visitor: V, 319 | ) -> Result 320 | where 321 | V: de::Visitor<'de>, 322 | { 323 | impl<'de, 'a, R, S, E> de::EnumAccess<'de> for &'a mut Deserializer 324 | where 325 | R: Read + 'a, 326 | S: SizeLimit, 327 | E: ByteOrder, 328 | { 329 | type Error = Error; 330 | type Variant = Self; 331 | 332 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> 333 | where 334 | V: de::DeserializeSeed<'de>, 335 | { 336 | let idx: u32 = de::Deserialize::deserialize(&mut *self)?; 337 | let val: Result<_> = seed.deserialize(idx.into_deserializer()); 338 | Ok((val?, self)) 339 | } 340 | } 341 | 342 | visitor.visit_enum(self) 343 | } 344 | 345 | fn deserialize_identifier(self, _visitor: V) -> Result 346 | where 347 | V: de::Visitor<'de>, 348 | { 349 | Err(Error::TypeNotSupported) 350 | } 351 | 352 | fn deserialize_ignored_any(self, _visitor: V) -> Result 353 | where 354 | V: de::Visitor<'de>, 355 | { 356 | Err(Error::TypeNotSupported) 357 | } 358 | 359 | fn is_human_readable(&self) -> bool { 360 | false 361 | } 362 | } 363 | 364 | impl<'de, 'a, R, S, E> de::VariantAccess<'de> for &'a mut Deserializer 365 | where 366 | R: Read, 367 | S: SizeLimit, 368 | E: ByteOrder, 369 | { 370 | type Error = Error; 371 | 372 | fn unit_variant(self) -> Result<()> { 373 | Ok(()) 374 | } 375 | 376 | fn newtype_variant_seed(self, seed: T) -> Result 377 | where 378 | T: de::DeserializeSeed<'de>, 379 | { 380 | de::DeserializeSeed::deserialize(seed, self) 381 | } 382 | 383 | fn tuple_variant(self, len: usize, visitor: V) -> Result 384 | where 385 | V: de::Visitor<'de>, 386 | { 387 | de::Deserializer::deserialize_tuple(self, len, visitor) 388 | } 389 | 390 | fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result 391 | where 392 | V: de::Visitor<'de>, 393 | { 394 | de::Deserializer::deserialize_tuple(self, fields.len(), visitor) 395 | } 396 | } 397 | 398 | impl From> for Deserializer { 399 | fn from(t: Deserializer) -> Self { 400 | Self { 401 | reader: t.reader, 402 | size_limit: t.size_limit, 403 | pos: t.pos, 404 | phantom: PhantomData, 405 | } 406 | } 407 | } 408 | 409 | #[inline] 410 | fn utf8_char_width(first_byte: u8) -> usize { 411 | UTF8_CHAR_WIDTH[first_byte as usize] as usize 412 | } 413 | 414 | // https://tools.ietf.org/html/rfc3629 415 | const UTF8_CHAR_WIDTH: &[u8; 256] = &[ 416 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 417 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x1F 418 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 419 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x3F 420 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 421 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x5F 422 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 423 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x7F 424 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 425 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x9F 426 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 427 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xBF 428 | 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 429 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xDF 430 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF 431 | 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF 432 | ]; 433 | 434 | /// Deserializes a slice of bytes into an object. 435 | pub fn deserialize_data<'de, T, E>(bytes: &[u8]) -> Result 436 | where 437 | T: de::Deserialize<'de>, 438 | E: ByteOrder, 439 | { 440 | deserialize_data_from::<_, _, _, E>(bytes, Infinite) 441 | } 442 | 443 | /// Deserializes an object directly from a `Read`. 444 | pub fn deserialize_data_from<'de, R, T, S, E>(reader: R, size_limit: S) -> Result 445 | where 446 | R: Read, 447 | T: de::Deserialize<'de>, 448 | S: SizeLimit, 449 | E: ByteOrder, 450 | { 451 | let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit); 452 | de::Deserialize::deserialize(&mut deserializer) 453 | } 454 | -------------------------------------------------------------------------------- /tests/test.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings, clippy::all)] 2 | 3 | use std::{fmt::Debug, io::Cursor}; 4 | 5 | use cdr::{ 6 | BigEndian, Bounded, CdrBe, CdrLe, Error, Infinite, LittleEndian, PlCdrBe, PlCdrLe, Result, 7 | }; 8 | use serde_derive::{Deserialize, Serialize}; 9 | 10 | const ENCAPSULATION_HEADER_SIZE: u64 = 4; 11 | 12 | fn check<'de, T>(element: T, maybe_size: Option) 13 | where 14 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 15 | { 16 | check_serialized_size(&element, maybe_size); 17 | check_round_trip(&element, maybe_size); 18 | check_capacity_shortage(&element, maybe_size); 19 | check_size_limit(&element, maybe_size); 20 | } 21 | 22 | fn check_serialized_size<'de, T>(element: &T, maybe_size: Option) 23 | where 24 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 25 | { 26 | if let Some(serialized_size) = maybe_size { 27 | { 28 | let size = cdr::size::calc_serialized_data_size(&element); 29 | assert_eq!(serialized_size, size); 30 | } 31 | { 32 | let size = cdr::calc_serialized_size(&element); 33 | assert_eq!(serialized_size + ENCAPSULATION_HEADER_SIZE, size); 34 | } 35 | } 36 | } 37 | 38 | fn check_round_trip<'de, T>(element: &T, maybe_size: Option) 39 | where 40 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 41 | { 42 | let size = match maybe_size { 43 | Some(v) => v, 44 | None => cdr::calc_serialized_size(&element), 45 | }; 46 | { 47 | let encoded = cdr::ser::serialize_data::<_, _, BigEndian>(element, Infinite).unwrap(); 48 | let decoded = cdr::de::deserialize_data::(&encoded).unwrap(); 49 | 50 | assert_eq!(*element, decoded); 51 | assert_eq!(size, encoded.len() as u64); 52 | } 53 | { 54 | let encoded = cdr::ser::serialize_data::<_, _, LittleEndian>(element, Infinite).unwrap(); 55 | let decoded = cdr::de::deserialize_data::(&encoded).unwrap(); 56 | 57 | assert_eq!(*element, decoded); 58 | assert_eq!(size, encoded.len() as u64); 59 | } 60 | { 61 | let encoded = cdr::serialize::<_, _, CdrBe>(element, Infinite).unwrap(); 62 | let decoded = cdr::deserialize(&encoded).unwrap(); 63 | 64 | assert_eq!(*element, decoded); 65 | assert_eq!(size + ENCAPSULATION_HEADER_SIZE, encoded.len() as u64); 66 | } 67 | { 68 | let encoded = cdr::serialize::<_, _, CdrLe>(element, Infinite).unwrap(); 69 | let decoded = cdr::deserialize(&encoded).unwrap(); 70 | 71 | assert_eq!(*element, decoded); 72 | assert_eq!(size + ENCAPSULATION_HEADER_SIZE, encoded.len() as u64); 73 | } 74 | { 75 | let encoded = cdr::serialize::<_, _, PlCdrBe>(element, Infinite).unwrap(); 76 | let decoded = cdr::deserialize(&encoded).unwrap(); 77 | 78 | assert_eq!(*element, decoded); 79 | assert_eq!(size + ENCAPSULATION_HEADER_SIZE, encoded.len() as u64); 80 | } 81 | { 82 | let encoded = cdr::serialize::<_, _, PlCdrLe>(element, Infinite).unwrap(); 83 | let decoded = cdr::deserialize(&encoded).unwrap(); 84 | 85 | assert_eq!(*element, decoded); 86 | assert_eq!(size + ENCAPSULATION_HEADER_SIZE, encoded.len() as u64); 87 | } 88 | } 89 | 90 | fn check_capacity_shortage<'de, T>(element: &T, maybe_size: Option) 91 | where 92 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 93 | { 94 | let mut buf = [0u8; 2000]; 95 | if let Some(bound) = calc_invalid_size(element, maybe_size) { 96 | { 97 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 98 | assert!(cdr::ser::serialize_data_into::<_, _, _, BigEndian>( 99 | &mut buf, &element, Infinite 100 | ) 101 | .is_err()); 102 | } 103 | { 104 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 105 | assert!(cdr::ser::serialize_data_into::<_, _, _, LittleEndian>( 106 | &mut buf, &element, Infinite 107 | ) 108 | .is_err()); 109 | } 110 | { 111 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 112 | assert!(cdr::serialize_into::<_, _, _, CdrBe>(&mut buf, &element, Infinite).is_err()); 113 | } 114 | { 115 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 116 | assert!(cdr::serialize_into::<_, _, _, CdrLe>(&mut buf, &element, Infinite).is_err()); 117 | } 118 | { 119 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 120 | assert!(cdr::serialize_into::<_, _, _, PlCdrBe>(&mut buf, &element, Infinite).is_err()); 121 | } 122 | { 123 | let mut buf = Cursor::new(&mut buf[0..bound as usize]); 124 | assert!(cdr::serialize_into::<_, _, _, PlCdrLe>(&mut buf, &element, Infinite).is_err()); 125 | } 126 | } else { 127 | { 128 | let mut buf = Cursor::new(&mut buf[0..0]); 129 | assert!(cdr::ser::serialize_data_into::<_, _, _, BigEndian>( 130 | &mut buf, &element, Infinite 131 | ) 132 | .is_ok()); 133 | } 134 | { 135 | let mut buf = Cursor::new(&mut buf[0..0]); 136 | assert!(cdr::ser::serialize_data_into::<_, _, _, LittleEndian>( 137 | &mut buf, &element, Infinite 138 | ) 139 | .is_ok()); 140 | } 141 | { 142 | let mut buf = Cursor::new(&mut buf[0..ENCAPSULATION_HEADER_SIZE as usize]); 143 | assert!(cdr::serialize_into::<_, _, _, CdrBe>(&mut buf, &element, Infinite).is_ok()); 144 | } 145 | { 146 | let mut buf = Cursor::new(&mut buf[0..ENCAPSULATION_HEADER_SIZE as usize]); 147 | assert!(cdr::serialize_into::<_, _, _, CdrLe>(&mut buf, &element, Infinite).is_ok()); 148 | } 149 | { 150 | let mut buf = Cursor::new(&mut buf[0..ENCAPSULATION_HEADER_SIZE as usize]); 151 | assert!(cdr::serialize_into::<_, _, _, PlCdrBe>(&mut buf, &element, Infinite).is_ok()); 152 | } 153 | { 154 | let mut buf = Cursor::new(&mut buf[0..ENCAPSULATION_HEADER_SIZE as usize]); 155 | assert!(cdr::serialize_into::<_, _, _, PlCdrLe>(&mut buf, &element, Infinite).is_ok()); 156 | } 157 | } 158 | } 159 | 160 | fn check_size_limit<'de, T>(element: &T, maybe_size: Option) 161 | where 162 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 163 | { 164 | if let Some(bound) = calc_invalid_size(element, maybe_size) { 165 | assert!(cdr::ser::serialize_data::<_, _, BigEndian>(&element, Bounded(bound)).is_err()); 166 | assert!(cdr::ser::serialize_data::<_, _, LittleEndian>(&element, Bounded(bound)).is_err()); 167 | assert!(cdr::serialize::<_, _, CdrBe>(&element, Bounded(bound)).is_err()); 168 | assert!(cdr::serialize::<_, _, CdrLe>(&element, Bounded(bound)).is_err()); 169 | assert!(cdr::serialize::<_, _, PlCdrBe>(&element, Bounded(bound)).is_err()); 170 | assert!(cdr::serialize::<_, _, PlCdrLe>(&element, Bounded(bound)).is_err()); 171 | { 172 | let encoded = cdr::ser::serialize_data::<_, _, BigEndian>(&element, Infinite).unwrap(); 173 | let mut encoded = encoded.as_slice(); 174 | assert!(cdr::de::deserialize_data_from::<_, T, _, BigEndian>( 175 | &mut encoded, 176 | Bounded(bound) 177 | ) 178 | .is_err()); 179 | } 180 | { 181 | let encoded = 182 | cdr::ser::serialize_data::<_, _, LittleEndian>(&element, Infinite).unwrap(); 183 | let mut encoded = encoded.as_slice(); 184 | assert!(cdr::de::deserialize_data_from::<_, T, _, LittleEndian>( 185 | &mut encoded, 186 | Bounded(bound) 187 | ) 188 | .is_err()); 189 | } 190 | { 191 | let encoded = cdr::serialize::<_, _, CdrBe>(&element, Infinite).unwrap(); 192 | let mut encoded = encoded.as_slice(); 193 | assert!(cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(bound)).is_err()); 194 | } 195 | { 196 | let encoded = cdr::serialize::<_, _, CdrLe>(&element, Infinite).unwrap(); 197 | let mut encoded = encoded.as_slice(); 198 | assert!(cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(bound)).is_err()); 199 | } 200 | { 201 | let encoded = cdr::serialize::<_, _, PlCdrBe>(&element, Infinite).unwrap(); 202 | let mut encoded = encoded.as_slice(); 203 | assert!(cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(bound)).is_err()); 204 | } 205 | { 206 | let encoded = cdr::serialize::<_, _, PlCdrLe>(&element, Infinite).unwrap(); 207 | let mut encoded = encoded.as_slice(); 208 | assert!(cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(bound)).is_err()); 209 | } 210 | } else { 211 | { 212 | let encoded = 213 | cdr::ser::serialize_data::<_, _, BigEndian>(&element, Bounded(0)).unwrap(); 214 | let mut encoded = encoded.as_slice(); 215 | let decoded = 216 | cdr::de::deserialize_data_from::<_, T, _, BigEndian>(&mut encoded, Bounded(0)) 217 | .unwrap(); 218 | 219 | assert_eq!(*element, decoded); 220 | } 221 | { 222 | let encoded = 223 | cdr::ser::serialize_data::<_, _, LittleEndian>(&element, Bounded(0)).unwrap(); 224 | let mut encoded = encoded.as_slice(); 225 | let decoded = 226 | cdr::de::deserialize_data_from::<_, T, _, LittleEndian>(&mut encoded, Bounded(0)) 227 | .unwrap(); 228 | 229 | assert_eq!(*element, decoded); 230 | } 231 | { 232 | let encoded = 233 | cdr::serialize::<_, _, CdrBe>(&element, Bounded(ENCAPSULATION_HEADER_SIZE)) 234 | .unwrap(); 235 | let mut encoded = encoded.as_slice(); 236 | let decoded = 237 | cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(ENCAPSULATION_HEADER_SIZE)) 238 | .unwrap(); 239 | 240 | assert_eq!(*element, decoded); 241 | } 242 | { 243 | let encoded = 244 | cdr::serialize::<_, _, CdrLe>(&element, Bounded(ENCAPSULATION_HEADER_SIZE)) 245 | .unwrap(); 246 | let mut encoded = encoded.as_slice(); 247 | let decoded = 248 | cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(ENCAPSULATION_HEADER_SIZE)) 249 | .unwrap(); 250 | 251 | assert_eq!(*element, decoded); 252 | } 253 | { 254 | let encoded = 255 | cdr::serialize::<_, _, PlCdrBe>(&element, Bounded(ENCAPSULATION_HEADER_SIZE)) 256 | .unwrap(); 257 | let mut encoded = encoded.as_slice(); 258 | let decoded = 259 | cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(ENCAPSULATION_HEADER_SIZE)) 260 | .unwrap(); 261 | 262 | assert_eq!(*element, decoded); 263 | } 264 | { 265 | let encoded = 266 | cdr::serialize::<_, _, PlCdrLe>(&element, Bounded(ENCAPSULATION_HEADER_SIZE)) 267 | .unwrap(); 268 | let mut encoded = encoded.as_slice(); 269 | let decoded = 270 | cdr::deserialize_from::<_, T, _>(&mut encoded, Bounded(ENCAPSULATION_HEADER_SIZE)) 271 | .unwrap(); 272 | 273 | assert_eq!(*element, decoded); 274 | } 275 | } 276 | } 277 | 278 | fn calc_invalid_size<'de, T>(element: &T, maybe_size: Option) -> Option 279 | where 280 | T: serde::Serialize + serde::Deserialize<'de> + PartialEq + Debug, 281 | { 282 | match maybe_size { 283 | Some(v) if v > 0 => Some(v - 1), 284 | Some(_) => None, 285 | None => { 286 | let size = cdr::size::calc_serialized_data_size(&element); 287 | if size > 0 { 288 | Some(size - 1) 289 | } else { 290 | None 291 | } 292 | } 293 | } 294 | } 295 | 296 | #[test] 297 | fn test_octet() { 298 | check(std::u8::MIN, Some(1)); 299 | check(std::u8::MAX, Some(1)); 300 | } 301 | 302 | #[test] 303 | fn test_char() { 304 | check('a', Some(1)); 305 | check('Z', Some(1)); 306 | } 307 | 308 | #[test] 309 | fn test_unsigned_short() { 310 | check(std::u16::MIN, Some(2)); 311 | check(std::u16::MAX, Some(2)); 312 | } 313 | 314 | #[test] 315 | fn test_short() { 316 | check(std::i16::MIN, Some(2)); 317 | check(std::i16::MAX, Some(2)); 318 | } 319 | 320 | #[test] 321 | fn test_unsigned_long() { 322 | check(std::u32::MIN, Some(4)); 323 | check(std::u32::MAX, Some(4)); 324 | } 325 | 326 | #[test] 327 | fn test_long() { 328 | check(std::i32::MIN, Some(4)); 329 | check(std::i32::MAX, Some(4)); 330 | } 331 | 332 | #[test] 333 | fn test_unsigned_long_long() { 334 | check(std::u64::MIN, Some(8)); 335 | check(std::u64::MAX, Some(8)); 336 | } 337 | 338 | #[test] 339 | fn test_long_long() { 340 | check(std::i64::MIN, Some(8)); 341 | check(std::i64::MAX, Some(8)); 342 | } 343 | 344 | #[test] 345 | fn test_float() { 346 | check(std::f32::MIN, Some(4)); 347 | check(std::f32::MAX, Some(4)); 348 | } 349 | 350 | #[test] 351 | fn test_double() { 352 | check(std::f64::MIN, Some(8)); 353 | check(std::f64::MAX, Some(8)); 354 | } 355 | 356 | #[test] 357 | fn test_bool() { 358 | check(false, Some(1)); 359 | check(true, Some(1)); 360 | } 361 | 362 | #[test] 363 | fn test_string() { 364 | check("".to_string(), Some(5)); 365 | check("a".to_string(), Some(6)); 366 | } 367 | 368 | #[test] 369 | fn test_unsigned_short_alignment() { 370 | check(('a', 1u16), Some(1 + 1 + 2)); 371 | check((1u8, 1u16), Some(1 + 1 + 2)); 372 | check((1i8, 1u16), Some(1 + 1 + 2)); 373 | check((1u16, 1u16), Some(2 + 2)); 374 | check((1i16, 1u16), Some(2 + 2)); 375 | check((1u32, 1u16), Some(4 + 2)); 376 | check((1i32, 1u16), Some(4 + 2)); 377 | check((1f32, 1u16), Some(4 + 2)); 378 | check((1f64, 1u16), Some(8 + 2)); 379 | check((true, 1u16), Some(1 + 1 + 2)); 380 | check(("a".to_string(), 1u16), Some(6 + 2)); 381 | } 382 | 383 | #[test] 384 | fn test_short_alignment() { 385 | check(('a', 1i16), Some(1 + 1 + 2)); 386 | check((1u8, 1i16), Some(1 + 1 + 2)); 387 | check((1i8, 1i16), Some(1 + 1 + 2)); 388 | check((1u16, 1i16), Some(2 + 2)); 389 | check((1i16, 1i16), Some(2 + 2)); 390 | check((1u32, 1i16), Some(4 + 2)); 391 | check((1i32, 1i16), Some(4 + 2)); 392 | check((1f32, 1i16), Some(4 + 2)); 393 | check((1f64, 1i16), Some(8 + 2)); 394 | check((true, 1i16), Some(1 + 1 + 2)); 395 | check(("a".to_string(), 1i16), Some(6 + 2)); 396 | } 397 | 398 | #[test] 399 | fn test_unsigned_long_alignment() { 400 | check(('a', 1u32), Some(1 + 3 + 4)); 401 | check((1u8, 1u32), Some(1 + 3 + 4)); 402 | check((1i8, 1u32), Some(1 + 3 + 4)); 403 | check((1u16, 1u32), Some(2 + 2 + 4)); 404 | check((1i16, 1u32), Some(2 + 2 + 4)); 405 | check((1u32, 1u32), Some(4 + 4)); 406 | check((1i32, 1u32), Some(4 + 4)); 407 | check((1f32, 1u32), Some(4 + 4)); 408 | check((1f64, 1u32), Some(8 + 4)); 409 | check((true, 1u32), Some(1 + 3 + 4)); 410 | check(("a".to_string(), 1u32), Some(6 + 2 + 4)); 411 | } 412 | 413 | #[test] 414 | fn test_long_alignment() { 415 | check(('a', 1i32), Some(1 + 3 + 4)); 416 | check((1u8, 1i32), Some(1 + 3 + 4)); 417 | check((1i8, 1i32), Some(1 + 3 + 4)); 418 | check((1u16, 1i32), Some(2 + 2 + 4)); 419 | check((1i16, 1i32), Some(2 + 2 + 4)); 420 | check((1u32, 1i32), Some(4 + 4)); 421 | check((1i32, 1i32), Some(4 + 4)); 422 | check((1f32, 1i32), Some(4 + 4)); 423 | check((1f64, 1i32), Some(8 + 4)); 424 | check((true, 1i32), Some(1 + 3 + 4)); 425 | check(("a".to_string(), 1i32), Some(6 + 2 + 4)); 426 | } 427 | 428 | #[test] 429 | fn test_unsigned_long_long_alignment() { 430 | check(('a', 1u64), Some(1 + 7 + 8)); 431 | check((1u8, 1u64), Some(1 + 7 + 8)); 432 | check((1i8, 1u64), Some(1 + 7 + 8)); 433 | check((1u16, 1u64), Some(2 + 6 + 8)); 434 | check((1i16, 1u64), Some(2 + 6 + 8)); 435 | check((1u32, 1u64), Some(4 + 4 + 8)); 436 | check((1i32, 1u64), Some(4 + 4 + 8)); 437 | check((1f32, 1u64), Some(4 + 4 + 8)); 438 | check((1f64, 1u64), Some(8 + 8)); 439 | check((true, 1u64), Some(1 + 7 + 8)); 440 | check(("a".to_string(), 1u64), Some(6 + 2 + 8)); 441 | } 442 | 443 | #[test] 444 | fn test_long_long_alignment() { 445 | check(('a', 1i64), Some(1 + 7 + 8)); 446 | check((1u8, 1i64), Some(1 + 7 + 8)); 447 | check((1i8, 1i64), Some(1 + 7 + 8)); 448 | check((1u16, 1i64), Some(2 + 6 + 8)); 449 | check((1i16, 1i64), Some(2 + 6 + 8)); 450 | check((1u32, 1i64), Some(4 + 4 + 8)); 451 | check((1i32, 1i64), Some(4 + 4 + 8)); 452 | check((1f32, 1i64), Some(4 + 4 + 8)); 453 | check((1f64, 1i64), Some(8 + 8)); 454 | check((true, 1i64), Some(1 + 7 + 8)); 455 | check(("a".to_string(), 1i64), Some(6 + 2 + 8)); 456 | } 457 | 458 | #[test] 459 | fn test_float_alignment() { 460 | check(('a', 1f32), Some(1 + 3 + 4)); 461 | check((1u8, 1f32), Some(1 + 3 + 4)); 462 | check((1i8, 1f32), Some(1 + 3 + 4)); 463 | check((1u16, 1f32), Some(2 + 2 + 4)); 464 | check((1i16, 1f32), Some(2 + 2 + 4)); 465 | check((1u32, 1f32), Some(4 + 4)); 466 | check((1f32, 1f32), Some(4 + 4)); 467 | check((1f32, 1f32), Some(4 + 4)); 468 | check((1f64, 1f32), Some(8 + 4)); 469 | check((true, 1f32), Some(1 + 3 + 4)); 470 | check(("a".to_string(), 1f32), Some(6 + 2 + 4)); 471 | } 472 | 473 | #[test] 474 | fn test_double_alignment() { 475 | check(('a', 1f64), Some(1 + 7 + 8)); 476 | check((1u8, 1f64), Some(1 + 7 + 8)); 477 | check((1i8, 1f64), Some(1 + 7 + 8)); 478 | check((1u16, 1f64), Some(2 + 6 + 8)); 479 | check((1i16, 1f64), Some(2 + 6 + 8)); 480 | check((1u32, 1f64), Some(4 + 4 + 8)); 481 | check((1i32, 1f64), Some(4 + 4 + 8)); 482 | check((1f32, 1f64), Some(4 + 4 + 8)); 483 | check((1f64, 1f64), Some(8 + 8)); 484 | check((true, 1f64), Some(1 + 7 + 8)); 485 | check(("a".to_string(), 1f64), Some(6 + 2 + 8)); 486 | } 487 | 488 | #[test] 489 | fn test_seq_octet() { 490 | check(Vec::::new(), Some(4)); 491 | check(vec![0u8, 1, 2], Some(4 + 3)); 492 | } 493 | 494 | #[test] 495 | fn test_seq_char() { 496 | check(Vec::::new(), Some(4)); 497 | check(vec!['a', 'b', 'c'], Some(4 + 3)); 498 | } 499 | 500 | #[test] 501 | fn test_seq_unsigned_short() { 502 | check(Vec::::new(), Some(4)); 503 | check(vec![0u16, 1, 2], Some(4 + 2 * 3)); 504 | } 505 | 506 | #[test] 507 | fn test_seq_short() { 508 | check(Vec::::new(), Some(4)); 509 | check(vec![0i16, 1, 2], Some(4 + 2 * 3)); 510 | } 511 | 512 | #[test] 513 | fn test_seq_unsigned_long() { 514 | check(Vec::::new(), Some(4)); 515 | check(vec![0u32, 1, 2], Some(4 + 4 * 3)); 516 | } 517 | 518 | #[test] 519 | fn test_seq_long() { 520 | check(Vec::::new(), Some(4)); 521 | check(vec![0i32, 1, 2], Some(4 + 4 * 3)); 522 | } 523 | 524 | #[test] 525 | fn test_seq_unsigned_long_long() { 526 | check(Vec::::new(), Some(4)); 527 | check(vec![0u64, 1, 2], Some(4 + 4 + 8 * 3)); 528 | } 529 | 530 | #[test] 531 | fn test_seq_long_long() { 532 | check(Vec::::new(), Some(4)); 533 | check(vec![0i64, 1, 2], Some(4 + 4 + 8 * 3)); 534 | } 535 | 536 | #[test] 537 | fn test_seq_float() { 538 | check(Vec::::new(), Some(4)); 539 | check(vec![0f32, 1., 2.], Some(4 + 4 * 3)); 540 | } 541 | 542 | #[test] 543 | fn test_seq_double() { 544 | check(Vec::::new(), Some(4)); 545 | check(vec![0f64, 1., 2.], Some(4 + 4 + 8 * 3)); 546 | } 547 | 548 | #[test] 549 | fn test_seq_bool() { 550 | check(Vec::::new(), Some(4)); 551 | check(vec![false, true, false], Some(4 + 3)); 552 | } 553 | 554 | #[test] 555 | fn test_seq_string() { 556 | check(Vec::::new(), Some(4)); 557 | check( 558 | vec!["".to_string(), "a".to_string(), "b".to_string()], 559 | Some(4 + 4 + 1 + 3 + 4 + 2 + 2 + 4 + 2), 560 | ); 561 | } 562 | 563 | #[test] 564 | fn test_seq_in_seq() { 565 | check(vec![Vec::::new()], Some(8)); 566 | check(vec![vec![1i64, 3, 5], vec![-1, -3, -5]], Some(64)); 567 | } 568 | 569 | #[test] 570 | fn test_array_octet() { 571 | check([] as [u8; 0], Some(0)); 572 | check([0u8, 1, 2], Some(3)); 573 | } 574 | 575 | #[test] 576 | fn test_array_char() { 577 | check([] as [char; 0], Some(0)); 578 | check(['a', 'b', 'c'], Some(3)); 579 | } 580 | 581 | #[test] 582 | fn test_array_unsigned_short() { 583 | check([] as [u16; 0], Some(0)); 584 | check([0u16, 1, 2], Some(6)); 585 | } 586 | 587 | #[test] 588 | fn test_array_short() { 589 | check([] as [i16; 0], Some(0)); 590 | check([0i16, 1, 2], Some(6)); 591 | } 592 | 593 | #[test] 594 | fn test_array_unsigned_long() { 595 | check([] as [u32; 0], Some(0)); 596 | check([0u32, 1, 2], Some(12)); 597 | } 598 | 599 | #[test] 600 | fn test_array_long() { 601 | check([] as [i32; 0], Some(0)); 602 | check([0i32, 1, 2], Some(12)); 603 | } 604 | 605 | #[test] 606 | fn test_array_unsigned_long_long() { 607 | check([] as [u64; 0], Some(0)); 608 | check([0u64, 1, 2], Some(24)); 609 | } 610 | 611 | #[test] 612 | fn test_array_long_long() { 613 | check([] as [i64; 0], Some(0)); 614 | check([0i64, 1, 2], Some(24)); 615 | } 616 | 617 | #[test] 618 | fn test_array_float() { 619 | check([] as [f32; 0], Some(0)); 620 | check([0f32, 1., 2.], Some(12)); 621 | } 622 | 623 | #[test] 624 | fn test_array_double() { 625 | check([] as [f64; 0], Some(0)); 626 | check([0f64, 1., 2.], Some(24)); 627 | } 628 | 629 | #[test] 630 | fn test_array_bool() { 631 | check([] as [bool; 0], Some(0)); 632 | check([false, true, false], Some(3)); 633 | } 634 | 635 | #[test] 636 | fn test_array_string() { 637 | check([] as [String; 0], Some(0)); 638 | check( 639 | ["".to_string(), "a".to_string(), "b".to_string()], 640 | Some(5 + 3 + 6 + 2 + 6), 641 | ); 642 | } 643 | 644 | #[test] 645 | fn test_array_in_array() { 646 | check([[]] as [[usize; 0]; 1], Some(0)); 647 | check( 648 | [[std::f64::consts::PI, 2.71, 1.41], [1.73, 2.23, 2.44]], 649 | Some(48), 650 | ); 651 | } 652 | 653 | #[test] 654 | fn test_tuple() { 655 | check((1u32,), Some(4)); 656 | check((1u32, 2i32), Some(4 + 4)); 657 | check( 658 | (1u16, 2i16, std::f32::consts::PI, "hi".to_string()), 659 | Some(2 + 2 + 4 + 7), 660 | ); 661 | } 662 | 663 | #[test] 664 | fn test_tuple_containing_padding() { 665 | check((true, 1u64, 'z', 2.71f32), Some(24)); 666 | } 667 | 668 | #[test] 669 | fn test_struct() { 670 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 671 | struct S { 672 | c: char, 673 | n: i32, 674 | b: bool, 675 | m: u64, 676 | s: String, 677 | } 678 | 679 | check( 680 | S { 681 | c: 'x', 682 | n: -7, 683 | b: true, 684 | m: 17, 685 | s: "hello".to_string(), 686 | }, 687 | Some(34), 688 | ); 689 | } 690 | 691 | #[test] 692 | fn test_struct_in_struct() { 693 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 694 | struct Outer { 695 | i: Inner1, 696 | ii: Inner2, 697 | iii: Inner3, 698 | } 699 | 700 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 701 | struct Inner1 { 702 | a: i32, 703 | b: u64, 704 | } 705 | 706 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 707 | struct Inner2 { 708 | a: bool, 709 | b: f64, 710 | } 711 | 712 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 713 | struct Inner3 { 714 | a: char, 715 | b: f32, 716 | } 717 | 718 | check( 719 | Outer { 720 | i: Inner1 { a: -3, b: 5 }, 721 | ii: Inner2 { a: false, b: 1.414 }, 722 | iii: Inner3 { a: 'a', b: 1.732 }, 723 | }, 724 | Some(40), 725 | ); 726 | } 727 | 728 | #[test] 729 | fn test_enum() { 730 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 731 | enum E { 732 | One = 0, 733 | Two, 734 | Three, 735 | } 736 | 737 | check(vec![E::One, E::Two, E::Three], Some(4 + 4 * 3)); 738 | check( 739 | vec![E::One as u32, E::Two as u32, E::Three as u32], 740 | Some(4 + 4 * 3), 741 | ); 742 | } 743 | 744 | #[test] 745 | fn test_union() { 746 | #[derive(Serialize, Deserialize, PartialEq, Debug)] 747 | enum U { 748 | A(u32), 749 | B(i16, u32, u64), 750 | C { 751 | c: char, 752 | n: u32, 753 | b: bool, 754 | v: Vec, 755 | }, 756 | D, 757 | } 758 | 759 | check(U::A(3), Some(4 + 4)); 760 | check(U::B(1, 2, 3), Some(4 + 2 + 2 + 4 + 4 + 8)); 761 | check( 762 | U::C { 763 | c: 'a', 764 | n: 5, 765 | b: true, 766 | v: vec![1, 1, 2, 3, 5], 767 | }, 768 | Some(4 + 1 + 3 + 4 + 1 + 3 + 4 + 5), 769 | ); 770 | check(U::D, Some(4)); 771 | } 772 | 773 | #[test] 774 | fn test_unsupported() { 775 | use std::collections::{BTreeMap, HashMap}; 776 | 777 | fn check_error_kind(res: Result) { 778 | match res { 779 | Err(e) => match e { 780 | Error::TypeNotSupported => (), 781 | e => panic!("unexpected error kind: {}", e), 782 | }, 783 | _ => panic!("should be error"), 784 | } 785 | } 786 | 787 | check_error_kind(cdr::ser::serialize_data::<_, _, BigEndian>( 788 | &Some(1usize), 789 | Infinite, 790 | )); 791 | check_error_kind(cdr::ser::serialize_data::<_, _, BigEndian>( 792 | &None::, 793 | Infinite, 794 | )); 795 | check_error_kind(cdr::ser::serialize_data::<_, _, BigEndian>( 796 | &HashMap::::new(), 797 | Infinite, 798 | )); 799 | check_error_kind(cdr::ser::serialize_data::<_, _, BigEndian>( 800 | &BTreeMap::::new(), 801 | Infinite, 802 | )); 803 | 804 | check_error_kind(cdr::de::deserialize_data::, BigEndian>( 805 | Vec::new().as_slice(), 806 | )); 807 | check_error_kind( 808 | cdr::de::deserialize_data::, BigEndian>(Vec::new().as_slice()), 809 | ); 810 | check_error_kind( 811 | cdr::de::deserialize_data::, BigEndian>(Vec::new().as_slice()), 812 | ); 813 | } 814 | -------------------------------------------------------------------------------- /src/ser.rs: -------------------------------------------------------------------------------- 1 | //! Serializing Rust data types into CDR. 2 | 3 | use std::{self, io::Write, marker::PhantomData}; 4 | 5 | use byteorder::{ByteOrder, WriteBytesExt}; 6 | use serde::ser; 7 | 8 | use crate::{ 9 | error::{Error, Result}, 10 | size::{calc_serialized_data_size, calc_serialized_data_size_bounded, Infinite, SizeLimit}, 11 | }; 12 | 13 | /// A serializer that writes values into a buffer. 14 | pub struct Serializer { 15 | writer: W, 16 | pos: u64, 17 | phantom: PhantomData, 18 | } 19 | 20 | impl Serializer 21 | where 22 | W: Write, 23 | E: ByteOrder, 24 | { 25 | pub fn new(writer: W) -> Self { 26 | Self { 27 | writer, 28 | pos: 0, 29 | phantom: PhantomData, 30 | } 31 | } 32 | 33 | fn add_pos(&mut self, size: u64) { 34 | self.pos += size; 35 | } 36 | 37 | pub(crate) fn reset_pos(&mut self) { 38 | self.pos = 0; 39 | } 40 | 41 | fn set_pos_of(&mut self) -> Result<()> { 42 | self.write_padding_of::()?; 43 | self.add_pos(std::mem::size_of::() as u64); 44 | Ok(()) 45 | } 46 | 47 | fn write_padding_of(&mut self) -> Result<()> { 48 | // Calculate the required padding to align with 1-byte, 2-byte, 4-byte, 8-byte 49 | // boundaries Instead of using the slow modulo operation '%', the faster 50 | // bit-masking is used 51 | const PADDING: [u8; 8] = [0; 8]; 52 | let alignment = std::mem::size_of::(); 53 | let rem_mask = alignment - 1; // mask like 0x0, 0x1, 0x3, 0x7 54 | match (self.pos as usize) & rem_mask { 55 | 0 => Ok(()), 56 | n @ 1..=7 => { 57 | let amt = alignment - n; 58 | self.pos += amt as u64; 59 | self.writer.write_all(&PADDING[..amt]).map_err(Into::into) 60 | } 61 | _ => unreachable!(), 62 | } 63 | } 64 | 65 | fn write_usize_as_u32(&mut self, v: usize) -> Result<()> { 66 | if v > std::u32::MAX as usize { 67 | return Err(Error::NumberOutOfRange); 68 | } 69 | 70 | ser::Serializer::serialize_u32(self, v as u32) 71 | } 72 | } 73 | 74 | macro_rules! impl_serialize_value { 75 | ($ser_method:ident($ty:ty) = $writer_method:ident()) => { 76 | fn $ser_method(self, v: $ty) -> Result { 77 | self.set_pos_of::<$ty>()?; 78 | self.writer.$writer_method::(v).map_err(Into::into) 79 | } 80 | }; 81 | } 82 | 83 | impl<'a, W, E> ser::Serializer for &'a mut Serializer 84 | where 85 | W: Write, 86 | E: ByteOrder, 87 | { 88 | type Error = Error; 89 | type Ok = (); 90 | type SerializeMap = Compound<'a, W, E>; 91 | type SerializeSeq = Compound<'a, W, E>; 92 | type SerializeStruct = Compound<'a, W, E>; 93 | type SerializeStructVariant = Compound<'a, W, E>; 94 | type SerializeTuple = Compound<'a, W, E>; 95 | type SerializeTupleStruct = Compound<'a, W, E>; 96 | type SerializeTupleVariant = Compound<'a, W, E>; 97 | 98 | impl_serialize_value! { serialize_i16(i16) = write_i16() } 99 | 100 | impl_serialize_value! { serialize_i32(i32) = write_i32() } 101 | 102 | impl_serialize_value! { serialize_i64(i64) = write_i64() } 103 | 104 | impl_serialize_value! { serialize_u16(u16) = write_u16() } 105 | 106 | impl_serialize_value! { serialize_u32(u32) = write_u32() } 107 | 108 | impl_serialize_value! { serialize_u64(u64) = write_u64() } 109 | 110 | impl_serialize_value! { serialize_f32(f32) = write_f32() } 111 | 112 | impl_serialize_value! { serialize_f64(f64) = write_f64() } 113 | 114 | fn serialize_bool(self, v: bool) -> Result { 115 | self.set_pos_of::()?; 116 | self.writer.write_u8(v as u8).map_err(Into::into) 117 | } 118 | 119 | fn serialize_i8(self, v: i8) -> Result { 120 | self.set_pos_of::()?; 121 | self.writer.write_i8(v).map_err(Into::into) 122 | } 123 | 124 | fn serialize_u8(self, v: u8) -> Result { 125 | self.set_pos_of::()?; 126 | self.writer.write_u8(v).map_err(Into::into) 127 | } 128 | 129 | fn serialize_char(self, v: char) -> Result { 130 | if !v.is_ascii() { 131 | Err(Error::InvalidChar(v)) 132 | } else { 133 | let mut buf = [0u8; 1]; 134 | v.encode_utf8(&mut buf); 135 | self.add_pos(1); 136 | self.writer.write_all(&buf).map_err(Into::into) 137 | } 138 | } 139 | 140 | fn serialize_str(self, v: &str) -> Result { 141 | if !v.is_ascii() { 142 | Err(Error::InvalidString(v.into())) 143 | } else { 144 | let terminating_char = [0u8]; 145 | let l = v.len() + terminating_char.len(); 146 | self.write_usize_as_u32(l)?; 147 | self.add_pos(l as u64); 148 | self.writer.write_all(v.as_bytes())?; 149 | self.writer.write_all(&terminating_char).map_err(Into::into) 150 | } 151 | } 152 | 153 | fn serialize_bytes(self, v: &[u8]) -> Result { 154 | let l = v.len(); 155 | self.write_usize_as_u32(l)?; 156 | self.add_pos(l as u64); 157 | self.writer.write_all(v).map_err(Into::into) 158 | } 159 | 160 | fn serialize_none(self) -> Result { 161 | Err(Error::TypeNotSupported) 162 | } 163 | 164 | fn serialize_some(self, _v: &T) -> Result 165 | where 166 | T: ser::Serialize + ?Sized, 167 | { 168 | Err(Error::TypeNotSupported) 169 | } 170 | 171 | fn serialize_unit(self) -> Result { 172 | Ok(()) 173 | } 174 | 175 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 176 | Ok(()) 177 | } 178 | 179 | fn serialize_unit_variant( 180 | self, 181 | _name: &'static str, 182 | variant_index: u32, 183 | _variant: &'static str, 184 | ) -> Result { 185 | self.serialize_u32(variant_index) 186 | } 187 | 188 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result 189 | where 190 | T: ser::Serialize + ?Sized, 191 | { 192 | value.serialize(self) 193 | } 194 | 195 | fn serialize_newtype_variant( 196 | self, 197 | _name: &'static str, 198 | variant_index: u32, 199 | _variant: &'static str, 200 | value: &T, 201 | ) -> Result 202 | where 203 | T: ser::Serialize + ?Sized, 204 | { 205 | self.serialize_u32(variant_index)?; 206 | value.serialize(self) 207 | } 208 | 209 | fn serialize_seq(self, len: Option) -> Result { 210 | let len = len.ok_or(Error::SequenceMustHaveLength)?; 211 | self.write_usize_as_u32(len)?; 212 | Ok(Compound { ser: self }) 213 | } 214 | 215 | fn serialize_tuple(self, _len: usize) -> Result { 216 | Ok(Compound { ser: self }) 217 | } 218 | 219 | fn serialize_tuple_struct( 220 | self, 221 | _name: &'static str, 222 | _len: usize, 223 | ) -> Result { 224 | Ok(Compound { ser: self }) 225 | } 226 | 227 | fn serialize_tuple_variant( 228 | self, 229 | _name: &'static str, 230 | variant_index: u32, 231 | _variant: &'static str, 232 | _len: usize, 233 | ) -> Result { 234 | self.serialize_u32(variant_index)?; 235 | Ok(Compound { ser: self }) 236 | } 237 | 238 | fn serialize_map(self, _len: Option) -> Result { 239 | Err(Error::TypeNotSupported) 240 | } 241 | 242 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 243 | Ok(Compound { ser: self }) 244 | } 245 | 246 | fn serialize_struct_variant( 247 | self, 248 | _name: &'static str, 249 | variant_index: u32, 250 | _variant: &'static str, 251 | _len: usize, 252 | ) -> Result { 253 | self.serialize_u32(variant_index)?; 254 | Ok(Compound { ser: self }) 255 | } 256 | 257 | fn is_human_readable(&self) -> bool { 258 | false 259 | } 260 | } 261 | 262 | #[doc(hidden)] 263 | pub struct Compound<'a, W: 'a, E: 'a> { 264 | ser: &'a mut Serializer, 265 | } 266 | 267 | impl<'a, W, E> ser::SerializeSeq for Compound<'a, W, E> 268 | where 269 | W: Write, 270 | E: ByteOrder, 271 | { 272 | type Error = Error; 273 | type Ok = (); 274 | 275 | #[inline] 276 | fn serialize_element(&mut self, value: &T) -> Result<()> 277 | where 278 | T: ser::Serialize + ?Sized, 279 | { 280 | value.serialize(&mut *self.ser) 281 | } 282 | 283 | #[inline] 284 | fn end(self) -> Result<()> { 285 | Ok(()) 286 | } 287 | } 288 | 289 | impl<'a, W, E> ser::SerializeTuple for Compound<'a, W, E> 290 | where 291 | W: Write, 292 | E: ByteOrder, 293 | { 294 | type Error = Error; 295 | type Ok = (); 296 | 297 | #[inline] 298 | fn serialize_element(&mut self, value: &T) -> Result<()> 299 | where 300 | T: ser::Serialize + ?Sized, 301 | { 302 | value.serialize(&mut *self.ser) 303 | } 304 | 305 | #[inline] 306 | fn end(self) -> Result<()> { 307 | Ok(()) 308 | } 309 | } 310 | 311 | impl<'a, W, E> ser::SerializeTupleStruct for Compound<'a, W, E> 312 | where 313 | W: Write, 314 | E: ByteOrder, 315 | { 316 | type Error = Error; 317 | type Ok = (); 318 | 319 | #[inline] 320 | fn serialize_field(&mut self, value: &T) -> Result<()> 321 | where 322 | T: ser::Serialize + ?Sized, 323 | { 324 | value.serialize(&mut *self.ser) 325 | } 326 | 327 | #[inline] 328 | fn end(self) -> Result<()> { 329 | Ok(()) 330 | } 331 | } 332 | 333 | impl<'a, W, E> ser::SerializeTupleVariant for Compound<'a, W, E> 334 | where 335 | W: Write, 336 | E: ByteOrder, 337 | { 338 | type Error = Error; 339 | type Ok = (); 340 | 341 | #[inline] 342 | fn serialize_field(&mut self, value: &T) -> Result<()> 343 | where 344 | T: ser::Serialize + ?Sized, 345 | { 346 | value.serialize(&mut *self.ser) 347 | } 348 | 349 | #[inline] 350 | fn end(self) -> Result<()> { 351 | Ok(()) 352 | } 353 | } 354 | 355 | impl<'a, W, E> ser::SerializeMap for Compound<'a, W, E> 356 | where 357 | W: Write, 358 | E: ByteOrder, 359 | { 360 | type Error = Error; 361 | type Ok = (); 362 | 363 | #[inline] 364 | fn serialize_key(&mut self, key: &T) -> Result<()> 365 | where 366 | T: ser::Serialize + ?Sized, 367 | { 368 | key.serialize(&mut *self.ser) 369 | } 370 | 371 | #[inline] 372 | fn serialize_value(&mut self, value: &T) -> Result<()> 373 | where 374 | T: ser::Serialize + ?Sized, 375 | { 376 | value.serialize(&mut *self.ser) 377 | } 378 | 379 | #[inline] 380 | fn end(self) -> Result<()> { 381 | Ok(()) 382 | } 383 | } 384 | 385 | impl<'a, W, E> ser::SerializeStruct for Compound<'a, W, E> 386 | where 387 | W: Write, 388 | E: ByteOrder, 389 | { 390 | type Error = Error; 391 | type Ok = (); 392 | 393 | #[inline] 394 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 395 | where 396 | T: ser::Serialize + ?Sized, 397 | { 398 | value.serialize(&mut *self.ser) 399 | } 400 | 401 | #[inline] 402 | fn end(self) -> Result<()> { 403 | Ok(()) 404 | } 405 | } 406 | 407 | impl<'a, W, E> ser::SerializeStructVariant for Compound<'a, W, E> 408 | where 409 | W: Write, 410 | E: ByteOrder, 411 | { 412 | type Error = Error; 413 | type Ok = (); 414 | 415 | #[inline] 416 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 417 | where 418 | T: ser::Serialize + ?Sized, 419 | { 420 | value.serialize(&mut *self.ser) 421 | } 422 | 423 | #[inline] 424 | fn end(self) -> Result<()> { 425 | Ok(()) 426 | } 427 | } 428 | 429 | /// Serializes a serializable object into a `Vec` of bytes. 430 | pub fn serialize_data(value: &T, size_limit: S) -> Result> 431 | where 432 | T: ser::Serialize + ?Sized, 433 | S: SizeLimit, 434 | E: ByteOrder, 435 | { 436 | let mut writer = match size_limit.limit() { 437 | Some(limit) => { 438 | let actual_size = calc_serialized_data_size_bounded(value, limit)?; 439 | Vec::with_capacity(actual_size as usize) 440 | } 441 | None => { 442 | let size = calc_serialized_data_size(value) as usize; 443 | Vec::with_capacity(size) 444 | } 445 | }; 446 | 447 | serialize_data_into::<_, _, _, E>(&mut writer, value, Infinite)?; 448 | Ok(writer) 449 | } 450 | 451 | /// Serializes an object directly into a `Write`. 452 | pub fn serialize_data_into(writer: W, value: &T, size_limit: S) -> Result<()> 453 | where 454 | W: Write, 455 | T: ser::Serialize + ?Sized, 456 | S: SizeLimit, 457 | E: ByteOrder, 458 | { 459 | if let Some(limit) = size_limit.limit() { 460 | calc_serialized_data_size_bounded(value, limit)?; 461 | } 462 | 463 | let mut serializer = Serializer::<_, E>::new(writer); 464 | ser::Serialize::serialize(value, &mut serializer) 465 | } 466 | 467 | #[cfg(test)] 468 | mod tests { 469 | use byteorder::{BigEndian, LittleEndian}; 470 | 471 | use super::*; 472 | 473 | #[test] 474 | fn serialize_octet() { 475 | let v = 32u8; 476 | assert_eq!( 477 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 478 | vec![0x20] 479 | ); 480 | assert_eq!( 481 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 482 | vec![0x20] 483 | ); 484 | } 485 | 486 | #[test] 487 | fn serialize_char() { 488 | let v = 'Z'; 489 | assert_eq!( 490 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 491 | vec![0x5a] 492 | ); 493 | assert_eq!( 494 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 495 | vec![0x5a] 496 | ); 497 | } 498 | 499 | #[test] 500 | fn serialize_wchar() { 501 | let v = 'Å'; 502 | assert!(serialize_data::<_, _, BigEndian>(&v, Infinite).is_err()); 503 | assert!(serialize_data::<_, _, LittleEndian>(&v, Infinite).is_err()); 504 | } 505 | 506 | #[test] 507 | fn serialize_ushort() { 508 | let v = 65500u16; 509 | assert_eq!( 510 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 511 | vec![0xff, 0xdc] 512 | ); 513 | assert_eq!( 514 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 515 | vec![0xdc, 0xff] 516 | ); 517 | } 518 | 519 | #[test] 520 | fn serialize_short() { 521 | let v = -32700i16; 522 | assert_eq!( 523 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 524 | vec![0x80, 0x44] 525 | ); 526 | assert_eq!( 527 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 528 | vec![0x44, 0x80] 529 | ); 530 | } 531 | 532 | #[test] 533 | fn serialize_ulong() { 534 | let v = 4294967200u32; 535 | assert_eq!( 536 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 537 | vec![0xff, 0xff, 0xff, 0xa0] 538 | ); 539 | assert_eq!( 540 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 541 | vec![0xa0, 0xff, 0xff, 0xff] 542 | ); 543 | } 544 | 545 | #[test] 546 | fn serialize_long() { 547 | let v = -2147483600i32; 548 | assert_eq!( 549 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 550 | vec![0x80, 0x00, 0x00, 0x30] 551 | ); 552 | assert_eq!( 553 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 554 | vec![0x30, 0x00, 0x00, 0x80] 555 | ); 556 | } 557 | 558 | #[test] 559 | fn serialize_ulonglong() { 560 | let v = 18446744073709551600u64; 561 | assert_eq!( 562 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 563 | vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0] 564 | ); 565 | assert_eq!( 566 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 567 | vec![0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] 568 | ); 569 | } 570 | 571 | #[test] 572 | fn serialize_longlong() { 573 | let v = -9223372036800i64; 574 | assert_eq!( 575 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 576 | vec![0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x40] 577 | ); 578 | assert_eq!( 579 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 580 | vec![0x40, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff] 581 | ); 582 | } 583 | 584 | #[test] 585 | fn serialize_float() { 586 | let v = std::f32::MIN_POSITIVE; 587 | assert_eq!( 588 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 589 | vec![0x00, 0x80, 0x00, 0x00] 590 | ); 591 | assert_eq!( 592 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 593 | vec![0x00, 0x00, 0x80, 0x00] 594 | ); 595 | } 596 | 597 | #[test] 598 | fn serialize_double() { 599 | let v = std::f64::MIN_POSITIVE; 600 | assert_eq!( 601 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 602 | vec![0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 603 | ); 604 | assert_eq!( 605 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 606 | vec![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00] 607 | ); 608 | } 609 | 610 | #[test] 611 | fn serialize_bool() { 612 | let v = true; 613 | assert_eq!( 614 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 615 | vec![0x01] 616 | ); 617 | assert_eq!( 618 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 619 | vec![0x01] 620 | ); 621 | } 622 | 623 | #[test] 624 | fn serialize_string() { 625 | let v = "Hola a todos, esto es un test"; 626 | assert_eq!( 627 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 628 | vec![ 629 | 0x00, 0x00, 0x00, 0x1e, 0x48, 0x6f, 0x6c, 0x61, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x64, 630 | 0x6f, 0x73, 0x2c, 0x20, 0x65, 0x73, 0x74, 0x6f, 0x20, 0x65, 0x73, 0x20, 0x75, 0x6e, 631 | 0x20, 0x74, 0x65, 0x73, 0x74, 0x00, 632 | ] 633 | ); 634 | assert_eq!( 635 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 636 | vec![ 637 | 0x1e, 0x00, 0x00, 0x00, 0x48, 0x6f, 0x6c, 0x61, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x64, 638 | 0x6f, 0x73, 0x2c, 0x20, 0x65, 0x73, 0x74, 0x6f, 0x20, 0x65, 0x73, 0x20, 0x75, 0x6e, 639 | 0x20, 0x74, 0x65, 0x73, 0x74, 0x00, 640 | ] 641 | ); 642 | } 643 | 644 | #[test] 645 | fn serialize_wstring() { 646 | let v = "みなさんこんにちは。これはテストです。"; 647 | assert!(serialize_data::<_, _, BigEndian>(&v, Infinite).is_err()); 648 | assert!(serialize_data::<_, _, LittleEndian>(&v, Infinite).is_err()); 649 | } 650 | 651 | #[test] 652 | fn serialize_empty_string() { 653 | let v = ""; 654 | assert_eq!( 655 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 656 | vec![0x00, 0x00, 0x00, 0x01, 0x00] 657 | ); 658 | assert_eq!( 659 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 660 | vec![0x01, 0x00, 0x00, 0x00, 0x00] 661 | ); 662 | } 663 | 664 | #[test] 665 | fn serialize_octet_array() { 666 | let v = [1u8, 2, 3, 4, 5]; 667 | assert_eq!( 668 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 669 | vec![0x01, 0x02, 0x03, 0x04, 0x05] 670 | ); 671 | assert_eq!( 672 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 673 | vec![0x01, 0x02, 0x03, 0x04, 0x05] 674 | ); 675 | } 676 | 677 | #[test] 678 | fn serialize_char_array() { 679 | let v = ['A', 'B', 'C', 'D', 'E']; 680 | assert_eq!( 681 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 682 | vec![0x41, 0x42, 0x43, 0x44, 0x45] 683 | ); 684 | assert_eq!( 685 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 686 | vec![0x41, 0x42, 0x43, 0x44, 0x45] 687 | ); 688 | } 689 | 690 | #[test] 691 | fn serialize_ushort_array() { 692 | let v = [65500u16, 65501, 65502, 65503, 65504]; 693 | assert_eq!( 694 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 695 | vec![ 696 | 0xff, 0xdc, // 697 | 0xff, 0xdd, // 698 | 0xff, 0xde, // 699 | 0xff, 0xdf, // 700 | 0xff, 0xe0 701 | ] 702 | ); 703 | assert_eq!( 704 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 705 | vec![ 706 | 0xdc, 0xff, // 707 | 0xdd, 0xff, // 708 | 0xde, 0xff, // 709 | 0xdf, 0xff, // 710 | 0xe0, 0xff 711 | ] 712 | ); 713 | } 714 | 715 | #[test] 716 | fn serialize_short_array() { 717 | let v = [-32700i16, -32701, -32702, -32703, -32704]; 718 | assert_eq!( 719 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 720 | vec![ 721 | 0x80, 0x44, // 722 | 0x80, 0x43, // 723 | 0x80, 0x42, // 724 | 0x80, 0x41, // 725 | 0x80, 0x40 726 | ] 727 | ); 728 | assert_eq!( 729 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 730 | vec![ 731 | 0x44, 0x80, // 732 | 0x43, 0x80, // 733 | 0x42, 0x80, // 734 | 0x41, 0x80, // 735 | 0x40, 0x80 736 | ] 737 | ); 738 | } 739 | 740 | #[test] 741 | fn serialize_ulong_array() { 742 | let v = [ 743 | 4294967200u32, 744 | 4294967201, 745 | 4294967202, 746 | 4294967203, 747 | 4294967204, 748 | ]; 749 | assert_eq!( 750 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 751 | vec![ 752 | 0xff, 0xff, 0xff, 0xa0, // 753 | 0xff, 0xff, 0xff, 0xa1, // 754 | 0xff, 0xff, 0xff, 0xa2, // 755 | 0xff, 0xff, 0xff, 0xa3, // 756 | 0xff, 0xff, 0xff, 0xa4, 757 | ] 758 | ); 759 | assert_eq!( 760 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 761 | vec![ 762 | 0xa0, 0xff, 0xff, 0xff, // 763 | 0xa1, 0xff, 0xff, 0xff, // 764 | 0xa2, 0xff, 0xff, 0xff, // 765 | 0xa3, 0xff, 0xff, 0xff, // 766 | 0xa4, 0xff, 0xff, 0xff, 767 | ] 768 | ); 769 | } 770 | 771 | #[test] 772 | fn serialize_long_array() { 773 | let v = [ 774 | -2147483600, 775 | -2147483601, 776 | -2147483602, 777 | -2147483603, 778 | -2147483604, 779 | ]; 780 | assert_eq!( 781 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 782 | vec![ 783 | 0x80, 0x00, 0x00, 0x30, // 784 | 0x80, 0x00, 0x00, 0x2f, // 785 | 0x80, 0x00, 0x00, 0x2e, // 786 | 0x80, 0x00, 0x00, 0x2d, // 787 | 0x80, 0x00, 0x00, 0x2c, 788 | ] 789 | ); 790 | assert_eq!( 791 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 792 | vec![ 793 | 0x30, 0x00, 0x00, 0x80, // 794 | 0x2f, 0x00, 0x00, 0x80, // 795 | 0x2e, 0x00, 0x00, 0x80, // 796 | 0x2d, 0x00, 0x00, 0x80, // 797 | 0x2c, 0x00, 0x00, 0x80, 798 | ] 799 | ); 800 | } 801 | 802 | #[test] 803 | fn serialize_ulonglong_array() { 804 | let v = [ 805 | 18446744073709551600u64, 806 | 18446744073709551601, 807 | 18446744073709551602, 808 | 18446744073709551603, 809 | 18446744073709551604, 810 | ]; 811 | assert_eq!( 812 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 813 | vec![ 814 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, // 815 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, // 816 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, // 817 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, // 818 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 819 | ] 820 | ); 821 | assert_eq!( 822 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 823 | vec![ 824 | 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 825 | 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 826 | 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 827 | 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 828 | 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 829 | ] 830 | ); 831 | } 832 | 833 | #[test] 834 | fn serialize_longlong_array() { 835 | let v = [ 836 | -9223372036800i64, 837 | -9223372036801, 838 | -9223372036802, 839 | -9223372036803, 840 | -9223372036804, 841 | ]; 842 | assert_eq!( 843 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 844 | vec![ 845 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x40, // 846 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3f, // 847 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3e, // 848 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3d, // 849 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3c, 850 | ] 851 | ); 852 | assert_eq!( 853 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 854 | vec![ 855 | 0x40, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 856 | 0x3f, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 857 | 0x3e, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 858 | 0x3d, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 859 | 0x3c, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, 860 | ] 861 | ); 862 | } 863 | 864 | #[test] 865 | fn serialize_float_array() { 866 | let f = std::f32::MIN_POSITIVE; 867 | 868 | let v = [f, f + 1., f + 2., f + 3., f + 4.]; 869 | assert_eq!( 870 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 871 | vec![ 872 | 0x00, 0x80, 0x00, 0x00, // 873 | 0x3f, 0x80, 0x00, 0x00, // 874 | 0x40, 0x00, 0x00, 0x00, // 875 | 0x40, 0x40, 0x00, 0x00, // 876 | 0x40, 0x80, 0x00, 0x00, 877 | ] 878 | ); 879 | assert_eq!( 880 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 881 | vec![ 882 | 0x00, 0x00, 0x80, 0x00, // 883 | 0x00, 0x00, 0x80, 0x3f, // 884 | 0x00, 0x00, 0x00, 0x40, // 885 | 0x00, 0x00, 0x40, 0x40, // 886 | 0x00, 0x00, 0x80, 0x40, 887 | ] 888 | ); 889 | } 890 | 891 | #[test] 892 | fn serialize_double_array() { 893 | let f = std::f64::MIN_POSITIVE; 894 | 895 | let v = [f, f + 1., f + 2., f + 3., f + 4.]; 896 | assert_eq!( 897 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 898 | vec![ 899 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 900 | 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 901 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 902 | 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 903 | 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 904 | ] 905 | ); 906 | assert_eq!( 907 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 908 | vec![ 909 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, // 910 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, // 911 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // 912 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, // 913 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 914 | ] 915 | ); 916 | } 917 | 918 | #[test] 919 | fn serialize_bool_array() { 920 | let v = [true, false, true, false, true]; 921 | assert_eq!( 922 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 923 | vec![0x01, 0x00, 0x01, 0x00, 0x01] 924 | ); 925 | assert_eq!( 926 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 927 | vec![0x01, 0x00, 0x01, 0x00, 0x01] 928 | ); 929 | } 930 | 931 | #[test] 932 | fn serialize_string_array() { 933 | let v = ["HOLA", "ADIOS", "HELLO", "BYE", "GOODBYE"]; 934 | assert_eq!( 935 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 936 | vec![ 937 | 0x00, 0x00, 0x00, 0x05, // 938 | 0x48, 0x4f, 0x4c, 0x41, 0x00, // 939 | 0x00, 0x00, 0x00, // 940 | 0x00, 0x00, 0x00, 0x06, // 941 | 0x41, 0x44, 0x49, 0x4f, 0x53, 0x00, // 942 | 0x00, 0x00, // 943 | 0x00, 0x00, 0x00, 0x06, // 944 | 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x00, // 945 | 0x00, 0x00, // 946 | 0x00, 0x00, 0x00, 0x04, // 947 | 0x42, 0x59, 0x45, 0x00, // 948 | 0x00, 0x00, 0x00, 0x08, // 949 | 0x47, 0x4f, 0x4f, 0x44, 0x42, 0x59, 0x45, 0x00, 950 | ] 951 | ); 952 | assert_eq!( 953 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 954 | vec![ 955 | 0x05, 0x00, 0x00, 0x00, // 956 | 0x48, 0x4f, 0x4c, 0x41, 0x00, // 957 | 0x00, 0x00, 0x00, // 958 | 0x06, 0x00, 0x00, 0x00, // 959 | 0x41, 0x44, 0x49, 0x4f, 0x53, 0x00, // 960 | 0x00, 0x00, // 961 | 0x06, 0x00, 0x00, 0x00, // 962 | 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x00, // 963 | 0x00, 0x00, // 964 | 0x04, 0x00, 0x00, 0x00, // 965 | 0x42, 0x59, 0x45, 0x00, // 966 | 0x08, 0x00, 0x00, 0x00, // 967 | 0x47, 0x4f, 0x4f, 0x44, 0x42, 0x59, 0x45, 0x00, 968 | ] 969 | ); 970 | } 971 | 972 | #[test] 973 | fn serialize_octet_sequence() { 974 | let v = vec![1u8, 2, 3, 4, 5]; 975 | assert_eq!( 976 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 977 | vec![ 978 | 0x00, 0x00, 0x00, 0x05, // 979 | 0x01, 0x02, 0x03, 0x04, 0x05 980 | ] 981 | ); 982 | assert_eq!( 983 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 984 | vec![ 985 | 0x05, 0x00, 0x00, 0x00, // 986 | 0x01, 0x02, 0x03, 0x04, 0x05 987 | ] 988 | ); 989 | } 990 | 991 | #[test] 992 | fn serialize_char_sequence() { 993 | let v = vec!['A', 'B', 'C', 'D', 'E']; 994 | assert_eq!( 995 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 996 | vec![ 997 | 0x00, 0x00, 0x00, 0x05, // 998 | 0x41, 0x42, 0x43, 0x44, 0x45 999 | ] 1000 | ); 1001 | assert_eq!( 1002 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1003 | vec![ 1004 | 0x05, 0x00, 0x00, 0x00, // 1005 | 0x41, 0x42, 0x43, 0x44, 0x45 1006 | ] 1007 | ); 1008 | } 1009 | 1010 | #[test] 1011 | fn serialize_ushort_sequence() { 1012 | let v = vec![65500u16, 65501, 65502, 65503, 65504]; 1013 | assert_eq!( 1014 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1015 | vec![ 1016 | 0x00, 0x00, 0x00, 0x05, // 1017 | 0xff, 0xdc, // 1018 | 0xff, 0xdd, // 1019 | 0xff, 0xde, // 1020 | 0xff, 0xdf, // 1021 | 0xff, 0xe0 1022 | ] 1023 | ); 1024 | assert_eq!( 1025 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1026 | vec![ 1027 | 0x05, 0x00, 0x00, 0x00, // 1028 | 0xdc, 0xff, // 1029 | 0xdd, 0xff, // 1030 | 0xde, 0xff, // 1031 | 0xdf, 0xff, // 1032 | 0xe0, 0xff 1033 | ] 1034 | ); 1035 | } 1036 | 1037 | #[test] 1038 | fn serialize_short_sequence() { 1039 | let v = vec![-32700i16, -32701, -32702, -32703, -32704]; 1040 | assert_eq!( 1041 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1042 | vec![ 1043 | 0x00, 0x00, 0x00, 0x05, // 1044 | 0x80, 0x44, // 1045 | 0x80, 0x43, // 1046 | 0x80, 0x42, // 1047 | 0x80, 0x41, // 1048 | 0x80, 0x40 1049 | ] 1050 | ); 1051 | assert_eq!( 1052 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1053 | vec![ 1054 | 0x05, 0x00, 0x00, 0x00, // 1055 | 0x44, 0x80, // 1056 | 0x43, 0x80, // 1057 | 0x42, 0x80, // 1058 | 0x41, 0x80, // 1059 | 0x40, 0x80 1060 | ] 1061 | ); 1062 | } 1063 | 1064 | #[test] 1065 | fn serialize_ulong_sequence() { 1066 | let v = vec![ 1067 | 4294967200u32, 1068 | 4294967201, 1069 | 4294967202, 1070 | 4294967203, 1071 | 4294967204, 1072 | ]; 1073 | assert_eq!( 1074 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1075 | vec![ 1076 | 0x00, 0x00, 0x00, 0x05, // 1077 | 0xff, 0xff, 0xff, 0xa0, // 1078 | 0xff, 0xff, 0xff, 0xa1, // 1079 | 0xff, 0xff, 0xff, 0xa2, // 1080 | 0xff, 0xff, 0xff, 0xa3, // 1081 | 0xff, 0xff, 0xff, 0xa4, 1082 | ] 1083 | ); 1084 | assert_eq!( 1085 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1086 | vec![ 1087 | 0x05, 0x00, 0x00, 0x00, // 1088 | 0xa0, 0xff, 0xff, 0xff, // 1089 | 0xa1, 0xff, 0xff, 0xff, // 1090 | 0xa2, 0xff, 0xff, 0xff, // 1091 | 0xa3, 0xff, 0xff, 0xff, // 1092 | 0xa4, 0xff, 0xff, 0xff, 1093 | ] 1094 | ); 1095 | } 1096 | 1097 | #[test] 1098 | fn serialize_long_sequence() { 1099 | let v = vec![ 1100 | -2147483600, 1101 | -2147483601, 1102 | -2147483602, 1103 | -2147483603, 1104 | -2147483604, 1105 | ]; 1106 | assert_eq!( 1107 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1108 | vec![ 1109 | 0x00, 0x00, 0x00, 0x05, // 1110 | 0x80, 0x00, 0x00, 0x30, // 1111 | 0x80, 0x00, 0x00, 0x2f, // 1112 | 0x80, 0x00, 0x00, 0x2e, // 1113 | 0x80, 0x00, 0x00, 0x2d, // 1114 | 0x80, 0x00, 0x00, 0x2c, 1115 | ] 1116 | ); 1117 | assert_eq!( 1118 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1119 | vec![ 1120 | 0x05, 0x00, 0x00, 0x00, // 1121 | 0x30, 0x00, 0x00, 0x80, // 1122 | 0x2f, 0x00, 0x00, 0x80, // 1123 | 0x2e, 0x00, 0x00, 0x80, // 1124 | 0x2d, 0x00, 0x00, 0x80, // 1125 | 0x2c, 0x00, 0x00, 0x80, 1126 | ] 1127 | ); 1128 | } 1129 | 1130 | #[test] 1131 | fn serialize_ulonglong_sequence() { 1132 | let v = vec![ 1133 | 18446744073709551600u64, 1134 | 18446744073709551601, 1135 | 18446744073709551602, 1136 | 18446744073709551603, 1137 | 18446744073709551604, 1138 | ]; 1139 | assert_eq!( 1140 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1141 | vec![ 1142 | 0x00, 0x00, 0x00, 0x05, // 1143 | 0x00, 0x00, 0x00, 0x00, // 1144 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, // 1145 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, // 1146 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, // 1147 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, // 1148 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 1149 | ] 1150 | ); 1151 | assert_eq!( 1152 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1153 | vec![ 1154 | 0x05, 0x00, 0x00, 0x00, // 1155 | 0x00, 0x00, 0x00, 0x00, // 1156 | 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 1157 | 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 1158 | 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 1159 | 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 1160 | 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1161 | ] 1162 | ); 1163 | } 1164 | 1165 | #[test] 1166 | fn serialize_longlong_sequence() { 1167 | let v = vec![ 1168 | -9223372036800i64, 1169 | -9223372036801, 1170 | -9223372036802, 1171 | -9223372036803, 1172 | -9223372036804, 1173 | ]; 1174 | assert_eq!( 1175 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1176 | vec![ 1177 | 0x00, 0x00, 0x00, 0x05, // 1178 | 0x00, 0x00, 0x00, 0x00, // 1179 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x40, // 1180 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3f, // 1181 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3e, // 1182 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3d, // 1183 | 0xff, 0xff, 0xf7, 0x9c, 0x84, 0x2f, 0xa5, 0x3c, 1184 | ] 1185 | ); 1186 | assert_eq!( 1187 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1188 | vec![ 1189 | 0x05, 0x00, 0x00, 0x00, // 1190 | 0x00, 0x00, 0x00, 0x00, // 1191 | 0x40, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 1192 | 0x3f, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 1193 | 0x3e, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 1194 | 0x3d, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, // 1195 | 0x3c, 0xa5, 0x2f, 0x84, 0x9c, 0xf7, 0xff, 0xff, 1196 | ] 1197 | ); 1198 | } 1199 | 1200 | #[test] 1201 | fn serialize_float_sequence() { 1202 | let f = std::f32::MIN_POSITIVE; 1203 | 1204 | let v = vec![f, f + 1., f + 2., f + 3., f + 4.]; 1205 | assert_eq!( 1206 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1207 | vec![ 1208 | 0x00, 0x00, 0x00, 0x05, // 1209 | 0x00, 0x80, 0x00, 0x00, // 1210 | 0x3f, 0x80, 0x00, 0x00, // 1211 | 0x40, 0x00, 0x00, 0x00, // 1212 | 0x40, 0x40, 0x00, 0x00, // 1213 | 0x40, 0x80, 0x00, 0x00, 1214 | ] 1215 | ); 1216 | assert_eq!( 1217 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1218 | vec![ 1219 | 0x05, 0x00, 0x00, 0x00, // 1220 | 0x00, 0x00, 0x80, 0x00, // 1221 | 0x00, 0x00, 0x80, 0x3f, // 1222 | 0x00, 0x00, 0x00, 0x40, // 1223 | 0x00, 0x00, 0x40, 0x40, // 1224 | 0x00, 0x00, 0x80, 0x40, 1225 | ] 1226 | ); 1227 | } 1228 | 1229 | #[test] 1230 | fn serialize_double_sequence() { 1231 | let f = std::f64::MIN_POSITIVE; 1232 | 1233 | let v = vec![f, f + 1., f + 2., f + 3., f + 4.]; 1234 | assert_eq!( 1235 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1236 | vec![ 1237 | 0x00, 0x00, 0x00, 0x05, // 1238 | 0x00, 0x00, 0x00, 0x00, // 1239 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1240 | 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1241 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1242 | 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1243 | 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1244 | ] 1245 | ); 1246 | assert_eq!( 1247 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1248 | vec![ 1249 | 0x05, 0x00, 0x00, 0x00, // 1250 | 0x00, 0x00, 0x00, 0x00, // 1251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, // 1252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, // 1253 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // 1254 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, // 1255 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 1256 | ] 1257 | ); 1258 | } 1259 | 1260 | #[test] 1261 | fn serialize_bool_sequence() { 1262 | let v = vec![true, false, true, false, true]; 1263 | assert_eq!( 1264 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1265 | vec![ 1266 | 0x00, 0x00, 0x00, 0x05, // 1267 | 0x01, 0x00, 0x01, 0x00, 0x01 1268 | ] 1269 | ); 1270 | assert_eq!( 1271 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1272 | vec![ 1273 | 0x05, 0x00, 0x00, 0x00, // 1274 | 0x01, 0x00, 0x01, 0x00, 0x01 1275 | ] 1276 | ); 1277 | } 1278 | 1279 | #[test] 1280 | fn serialize_string_sequence() { 1281 | let v = vec!["HOLA", "ADIOS", "HELLO", "BYE", "GOODBYE"]; 1282 | assert_eq!( 1283 | serialize_data::<_, _, BigEndian>(&v, Infinite).unwrap(), 1284 | vec![ 1285 | 0x00, 0x00, 0x00, 0x05, // 1286 | 0x00, 0x00, 0x00, 0x05, // 1287 | 0x48, 0x4f, 0x4c, 0x41, 0x00, // 1288 | 0x00, 0x00, 0x00, // 1289 | 0x00, 0x00, 0x00, 0x06, // 1290 | 0x41, 0x44, 0x49, 0x4f, 0x53, 0x00, // 1291 | 0x00, 0x00, // 1292 | 0x00, 0x00, 0x00, 0x06, // 1293 | 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x00, // 1294 | 0x00, 0x00, // 1295 | 0x00, 0x00, 0x00, 0x04, // 1296 | 0x42, 0x59, 0x45, 0x00, // 1297 | 0x00, 0x00, 0x00, 0x08, // 1298 | 0x47, 0x4f, 0x4f, 0x44, 0x42, 0x59, 0x45, 0x00, 1299 | ] 1300 | ); 1301 | assert_eq!( 1302 | serialize_data::<_, _, LittleEndian>(&v, Infinite).unwrap(), 1303 | vec![ 1304 | 0x05, 0x00, 0x00, 0x00, // 1305 | 0x05, 0x00, 0x00, 0x00, // 1306 | 0x48, 0x4f, 0x4c, 0x41, 0x00, // 1307 | 0x00, 0x00, 0x00, // 1308 | 0x06, 0x00, 0x00, 0x00, // 1309 | 0x41, 0x44, 0x49, 0x4f, 0x53, 0x00, // 1310 | 0x00, 0x00, // 1311 | 0x06, 0x00, 0x00, 0x00, // 1312 | 0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x00, // 1313 | 0x00, 0x00, // 1314 | 0x04, 0x00, 0x00, 0x00, // 1315 | 0x42, 0x59, 0x45, 0x00, // 1316 | 0x08, 0x00, 0x00, 0x00, // 1317 | 0x47, 0x4f, 0x4f, 0x44, 0x42, 0x59, 0x45, 0x00, 1318 | ] 1319 | ); 1320 | } 1321 | } 1322 | --------------------------------------------------------------------------------