commit 936aeab692055c01de4af768cf2c4c894b07fe2d Author: Nicolas Stalder Date: Sun Jan 31 15:01:17 2021 +0100 Re-extraction from `solo-bee` diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f6c6f2b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "cbor-smol" +version = "0.1.0" +authors = ["Nicolas Stalder "] +edition = "2018" +description = "Streamlined serde serializer/deserializer for CBOR" +repository = "https://github.com/nickray/cbor-smol" +readme = "README.md" +license = "Apache-2.0 OR MIT" +documentation = "https://docs.rs/cbor-smol" +keywords = ["CBOR", "serde"] +categories = ["development-tools", "embedded"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +delog = "0.1.0-alpha.3" +heapless-bytes = "0.1.0" +serde = { version = "1.0", default-features = false } #, features = ["derive"] } + diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..cd482d8 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, "submitted" +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions: + +(a) You must give any other recipients of the Work or +Derivative Works a copy of this License; and + +(b) You must cause any modified files to carry prominent notices +stating that You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..1b92736 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2020 SoloKeys + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5dfa2c7 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# cbor-smol + +[github](https://github.com/nickray/cbor-smol) +[docs.rs](https://docs.rs/cbor-smol) +[main](https://nickray.github.io/cbor-smol/cbor-smol/index.html) +[build status](https://github.com/nickray/cbor-smol/actions?query=branch%3Amain) + +#### License + + +Licensed under either of Apache License, Version +2.0 or MIT license at your option. + + +
+ + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this crate by you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. + diff --git a/src/de.rs b/src/de.rs new file mode 100644 index 0000000..f85542f --- /dev/null +++ b/src/de.rs @@ -0,0 +1,1048 @@ +use serde::Deserialize; + +use serde::de::{ + IntoDeserializer, +}; + +use super::error::{Error, Result}; + +/// Deserialize a message of type `T` from a byte slice. The unused portion (if any) +/// of the byte slice is returned for further usage +pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_bytes(s); + let t = T::deserialize(&mut deserializer)?; + Ok(t) +} + +/// Deserialize a message of type `T` from a byte slice. The unused portion (if any) +/// of the byte slice is returned for further usage +pub fn take_from_bytes<'a, T>(s: &'a [u8]) -> Result<(T, &'a [u8])> +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_bytes(s); + let t = T::deserialize(&mut deserializer)?; + Ok((t, deserializer.input)) +} + +//////////////////////////////////////////////////////////////////////////////// + +// TODO: remove these allowances again later +// #![allow(unused_imports)] +// #![allow(unused_variables)] + +use core::convert::TryInto; + +use serde::de::{ + self, + DeserializeSeed, + Visitor, +}; + +/// A structure for deserializing a cbor-smol message. +pub struct Deserializer<'de> { + // This string starts with the input data and characters are truncated off + // the beginning as data is parsed. + pub(crate) input: &'de [u8], +} + +impl<'de> Deserializer<'de> { + /// Obtain a Deserializer from a slice of bytes + pub fn from_bytes(input: &'de [u8]) -> Self { + Deserializer { input } + } +} + +impl<'de> Deserializer<'de> { + fn try_take_n(&mut self, count: usize) -> Result<&'de [u8]> { + if self.input.len() >= count { + let (a, b) = self.input.split_at(count); + self.input = b; + Ok(a) + } else { + Err(Error::DeserializeUnexpectedEnd) + } + } + + fn peek_major(&mut self) -> Result { + if self.input.len() != 0 { + let byte = self.input[0]; + Ok(byte >> 5) + } else { + Err(Error::DeserializeUnexpectedEnd) + } + } + + fn peek(&mut self) -> Result { + if self.input.len() != 0 { + Ok(self.input[0]) + } else { + Err(Error::DeserializeUnexpectedEnd) + } + } + + fn consume(&mut self) -> Result<()> { + if self.input.len() != 0 { + self.input = &self.input[1..]; + Ok(()) + } else { + Err(Error::DeserializeUnexpectedEnd) + } + } + + fn expect_major(&mut self, major: u8) -> Result { + let byte = self.try_take_n(1)?[0]; + if major != (byte >> 5) { + // logging::info_now!("expecting {}, got {} in byte {}", major, byte >> 5, byte).ok(); + // logging::info_now!("remaining data: {:?}", &self.input).ok(); + return Err(Error::DeserializeBadMajor); + } + Ok(byte & ((1 << 5) - 1)) + } + + // TODO: name something like "one-byte-integer" + fn raw_deserialize_u8(&mut self, major: u8) -> Result + { + let additional = self.expect_major(major)?; + + match additional { + byte @ 0..=23 => Ok(byte), + 24 => { + match self.try_take_n(1)?[0] { + 0..=23 => Err(Error::DeserializeNonMinimal), + byte => Ok(byte), + } + }, + _ => Err(Error::DeserializeBadU8), + } + } + + fn raw_deserialize_u16(&mut self, major: u8) -> Result + { + let number = self.raw_deserialize_u32(major)?; + if number <= u16::max_value() as u32 { + Ok(number as u16) + } else { + Err(Error::DeserializeBadU16) + } + } + + fn raw_deserialize_u32(&mut self, major: u8) -> Result + { + let additional = self.expect_major(major)?; + + match additional { + byte @ 0..=23 => Ok(byte as u32), + 24 => { + match self.try_take_n(1)?[0] { + 0..=23 => Err(Error::DeserializeNonMinimal), + byte => Ok(byte as u32), + } + }, + 25 => { + let unsigned = u16::from_be_bytes( + self.try_take_n(2)? + .try_into().map_err(|_| Error::InexistentSliceToArrayError)? + ); + match unsigned { + 0..=255 => Err(Error::DeserializeNonMinimal), + unsigned => Ok(unsigned as u32), + } + }, + 26 => { + let unsigned = u32::from_be_bytes( + self.try_take_n(4)? + .try_into().map_err(|_| Error::InexistentSliceToArrayError)? + ); + match unsigned { + 0..=65535 => Err(Error::DeserializeNonMinimal), + unsigned => Ok(unsigned as u32), + } + }, + _ => Err(Error::DeserializeBadU32), + } + } + + // fn try_take_varint(&mut self) -> Result { + // for i in 0..VarintUsize::varint_usize_max() { + // let val = self.input.get(i).ok_or(Error::DeserializeUnexpectedEnd)?; + // if (val & 0x80) == 0 { + // let (a, b) = self.input.split_at(i + 1); + // self.input = b; + // let mut out = 0usize; + // for byte in a.iter().rev() { + // out <<= 7; + // out |= (byte & 0x7F) as usize; + // } + // return Ok(out); + // } + // } + + // Err(Error::DeserializeBadVarint) + // } +} + +struct SeqAccess<'a, 'b: 'a> { + deserializer: &'a mut Deserializer<'b>, + len: usize, +} + +impl<'a, 'b: 'a> serde::de::SeqAccess<'b> for SeqAccess<'a, 'b> { + type Error = Error; + + fn next_element_seed(&mut self, seed: V) -> Result> + where + V: DeserializeSeed<'b> + { + if self.len > 0 { + self.len -= 1; + Ok(Some(seed.deserialize(&mut *self.deserializer)?)) + } else { + Ok(None) + } + } + + fn size_hint(&self) -> Option { + Some(self.len) + } +} + +struct MapAccess<'a, 'b: 'a> { + deserializer: &'a mut Deserializer<'b>, + len: usize, +} + +impl<'a, 'b: 'a> serde::de::MapAccess<'b> for MapAccess<'a, 'b> { + type Error = Error; + + fn next_key_seed(&mut self, seed: V) -> Result> + where + V: DeserializeSeed<'b> + { + if self.len > 0 { + self.len -= 1; + Ok(Some(seed.deserialize(&mut *self.deserializer)?)) + } else { + Ok(None) + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'b>, + { + seed.deserialize(&mut *self.deserializer) + } + + fn size_hint(&self) -> Option { + Some(self.len) + } +} + +impl<'de, 'a> serde::de::VariantAccess<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + fn unit_variant(self) -> Result<()> { + Ok(()) + } + + fn newtype_variant_seed>(self, seed: V) -> Result { + DeserializeSeed::deserialize(seed, self) + } + + fn tuple_variant>(self, len: usize, visitor: V) -> Result { + serde::de::Deserializer::deserialize_tuple(self, len, visitor) + } + + fn struct_variant>( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result { + serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor) + } +} + +impl<'de, 'a> serde::de::EnumAccess<'de> for &'a mut Deserializer<'de> { + type Error = Error; + type Variant = Self; + + fn variant_seed>(self, seed: V) -> Result<(V::Value, Self)> { + let discriminant = self.raw_deserialize_u32(0)?; + // if discriminant > 0xFFFF_FFFF { + // return Err(Error::DeserializeBadEnum); + // } + let v = DeserializeSeed::deserialize(seed, discriminant.into_deserializer())?; + Ok((v, self)) + } +} + +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { + type Error = Error; + + // cbor-smol does not support structures not known at compile time + fn deserialize_any(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + // We wont ever support this. + // If you need this, use `serde_cbor`. + Err(Error::WontImplement) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let val = match self.try_take_n(1)?[0] { + 0xf4 => false, + 0xf5 => true, + _ => return Err(Error::DeserializeBadBool), + }; + visitor.visit_bool(val) + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek_major()? { + 0 => { + let raw_u8 = self.raw_deserialize_u8(0)?; + if raw_u8 <= i8::max_value() as u8 { + visitor.visit_i8(raw_u8 as i8) + } else { + Err(Error::DeserializeBadI8) + } + }, + 1 => { + let raw_u8 = self.raw_deserialize_u8(1)?; + // if raw_u8 <= 1 + i8::max_value() as u8 { + if raw_u8 <= 128 { + visitor.visit_i8(-1 - (raw_u8 as i16) as i8) + } else { + Err(Error::DeserializeBadI8) + } + }, + _ => Err(Error::DeserializeBadI8), + } + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek_major()? { + 0 => { + let raw = self.raw_deserialize_u16(0)?; + if raw <= i16::max_value() as u16 { + visitor.visit_i16(raw as i16) + } else { + Err(Error::DeserializeBadI16) + } + }, + 1 => { + let raw = self.raw_deserialize_u16(1)?; + if raw <= i16::max_value() as u16 { + visitor.visit_i16(-1 - (raw as i16)) + } else { + Err(Error::DeserializeBadI16) + } + }, + _ => Err(Error::DeserializeBadI16), + } + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek_major()? { + // TODO: figure out if this is BAAAAD for size or speed + major @ 0..=1 => { + let raw = self.raw_deserialize_u32(major)?; + if raw <= i32::max_value() as u32 { + if major == 0 { + visitor.visit_i32(raw as i32) + } else { + visitor.visit_i32(-1 - (raw as i32)) + } + } else { + Err(Error::DeserializeBadI32) + } + }, + _ => Err(Error::DeserializeBadI16), + } + } + + fn deserialize_i64(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::NotYetImplemented) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_deserialize_u8(0)?; + visitor.visit_u8(raw) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_deserialize_u16(0)?; + visitor.visit_u16(raw) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_deserialize_u32(0)?; + visitor.visit_u32(raw) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_deserialize_u32(0)?; + visitor.visit_u64(raw as u64) + } + + fn deserialize_f32(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::NotYetImplemented) + } + + fn deserialize_f64(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + Err(Error::NotYetImplemented) + } + + fn deserialize_char(self, _visitor: V) -> Result + where + V: Visitor<'de>, + { + // not sure, can this be implemented? + // todo!("implement `deserialize_char`"); + Err(Error::NotYetImplemented) + // let mut buf = [0u8; 4]; + // let bytes = self.try_take_n(4)?; + // buf.copy_from_slice(bytes); + // let integer = u32::from_le_bytes(buf); + // visitor.visit_char(core::char::from_u32(integer).ok_or(Error::DeserializeBadChar)?) + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // major type 2: "byte string" + let length = self.raw_deserialize_u32(2)? as usize; + let bytes: &'de [u8] = self.try_take_n(length)?; + visitor.visit_borrowed_bytes(bytes) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_bytes(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // major type 3: "text string" + let length = self.raw_deserialize_u32(3)? as usize; + let bytes: &'de [u8] = self.try_take_n(length)?; + let string_slice = core::str::from_utf8(bytes).map_err(|_| Error::DeserializeBadUtf8)?; + visitor.visit_borrowed_str(string_slice) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self.peek()? { + 0xf6 => { + self.consume()?; + visitor.visit_none() + } + _ => visitor.visit_some(self), + } + } + + // In Serde, unit means an anonymous value containing no data. + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.peek()? { + 0xf6 => { + self.consume()?; + visitor.visit_unit() + } + _ => Err(Error::DeserializeExpectedNull) + } + } + + // Unit struct means a named value containing no data. + fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // major type 4: "array" + let len = self.raw_deserialize_u32(4)? as usize; + + visitor.visit_seq(SeqAccess { + deserializer: self, + len, + }) + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + // major type 4: "array" + let len = self.raw_deserialize_u32(4)? as usize; + visitor.visit_seq(SeqAccess { + deserializer: self, + len, + }) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_tuple(len, visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // major type 5: "map" + let len = self.raw_deserialize_u32(5)? as usize; + + visitor.visit_map(MapAccess { + deserializer: self, + len, + }) + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_map(visitor) + } + + // fn deserialize_enum( + // self, + // _name: &'static str, + // _variants: &'static [&'static str], + // visitor: V, + // ) -> Result + // where + // V: Visitor<'de>, + // { + // todo!("implement `deserialize_enum`"); + // } + + + // fn parse_enum(&mut self, mut len: usize, visitor: V) -> Result + // where + // V: de::Visitor<'de>, + // { + // self.recursion_checked(|de| { + // let value = visitor.visit_enum(VariantAccess { + // seq: SeqAccess { de, len: &mut len }, + // })?; + + // if len != 0 { + // Err(de.error(ErrorCode::TrailingData)) + // } else { + // Ok(value) + // } + // }) + // } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.peek()? { + 0x82 => { + self.consume()?; + visitor.visit_enum(self) + // // self.parse_enum(2, visitor) + // let value = visitor.visit_enum(VariantAccess { + // seq: SeqAccess { self, len: &mut 2 }, + // })?; + + // if len != 0 { + // Err(de.error(ErrorCode::TrailingData)) + // } else { + // Ok(value) + // } + } + // _ => Err(Error::DeserializeBadEnum), + _ => visitor.visit_enum(self), + } + + // Some(byte @ 0x80..=0x9f) => { + // if !self.accept_legacy_enums { + // return Err(self.error(ErrorCode::WrongEnumFormat)); + // } + // self.consume(); + // match byte { + // 0x80..=0x97 => self.parse_enum(byte as usize - 0x80, visitor), + // 0x98 => { + // let len = self.parse_u8()?; + // self.parse_enum(len as usize, visitor) + // } + // 0x99 => { + // let len = self.parse_u16()?; + // self.parse_enum(len as usize, visitor) + // } + // 0x9a => { + // let len = self.parse_u32()?; + // self.parse_enum(len as usize, visitor) + // } + // 0x9b => { + // let len = self.parse_u64()?; + // if len > usize::max_value() as u64 { + // return Err(self.error(ErrorCode::LengthOutOfRange)); + // } + // self.parse_enum(len as usize, visitor) + // } + // _ => Err(Error::DeserializeBadEnum), + // // 0x9c..=0x9e => Err(self.error(ErrorCode::UnassignedCode)), + // // 0x9f => self.parse_indefinite_enum(visitor), + + // // _ => unreachable!(), + // } + // } + // _ => Err(Error::DeserializeBadEnum), + // // Some(0xa1) => { + // // if !self.accept_standard_enums { + // // return Err(self.error(ErrorCode::WrongEnumFormat)); + // // } + // // self.consume(); + // // self.parse_enum_map(visitor) + // // } + // } + // println!("visiting enum"); + // let ret = visitor.visit_enum(self); + // println!("visited enum"); + // ret + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // Ignore extra fields/options + visitor.visit_none() + } +} + +// impl<'de, 'a> serde::de::VariantAccess<'de> for &'a mut Deserializer<'de> { +// type Error = Error; + +// fn unit_variant(self) -> Result<()> { +// Ok(()) +// } + +// fn newtype_variant_seed>(self, seed: V) -> Result { +// DeserializeSeed::deserialize(seed, self) +// } + +// fn tuple_variant>(self, len: usize, visitor: V) -> Result { +// serde::de::Deserializer::deserialize_tuple(self, len, visitor) +// } + +// fn struct_variant>( +// self, +// fields: &'static [&'static str], +// visitor: V, +// ) -> Result { +// serde::de::Deserializer::deserialize_tuple(self, fields.len(), visitor) +// } +// } + +// impl<'de, 'a> serde::de::EnumAccess<'de> for &'a mut Deserializer<'de> { +// type Error = Error; +// type Variant = Self; + +// fn variant_seed>(self, seed: V) -> Result<(V::Value, Self)> { +// // let varint = self.try_take_varint()?; +// // if varint > 0xFFFF_FFFF { +// // return Err(Error::DeserializeBadEnum); +// // } +// let varint = self.raw_deserialize_u32(0)?; +// let v = DeserializeSeed::deserialize(seed, (varint as u32).into_deserializer())?; +// Ok((v, self)) +// } +// } + +// // // `MapAccess` is provided to the `Visitor` to give it the ability to iterate +// // // through entries of the map. +// // impl<'de, 'a> MapAccess<'de> for CommaSeparated<'a, 'de> { +// // type Error = Error; + +// // fn next_key_seed(&mut self, _seed: K) -> Result> +// // where +// // K: DeserializeSeed<'de>, +// // { +// // // // Check if there are no more entries. +// // // if self.de.peek_char()? == '}' { +// // // return Ok(None); +// // // } +// // // // Comma is required before every entry except the first. +// // // if !self.first && self.de.next_char()? != ',' { +// // // return Err(Error::ExpectedMapComma); +// // // } +// // // self.first = false; +// // // // Deserialize a map key. +// // // seed.deserialize(&mut *self.de).map(Some) +// // unimplemented!() +// // } + +// // fn next_value_seed(&mut self, _seed: V) -> Result +// // where +// // V: DeserializeSeed<'de>, +// // { +// // // // It doesn't make a difference whether the colon is parsed at the end +// // // // of `next_key_seed` or at the beginning of `next_value_seed`. In this +// // // // case the code is a bit simpler having it here. +// // // if self.de.next_char()? != ':' { +// // // return Err(Error::ExpectedMapColon); +// // // } +// // // // Deserialize a map value. +// // // seed.deserialize(&mut *self.de) +// // unimplemented!() +// // } +// // } + +#[cfg(test)] +mod tests { + // use super::*; + use super::from_bytes; + + // use crate::serde::{cbor_serialize, cbor_serialize2, cbor_deserialize}; + // use crate::serde::{cbor_serialize, cbor_serialize_old, cbor_deserialize}; + use crate::serde::{cbor_serialize, cbor_deserialize}; + + #[test] + fn de_bool() { + let mut buf = [0u8; 64]; + + for boolean in [true, false].iter() { + let _n = cbor_serialize(boolean, &mut buf).unwrap(); + let de: bool = from_bytes(&buf).unwrap(); + assert_eq!(de, *boolean); + } + } + + #[test] + fn de_u8() { + let mut buf = [0u8; 64]; + + for number in 0..=255 { + println!("testing {}", number); + let _n = cbor_serialize(&number, &mut buf).unwrap(); + let de: u8 = from_bytes(&buf).unwrap(); + assert_eq!(de, number); + } + } + + #[test] + fn de_i8() { + let mut buf = [0u8; 64]; + + for number in -128i8..=127 { + println!("testing {}", number); + let ser = cbor_serialize(&number, &mut buf).unwrap(); + println!("serialized: {:?}", ser); + let de: i8 = cbor_deserialize(ser).unwrap(); + assert_eq!(de, number); + } + } + + + #[test] + fn de_u16() { + let mut buf = [0u8; 64]; + + for number in 0..=65535 { + println!("testing {}", number); + let _n = cbor_serialize(&number, &mut buf).unwrap(); + let de: u16 = from_bytes(&buf).unwrap(); + assert_eq!(de, number); + } + } + + #[test] + fn de_i16() { + let mut buf = [0u8; 64]; + + for number in i16::min_value()..=i16::max_value() { + println!("testing {}", number); + let _n = cbor_serialize(&number, &mut buf).unwrap(); + let de: i16 = from_bytes(&buf).unwrap(); + assert_eq!(de, number); + } + } + + #[test] + fn de_u32() { + let mut buf = [0u8; 64]; + + for number in 0..=3*(u16::max_value() as u32) { + println!("testing {}", number); + let _n = cbor_serialize(&number, &mut buf).unwrap(); + let de: u32 = from_bytes(&buf).unwrap(); + assert_eq!(de, number); + } + + for number in (u32::max_value() - u16::max_value() as u32)..=u32::max_value() { + println!("testing {}", number); + let _n = cbor_serialize(&number, &mut buf).unwrap(); + let de: u32 = from_bytes(&buf).unwrap(); + assert_eq!(de, number); + } + } + + #[test] + fn de_i32() { + let mut buf = [0u8; 64]; + + let number: i32 = -98304; + let ser = cbor_serialize(&number, &mut buf).unwrap(); + println!("serialized number: {:?} of {}", ser, i16::min_value()); + let de: i32 = from_bytes(ser).unwrap(); + assert_eq!(de, number); + + for number in (3*i16::min_value() as i32)..=3*(i16::max_value() as i32) { + println!("testing {}", number); + let ser = cbor_serialize(&number, &mut buf).unwrap(); + let de: i32 = from_bytes(ser).unwrap(); + assert_eq!(de, number); + } + + for number in (i32::max_value() - i16::max_value() as i32)..=i32::max_value() { + println!("testing {}", number); + let ser = cbor_serialize(&number, &mut buf).unwrap(); + let de: i32 = from_bytes(ser).unwrap(); + assert_eq!(de, number); + } + + for number in i32::min_value()..=(i32::min_value() - i16::min_value() as i32) { + println!("testing {}", number); + let ser = cbor_serialize(&number, &mut buf).unwrap(); + let de: i32 = from_bytes(ser).unwrap(); + assert_eq!(de, number); + } + } + + #[test] + fn de_bytes() { + use heapless::consts::U64; + + let mut buf = [0u8; 64]; + + let slice = b"thank you postcard!"; + let bytes = heapless::ByteBuf::::from_slice(slice).unwrap(); + let ser = cbor_serialize(&bytes, &mut buf).unwrap(); + println!("serialized bytes = {:?}", ser); + let de: heapless::ByteBuf:: = from_bytes(&buf).unwrap(); + println!("deserialized bytes = {:?}", &de); + assert_eq!(&de, slice); + } + + #[test] + fn de_str() { + use heapless::consts::U64; + + let mut buf = [0u8; 64]; + + let string_slice = "thank you postcard, for blazing the path 🐝"; + let mut string = heapless::String::::new(); + string.push_str(string_slice).unwrap(); + let _n = cbor_serialize(&string, &mut buf); + let de: heapless::String = from_bytes(&buf).unwrap(); + assert_eq!(de, string_slice); + } + + #[test] + fn de_struct() { + use crate::ctap2::get_info::CtapOptions; + // rk: bool, + // up: bool, + // #[serde(skip_serializing_if = "Option::is_none")] + // uv: Option, + // plat: bool, + // #[serde(skip_serializing_if = "Option::is_none")] + // client_pin: Option, + // #[serde(skip_serializing_if = "Option::is_none")] + // cred_protect: Option, + + let options = CtapOptions { + rk: false, + up: true, + uv: None, + plat: Some(false), + client_pin: Some(true), + }; + + let mut buf = [0u8; 64]; + + let _n = cbor_serialize(&options, &mut buf); + let de: CtapOptions = from_bytes(&buf).unwrap(); + assert_eq!(de, options); + } + + #[test] + fn de_credential_id() { + use heapless::{ByteBuf, consts::{U32, U64}}; + use serde_indexed::{DeserializeIndexed, SerializeIndexed}; + #[derive(Clone,Debug,Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] + pub struct CredentialInner { + pub user_id: ByteBuf, + pub alg: i8, + pub seed: ByteBuf, + } + + let input = b"\xa3\x00Gnickray\x01&\x02X @7\xbf\xa6\x98j\xb9\x0e8nB\x92\xd8\xf2\x1bK\xef\x92\xe87\xfe2`\x92%\xff\x98jR\xd1\xc8\xc1"; + + let _credential_inner: CredentialInner = from_bytes(input).unwrap(); + } + + #[test] + fn de_enum() { + + let mut buf = [0u8; 64]; + let e = Some(3); + let ser = cbor_serialize(&e, &mut buf).unwrap(); + println!("ser(Some(3)) = {:?}", ser); + let de: Option = cbor_deserialize(ser).unwrap(); + assert_eq!(de, e); + let e: Option = None; + println!("ser({:?}) = {:x?}", &e, cbor_serialize(&e, &mut buf).unwrap()); + + // let mut buf = [0u8; 64]; + // let _n = cbor_serialize(&None, &mut buf).unwrap(); + // println!("ser(e) = {:?}", &buf[.._n]); + + // use serde_indexed::{DeserializeIndexed, SerializeIndexed}; + use serde::{Deserialize, Serialize}; + #[derive(Clone,Debug,Eq,PartialEq,Serialize,Deserialize)] + pub enum Enum { + Alpha(u8), + // Beta((i32, u32)), + Beta(i32), + } + + let mut buf = [0u8; 64]; + + // let e = Enum::Beta((-42, 7)); + let e = Enum::Beta(-42); + let ser = cbor_serialize(&e, &mut buf).unwrap(); + println!("ser({:?}) = {:?}", &e, ser); + let de: Enum = cbor_deserialize(ser).unwrap(); + assert_eq!(de, e); + + #[derive(Clone,Debug,Eq,PartialEq,Serialize,Deserialize)] + pub enum SimpleEnum { + // Alpha(u8), + Alpha(u8), + Beta, + } + + let e = SimpleEnum::Alpha(7); + let ser = cbor_serialize(&e, &mut buf).unwrap(); + println!("ser({:?}) = {:?}", &e, ser); + let de: SimpleEnum = cbor_deserialize(ser).unwrap(); + assert_eq!(de, e); + + let e = SimpleEnum::Beta; + let ser = cbor_serialize(&e, &mut buf).unwrap(); + println!("ser({:?}) = {:?}", &e, ser); + let de: SimpleEnum = cbor_deserialize(ser).unwrap(); + assert_eq!(de, e); + } + + #[test] + fn fuzzer_things() { + let data: [u8; 2] = [160, 96]; + type T = crate::webauthn::PublicKeyCredentialUserEntity; + cbor_deserialize::(&data).ok(); + } + + // #[test] + // fn piv_persistent_state() { + // let data = b"\xa6dkeys\xa2rauthentication_keyP<\xc1\xaa\x8c\xc3\xfav4\x88\xbc\xdb\x9fe\x81\xa7nnmanagement_keyP\x8c\x16\"\xed\x0f\xce\x9c\xac^\xf1;\xd0r\xea\xc9\xcbx\x1aconsecutive_pin_mismatches\x00x\x1aconsecutive_puk_mismatches\x00cpin\xa1jpadded_pin\x88\x181\x182\x183\x181\x182\x183\x18\xff\x18\xffcpuk\xa1jpadded_pin\x88\x181\x182\x183\x181\x182\x183\x18\xff\x18\xffitimestamp\x00"; + + // cbor_deserialize::(&data).ok(); + // } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..b9ba875 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,144 @@ +#![allow(unused_variables)] + +use core::fmt::{Display, Formatter}; + +/// This is the Result type used by cbor-smol. +pub type Result = core::result::Result; + +/// This is the error type used by cbor-smol +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(u8)] +pub enum Error { + /// This is a feature that cbor-smol will never implement + WontImplement, + /// This is a feature that cbor-smol intends to support, but does not yet + NotYetImplemented, + /// The serialize buffer is full + SerializeBufferFull(usize), + // /// The length of a sequence must be known + // SerializeSeqLengthUnknown, + /// Hit the end of buffer, expected more data + DeserializeUnexpectedEnd, + // /// Found a varint that didn't terminate. Is the usize too big for this platform? + // DeserializeBadVarint, + /// Found a bool that wasn't 0xf4 or 0xf5 + DeserializeBadBool, + // /// Found an invalid unicode char + // DeserializeBadChar, + /// Tried to parse invalid utf-8 + DeserializeBadUtf8, + // /// Found an Option discriminant that wasn't 0 or 1 + // DeserializeBadOption, + // /// Found an enum discriminant that was > u32::max_value() + /// Could not parse an enum + DeserializeBadEnum, + // /// The original data was not well encoded + // DeserializeBadEncoding, + /// Expected a different major type + DeserializeBadMajor, + /// Expected a i8, was too large + DeserializeBadI8, + /// Expected a i16, was too large + DeserializeBadI16, + /// Expected a i32, was too large + DeserializeBadI32, + /// Expected a u8 + DeserializeBadU8, + /// Expected a u16 + DeserializeBadU16, + /// Expected a u32 + DeserializeBadU32, + /// Expected a NULL marker + DeserializeExpectedNull, + /// Inexistent slice-to-array cast error. Used here to avoid calling unwrap. + InexistentSliceToArrayError, + /// Value may be valid, but not encoded in minimal way + DeserializeNonMinimal, + /// Serde Serialization Error + SerdeSerCustom, + /// Serde Deserialization Error + SerdeDeCustom, + /// Serde Missing required value + SerdeMissingField, +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter) -> core::fmt::Result { + use Error::*; + write!( + f, + "{}", + match self { + WontImplement => "This is a feature that cbor-smol will never implement", + NotYetImplemented => { + "This is a feature that cbor-smol intends to support, but does not yet" + } + SerializeBufferFull(i) => "The serialize buffer is full", + // SerializeSeqLengthUnknown => "The length of a sequence must be known", + DeserializeUnexpectedEnd => "Hit the end of buffer, expected more data", + // DeserializeBadVarint => { + // "Found a varint that didn't terminate. Is the usize too big for this platform?" + // } + DeserializeBadBool => "Found a bool that wasn't 0xf4 or 0xf5", + // DeserializeBadChar => "Found an invalid unicode char", + DeserializeBadUtf8 => "Tried to parse invalid utf-8", + // DeserializeBadOption => "Found an Option discriminant that wasn't 0 or 1", + // DeserializeBadEnum => "Found an enum discriminant that was > u32::max_value()", + DeserializeBadEnum => "Could not parse an enum", + // DeserializeBadEncoding => "The original data was not well encoded", + DeserializeBadI8 => "Expected a i8", + DeserializeBadI16 => "Expected a i16", + DeserializeBadI32 => "Expected a i32", + DeserializeBadMajor => "Expected a different major type", + DeserializeBadU8 => "Expected a u8", + DeserializeBadU16 => "Expected a u16", + DeserializeBadU32 => "Expected a u32", + DeserializeExpectedNull => "Expected 0xf6", + InexistentSliceToArrayError => "", + DeserializeNonMinimal => "Value may be valid, but not encoded in minimal way", + SerdeSerCustom => "Serde Serialization Error", + SerdeDeCustom => "Serde Deserialization Error", + SerdeMissingField => "Serde Missing Required Field" + } + ) + } +} + +impl serde::ser::Error for Error { + fn custom(_msg: T) -> Self + where + T: Display, + { + Error::SerdeSerCustom + } +} + +impl serde::de::Error for Error { + fn custom(msg: T) -> Self + where + T: Display, + { + // TODO: Would be helpful to log this to system logger + // This shows e.g. + // - missing fields + // - expected sequence, received X + // - etc. + // + // Particularly helpful would be better errors when receiving + // structures are undersized. + // + // E.g. if there is a `ByteBuf` and more than N bytes are delivered, + // currently the error _msg: T is: + // + // `invalid length 297, expected a sequence` + // + info_now!("deser error: {}",&msg); + Error::SerdeDeCustom + } + fn missing_field(field: &'static str) -> Self { + info_now!("deser missing: {}", field); + Error::SerdeMissingField + } +} + +impl serde::ser::StdError for Error {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e33f4a4 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,61 @@ +#![cfg_attr(not(test), no_std)] + +#[macro_use] +extern crate delog; +generate_macros!(); + +pub use heapless_bytes::{ArrayLength, Bytes as ByteBuf}; + +pub mod de; +pub mod ser; +pub mod error; + +pub use error::{Error, Result}; + +// pub use de::from_bytes; +// pub use de::take_from_bytes; + +// kudos to postcard, this is much nicer than returning size +pub fn cbor_serialize<'a, 'b, T: serde::Serialize>( + object: &'a T, + buffer: &'b mut [u8], +) -> Result<&'b [u8]> { + let writer = ser::SliceWriter::new(buffer); + let mut ser = ser::Serializer::new(writer); + + object.serialize(&mut ser)?; + + let writer = ser.into_inner(); + let size = writer.bytes_written(); + + Ok(&buffer[..size]) +} + + +pub fn cbor_serialize_bytes<'a, 'b, N: ArrayLength, T: serde::Serialize>( + object: &'a T, + bytes: &'b mut ByteBuf, +) -> Result { + let len_before = bytes.len(); + let mut ser = ser::Serializer::new(bytes); + + object.serialize(&mut ser)?; + + Ok(ser.into_inner().len() - len_before) +} + + +pub fn cbor_serialize_bytebuf, T: serde::Serialize>(object: &T) -> Result> { + let mut data = ByteBuf::::new(); + cbor_serialize_bytes(object, &mut data)?; + Ok(data) +} + + +pub fn cbor_deserialize<'de, T: serde::Deserialize<'de>>( + buffer: &'de [u8], +) -> Result { + // cortex_m_semihosting::hprintln!("deserializing {:?}", buffer).ok(); + de::from_bytes(buffer) +} + diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..d58d224 --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,652 @@ +use serde::Serialize; +use serde::ser; +use super::error::{Error, Result}; + +// pub fn to_slice<'a, 'b, T>(value: &'a T, buf: &'b mut [u8]) -> Result<&'b mut [u8]> +// where +// T: Serialize + ?Sized, +// { +// serialize_with_flavor::, &'a mut [u8]>(value, Slice::new(buf)) +// } + +pub trait Writer { + /// The type of error returned when a write operation fails. + type Error: Into; + + /// Attempts to write an entire buffer into this write. + fn write_all(&mut self, buf: &[u8]) -> core::result::Result<(), Self::Error>; +} + +#[derive(Debug)] +pub struct SliceWriter<'a> { + slice: &'a mut [u8], + index: usize, +} + +impl<'a> SliceWriter<'a> { + /// Wraps a mutable slice so it can be used as a `Writer`. + pub fn new(slice: &'a mut [u8]) -> SliceWriter<'a> { + SliceWriter { slice, index: 0 } + } + + /// Returns the number of bytes written to the underlying slice. + pub fn bytes_written(&self) -> usize { + self.index + } + + /// Returns the underlying slice. + pub fn into_inner(self) -> &'a mut [u8] { + self.slice + } +} + +impl<'a> Writer for SliceWriter<'a> { + type Error = Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + let l = buf.len(); + if self.slice.len() - self.index < l { + // This buffer will not fit in our slice + return Err(Error::SerializeBufferFull(self.index)); + } + self.slice[self.index..][..l].copy_from_slice(buf); + self.index += l; + Ok(()) + } +} + +impl<'a, N> Writer for &'a mut crate::ByteBuf +where + N: crate::ArrayLength, +{ + type Error = Error; + + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf).map_err( + |_| Error::SerializeBufferFull(buf.len())) + } +} + +pub struct Serializer +// where +// W: Writer, +{ + pub writer: W, +} + +impl Serializer { + + #[inline] + pub fn new(writer: W) -> Self { + Serializer { + writer, + // packed: false, + // enum_as_map: true, + } + } + + /// Unwrap the `Writer` from the `Serializer`. + #[inline] + pub fn into_inner(self) -> W { + self.writer + } + + #[inline] + fn write_u8(&mut self, major: u8, value: u8) -> Result<()> { + if value <= 0x17 { + self.writer.write_all(&[major << 5 | value]) + } else { + let buf = [major << 5 | 24, value]; + self.writer.write_all(&buf) + } + .map_err(|e| e.into()) + } + + #[inline] + fn write_u16(&mut self, major: u8, value: u16) -> Result<()> { + if value <= u16::from(u8::max_value()) { + self.write_u8(major, value as u8) + } else { + let mut buf = [major << 5 | 25, 0, 0]; + buf[1..].copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn write_u32(&mut self, major: u8, value: u32) -> Result<()> { + if value <= u32::from(u16::max_value()) { + self.write_u16(major, value as u16) + } else { + let mut buf = [major << 5 | 26, 0, 0, 0, 0]; + buf[1..].copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn write_u64(&mut self, major: u8, value: u64) -> Result<()> { + if value <= u64::from(u32::max_value()) { + self.write_u32(major, value as u32) + } else { + let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0]; + buf[1..].copy_from_slice(&value.to_be_bytes()); + self.writer.write_all(&buf).map_err(|e| e.into()) + } + } + + #[inline] + fn serialize_collection<'a>( + &'a mut self, + major: u8, + len: Option, + ) -> Result> { + let needs_eof = match len { + Some(len) => { + self.write_u64(major, len as u64)?; + false + } + None => { + self.writer + .write_all(&[major << 5 | 31]) + .map_err(|e| e.into())?; + true + } + }; + + Ok(CollectionSerializer { + ser: self, + needs_eof, + }) + } +} + +impl<'a, W> ser::Serializer for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + + type Error = Error; + + // type SerializeSeq = Self; + // type SerializeTuple = Self; + // type SerializeTupleStruct = Self; + // type SerializeTupleVariant = Self; + // type SerializeMap = Self; + // type SerializeStruct = Self; + // type SerializeStructVariant = Self; + + type SerializeSeq = CollectionSerializer<'a, W>; + type SerializeTuple = &'a mut Serializer; + type SerializeTupleStruct = &'a mut Serializer; + type SerializeTupleVariant = &'a mut Serializer; + type SerializeMap = CollectionSerializer<'a, W>; + type SerializeStruct = &'a mut Serializer; + type SerializeStructVariant= &'a mut Serializer; + + + #[inline] + fn serialize_bool(self, value: bool) -> Result<()> { + let value = if value { 0xf5 } else { 0xf4 }; + self.writer.write_all(&[value]).map_err(|e| e.into()) + } + + #[inline] + fn serialize_i8(self, value: i8) -> Result<()> { + let sign = (value >> 7) as u8; + let major_type = sign & 0x1; + let bits = sign ^ (value as u8); + self.write_u8(major_type, bits) + } + + #[inline] + fn serialize_i16(self, value: i16) -> Result<()> { + let sign = (value >> 15) as u16; + let major_type = (sign & 0x1) as u8; + let bits = sign ^ (value as u16); + self.write_u16(major_type, bits) + } + + #[inline] + fn serialize_i32(self, value: i32) -> Result<()> { + let sign = (value >> 31) as u32; + let major_type = (sign & 0x1) as u8; + let bits = sign ^ (value as u32); + self.write_u32(major_type, bits) + } + + #[inline] + fn serialize_i64(self, value: i64) -> Result<()> { + let sign = (value >> 63) as u64; + let major_type = (sign & 0x1) as u8; + let bits = sign ^ (value as u64); + self.write_u64(major_type, bits) + } + + #[inline] + fn serialize_u8(self, value: u8) -> Result<()> { + self.write_u8(0, value) + } + + #[inline] + fn serialize_u16(self, value: u16) -> Result<()> { + self.write_u16(0, value) + } + + #[inline] + fn serialize_u32(self, value: u32) -> Result<()> { + self.write_u32(0, value) + } + + #[inline] + fn serialize_u64(self, value: u64) -> Result<()> { + self.write_u64(0, value) + } + + fn serialize_f32(self, _v: f32) -> Result<()> { + todo!("serialize_f32 not implemented"); + } + + fn serialize_f64(self, _v: f64) -> Result<()> { + todo!("serialize_f64 not implemented"); + } + + #[inline] + fn serialize_char(self, value: char) -> Result<()> { + // A char encoded as UTF-8 takes 4 bytes at most. + let mut buf = [0; 4]; + self.serialize_str(value.encode_utf8(&mut buf)) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result<()> { + self.write_u64(3, value.len() as u64)?; + self.writer + .write_all(value.as_bytes()) + .map_err(|e| e.into()) + } + + #[inline] + fn serialize_bytes(self, value: &[u8]) -> Result<()> { + self.write_u64(2, value.len() as u64)?; + self.writer.write_all(value).map_err(|e| e.into()) + } + + #[inline] + fn serialize_none(self) -> Result<()> { + self.writer.write_all(&[0xf6]).map_err(|e| e.into()) + } + + #[inline] + fn serialize_some(self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(self) + } + + #[inline] + fn serialize_unit(self) -> Result<()> { + self.serialize_none() + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + variant_index: u32, + _variant: &'static str, + ) -> Result<()> { + // if self.packed { + self.serialize_u32(variant_index) + // } else { + // self.serialize_str(variant) + // } + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + // if name == CBOR_NEWTYPE_NAME { + // for tag in get_tag().into_iter() { + // self.write_u64(6, tag)?; + // } + // } + value.serialize(self) + } + + #[inline] + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + // if self.enum_as_map { + // self.write_u64(5, 1u64)?; + // variant.serialize(&mut *self)?; + // } else { + self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; + self.serialize_unit_variant(name, variant_index, variant)?; + // } + value.serialize(self) + } + + #[inline] + fn serialize_seq(self, len: Option) -> Result> { + self.serialize_collection(4, len) + } + + #[inline] + fn serialize_tuple(self, len: usize) -> Result<&'a mut Serializer> { + self.write_u64(4, len as u64)?; + Ok(self) + } + + #[inline] + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<&'a mut Serializer> { + self.serialize_tuple(len) + } + + #[inline] + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<&'a mut Serializer> { + // if self.enum_as_map { + // self.write_u64(5, 1u64)?; + // variant.serialize(&mut *self)?; + // self.serialize_tuple(len) + // } else { + self.write_u64(4, (len + 1) as u64)?; + self.serialize_unit_variant(name, variant_index, variant)?; + Ok(self) + // } + } + + #[inline] + fn serialize_map(self, len: Option) -> Result> { + self.serialize_collection(5, len) + } + + // #[cfg(not(feature = "std"))] + // fn collect_str(self, value: &T) -> Result<()> + // where + // T: core::fmt::Display, + // { + // use crate::write::FmtWrite; + // use core::fmt::Write; + + // let mut w = FmtWrite::new(&mut self.writer); + // write!(w, "{}", value)?; + // Ok(()) + // } + + #[inline] + fn serialize_struct(self, _name: &'static str, len: usize) -> Result { + self.write_u64(5, len as u64)?; + Ok(self) + } + + #[inline] + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + // if self.enum_as_map { + // self.write_u64(5, 1u64)?; + // } else { + self.writer.write_all(&[4 << 5 | 2]).map_err(|e| e.into())?; + // } + self.serialize_unit_variant(name, variant_index, variant)?; + self.serialize_struct(name, len) + } + + fn collect_str(self, _value: &T) -> Result + where + T: core::fmt::Display, + { + unreachable!() + } + + #[inline] + fn is_human_readable(&self) -> bool { + false + } +} + +// impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W> +// where +// W: Writer, +// { +// type Ok = (); +// type Error = Error; + +// #[inline] +// fn serialize_element(&mut self, value: &T) -> Result<()> +// where +// T: ?Sized + ser::Serialize, +// { +// value.serialize(&mut *self.ser) +// } + +// #[inline] +// fn end(self) -> Result<()> { +// self.end_inner() +// } +// } + +impl<'a, W> ser::SerializeTuple for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut **self) + } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeStruct for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + key.serialize(&mut **self)?; + value.serialize(&mut **self)?; + Ok(()) + } + + // #[inline] + // fn skip_field(&mut self, key: &'static str) -> Result<()> { + // Ok(()) + // } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +impl<'a, W> ser::SerializeStructVariant for &'a mut Serializer +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + key.serialize(&mut **self)?; + value.serialize(&mut **self)?; + Ok(()) + } + + // #[inline] + // fn skip_field(&mut self, key: &'static str) -> Result<()> { + // Ok(()) + // } + + #[inline] + fn end(self) -> Result<()> { + Ok(()) + } +} + +#[doc(hidden)] +pub struct CollectionSerializer<'a, W> { + ser: &'a mut Serializer, + needs_eof: bool, +} + +impl<'a, W> CollectionSerializer<'a, W> +where + W: Writer, +{ + #[inline] + fn end_inner(self) -> Result<()> { + if self.needs_eof { + self.ser.writer.write_all(&[0xff]).map_err(|e| e.into()) + } else { + Ok(()) + } + } +} + +impl<'a, W> ser::SerializeSeq for CollectionSerializer<'a, W> +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut *self.ser) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +} + +impl<'a, W> ser::SerializeMap for CollectionSerializer<'a, W> +where + W: Writer, +{ + type Ok = (); + type Error = Error; + + #[inline] + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + key.serialize(&mut *self.ser) + } + + #[inline] + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + value.serialize(&mut *self.ser) + } + + #[inline] + fn end(self) -> Result<()> { + self.end_inner() + } +}