···11+[package]
22+name = "serde_ipld_dagcbor"
33+version = "0.6.4"
44+authors = [
55+ "Pyfisch <pyfisch@posteo.org>",
66+ "Steven Fackler <sfackler@gmail.com>",
77+ "Volker Mische <volker.mische@gmail.com>"
88+]
99+repository = "https://github.com/ipld/serde_ipld_dagcbor"
1010+readme = "README.md"
1111+license = "MIT/Apache-2.0"
1212+description = "IPLD DAG-CBOR support for Serde."
1313+keywords = ["serde", "cbor", "serialization", "no_std"]
1414+categories = ["encoding"]
1515+edition = "2018"
1616+1717+[dependencies]
1818+cbor4ii = { version = "0.2.14", default-features = false, features = ["use_alloc"] }
1919+ipld-core = { version = "0.4.2", default-features = false, features = ["serde"] }
2020+scopeguard = { version = "1.1.0", default-features = false }
2121+serde = { version = "1.0.164", default-features = false, features = ["alloc"] }
2222+2323+[dev-dependencies]
2424+serde_derive = { version = "1.0.164", default-features = false }
2525+serde_bytes = { version = "0.11.9", default-features = false, features = ["alloc"]}
2626+serde-transcode = "1.1.1"
2727+const-hex = "1.14.0"
2828+serde_tuple = "1.1.0"
2929+# We need the RC feature to test a trait edge-case.
3030+serde = { version = "1.0.164", default-features = false, features = ["rc"] }
3131+3232+[features]
3333+default = ["codec", "std"]
3434+std = ["cbor4ii/use_std", "ipld-core/std", "serde/std", "serde_bytes/std"]
3535+# Enable the `Codec` trait implementation. It's a separate feature as it needs Rust >= 1.75.
3636+codec = ["ipld-core/codec"]
3737+# Prevent deserializing CIDs as bytes as much as possible.
3838+no-cid-as-bytes = []
+201
vendor/git/serde_ipld_dagcbor/LICENSE-APACHE
···11+ Apache License
22+ Version 2.0, January 2004
33+ http://www.apache.org/licenses/
44+55+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
66+77+1. Definitions.
88+99+ "License" shall mean the terms and conditions for use, reproduction,
1010+ and distribution as defined by Sections 1 through 9 of this document.
1111+1212+ "Licensor" shall mean the copyright owner or entity authorized by
1313+ the copyright owner that is granting the License.
1414+1515+ "Legal Entity" shall mean the union of the acting entity and all
1616+ other entities that control, are controlled by, or are under common
1717+ control with that entity. For the purposes of this definition,
1818+ "control" means (i) the power, direct or indirect, to cause the
1919+ direction or management of such entity, whether by contract or
2020+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
2121+ outstanding shares, or (iii) beneficial ownership of such entity.
2222+2323+ "You" (or "Your") shall mean an individual or Legal Entity
2424+ exercising permissions granted by this License.
2525+2626+ "Source" form shall mean the preferred form for making modifications,
2727+ including but not limited to software source code, documentation
2828+ source, and configuration files.
2929+3030+ "Object" form shall mean any form resulting from mechanical
3131+ transformation or translation of a Source form, including but
3232+ not limited to compiled object code, generated documentation,
3333+ and conversions to other media types.
3434+3535+ "Work" shall mean the work of authorship, whether in Source or
3636+ Object form, made available under the License, as indicated by a
3737+ copyright notice that is included in or attached to the work
3838+ (an example is provided in the Appendix below).
3939+4040+ "Derivative Works" shall mean any work, whether in Source or Object
4141+ form, that is based on (or derived from) the Work and for which the
4242+ editorial revisions, annotations, elaborations, or other modifications
4343+ represent, as a whole, an original work of authorship. For the purposes
4444+ of this License, Derivative Works shall not include works that remain
4545+ separable from, or merely link (or bind by name) to the interfaces of,
4646+ the Work and Derivative Works thereof.
4747+4848+ "Contribution" shall mean any work of authorship, including
4949+ the original version of the Work and any modifications or additions
5050+ to that Work or Derivative Works thereof, that is intentionally
5151+ submitted to Licensor for inclusion in the Work by the copyright owner
5252+ or by an individual or Legal Entity authorized to submit on behalf of
5353+ the copyright owner. For the purposes of this definition, "submitted"
5454+ means any form of electronic, verbal, or written communication sent
5555+ to the Licensor or its representatives, including but not limited to
5656+ communication on electronic mailing lists, source code control systems,
5757+ and issue tracking systems that are managed by, or on behalf of, the
5858+ Licensor for the purpose of discussing and improving the Work, but
5959+ excluding communication that is conspicuously marked or otherwise
6060+ designated in writing by the copyright owner as "Not a Contribution."
6161+6262+ "Contributor" shall mean Licensor and any individual or Legal Entity
6363+ on behalf of whom a Contribution has been received by Licensor and
6464+ subsequently incorporated within the Work.
6565+6666+2. Grant of Copyright License. Subject to the terms and conditions of
6767+ this License, each Contributor hereby grants to You a perpetual,
6868+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
6969+ copyright license to reproduce, prepare Derivative Works of,
7070+ publicly display, publicly perform, sublicense, and distribute the
7171+ Work and such Derivative Works in Source or Object form.
7272+7373+3. Grant of Patent License. Subject to the terms and conditions of
7474+ this License, each Contributor hereby grants to You a perpetual,
7575+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
7676+ (except as stated in this section) patent license to make, have made,
7777+ use, offer to sell, sell, import, and otherwise transfer the Work,
7878+ where such license applies only to those patent claims licensable
7979+ by such Contributor that are necessarily infringed by their
8080+ Contribution(s) alone or by combination of their Contribution(s)
8181+ with the Work to which such Contribution(s) was submitted. If You
8282+ institute patent litigation against any entity (including a
8383+ cross-claim or counterclaim in a lawsuit) alleging that the Work
8484+ or a Contribution incorporated within the Work constitutes direct
8585+ or contributory patent infringement, then any patent licenses
8686+ granted to You under this License for that Work shall terminate
8787+ as of the date such litigation is filed.
8888+8989+4. Redistribution. You may reproduce and distribute copies of the
9090+ Work or Derivative Works thereof in any medium, with or without
9191+ modifications, and in Source or Object form, provided that You
9292+ meet the following conditions:
9393+9494+ (a) You must give any other recipients of the Work or
9595+ Derivative Works a copy of this License; and
9696+9797+ (b) You must cause any modified files to carry prominent notices
9898+ stating that You changed the files; and
9999+100100+ (c) You must retain, in the Source form of any Derivative Works
101101+ that You distribute, all copyright, patent, trademark, and
102102+ attribution notices from the Source form of the Work,
103103+ excluding those notices that do not pertain to any part of
104104+ the Derivative Works; and
105105+106106+ (d) If the Work includes a "NOTICE" text file as part of its
107107+ distribution, then any Derivative Works that You distribute must
108108+ include a readable copy of the attribution notices contained
109109+ within such NOTICE file, excluding those notices that do not
110110+ pertain to any part of the Derivative Works, in at least one
111111+ of the following places: within a NOTICE text file distributed
112112+ as part of the Derivative Works; within the Source form or
113113+ documentation, if provided along with the Derivative Works; or,
114114+ within a display generated by the Derivative Works, if and
115115+ wherever such third-party notices normally appear. The contents
116116+ of the NOTICE file are for informational purposes only and
117117+ do not modify the License. You may add Your own attribution
118118+ notices within Derivative Works that You distribute, alongside
119119+ or as an addendum to the NOTICE text from the Work, provided
120120+ that such additional attribution notices cannot be construed
121121+ as modifying the License.
122122+123123+ You may add Your own copyright statement to Your modifications and
124124+ may provide additional or different license terms and conditions
125125+ for use, reproduction, or distribution of Your modifications, or
126126+ for any such Derivative Works as a whole, provided Your use,
127127+ reproduction, and distribution of the Work otherwise complies with
128128+ the conditions stated in this License.
129129+130130+5. Submission of Contributions. Unless You explicitly state otherwise,
131131+ any Contribution intentionally submitted for inclusion in the Work
132132+ by You to the Licensor shall be under the terms and conditions of
133133+ this License, without any additional terms or conditions.
134134+ Notwithstanding the above, nothing herein shall supersede or modify
135135+ the terms of any separate license agreement you may have executed
136136+ with Licensor regarding such Contributions.
137137+138138+6. Trademarks. This License does not grant permission to use the trade
139139+ names, trademarks, service marks, or product names of the Licensor,
140140+ except as required for reasonable and customary use in describing the
141141+ origin of the Work and reproducing the content of the NOTICE file.
142142+143143+7. Disclaimer of Warranty. Unless required by applicable law or
144144+ agreed to in writing, Licensor provides the Work (and each
145145+ Contributor provides its Contributions) on an "AS IS" BASIS,
146146+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147147+ implied, including, without limitation, any warranties or conditions
148148+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149149+ PARTICULAR PURPOSE. You are solely responsible for determining the
150150+ appropriateness of using or redistributing the Work and assume any
151151+ risks associated with Your exercise of permissions under this License.
152152+153153+8. Limitation of Liability. In no event and under no legal theory,
154154+ whether in tort (including negligence), contract, or otherwise,
155155+ unless required by applicable law (such as deliberate and grossly
156156+ negligent acts) or agreed to in writing, shall any Contributor be
157157+ liable to You for damages, including any direct, indirect, special,
158158+ incidental, or consequential damages of any character arising as a
159159+ result of this License or out of the use or inability to use the
160160+ Work (including but not limited to damages for loss of goodwill,
161161+ work stoppage, computer failure or malfunction, or any and all
162162+ other commercial damages or losses), even if such Contributor
163163+ has been advised of the possibility of such damages.
164164+165165+9. Accepting Warranty or Additional Liability. While redistributing
166166+ the Work or Derivative Works thereof, You may choose to offer,
167167+ and charge a fee for, acceptance of support, warranty, indemnity,
168168+ or other liability obligations and/or rights consistent with this
169169+ License. However, in accepting such obligations, You may act only
170170+ on Your own behalf and on Your sole responsibility, not on behalf
171171+ of any other Contributor, and only if You agree to indemnify,
172172+ defend, and hold each Contributor harmless for any liability
173173+ incurred by, or claims asserted against, such Contributor by reason
174174+ of your accepting any such warranty or additional liability.
175175+176176+END OF TERMS AND CONDITIONS
177177+178178+APPENDIX: How to apply the Apache License to your work.
179179+180180+ To apply the Apache License to your work, attach the following
181181+ boilerplate notice, with the fields enclosed by brackets "[]"
182182+ replaced with your own identifying information. (Don't include
183183+ the brackets!) The text should be enclosed in the appropriate
184184+ comment syntax for the file format. We also recommend that a
185185+ file or class name and description of purpose be included on the
186186+ same "printed page" as the copyright notice for easier
187187+ identification within third-party archives.
188188+189189+Copyright [yyyy] [name of copyright owner]
190190+191191+Licensed under the Apache License, Version 2.0 (the "License");
192192+you may not use this file except in compliance with the License.
193193+You may obtain a copy of the License at
194194+195195+ http://www.apache.org/licenses/LICENSE-2.0
196196+197197+Unless required by applicable law or agreed to in writing, software
198198+distributed under the License is distributed on an "AS IS" BASIS,
199199+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200200+See the License for the specific language governing permissions and
201201+limitations under the License.
+19
vendor/git/serde_ipld_dagcbor/LICENSE-MIT
···11+Copyright (c) 2015 Pyfisch
22+33+Permission is hereby granted, free of charge, to any person obtaining a copy
44+of this software and associated documentation files (the "Software"), to deal
55+in the Software without restriction, including without limitation the rights
66+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
77+copies of the Software, and to permit persons to whom the Software is
88+furnished to do so, subject to the following conditions:
99+1010+The above copyright notice and this permission notice shall be included in
1111+all copies or substantial portions of the Software.
1212+1313+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1414+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1515+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1616+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1717+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1919+THE SOFTWARE.
+93
vendor/git/serde_ipld_dagcbor/README.md
···11+Serde IPLD DAG-CBOR
22+===================
33+44+[](https://crates.io/crates/serde_ipld_dagcbor)
55+[](https://docs.rs/serde_ipld_dagcbor)
66+77+This is a [Serde] implementation for [DAG-CBOR]. It can be use in conjunction with [ipld-core].
88+99+The underlying library for CBOR encoding/decoding is [cbor4ii]. Their Serde implementation is used as a basis. A copy of their code was copied into this repo on April 2022 and is used under the MIT/Apache-2.0 license, with permission from [@quininer].
1010+1111+This crate started as a fork of [serde_cbor], thanks everyone involved there.
1212+1313+[Serde]: https://github.com/serde-rs/serde
1414+[DAG-CBOR]: https://ipld.io/specs/codecs/dag-cbor/spec/
1515+[ipld-core]: https://github.com/ipld/rust-ipld-core
1616+[cbor4ii]: https://github.com/quininer/cbor4ii
1717+[@quininer]: https://github.com/quininer/
1818+[serde_cbor]: https://github.com/pyfisch/cbor
1919+2020+2121+Usage
2222+-----
2323+2424+Storing and loading Rust types is easy and requires only
2525+minimal modifications to the program code.
2626+2727+```rust
2828+use serde_derive::{Deserialize, Serialize};
2929+use std::error::Error;
3030+use std::fs::File;
3131+use std::io::BufReader;
3232+3333+// Types annotated with `Serialize` can be stored as DAG-CBOR.
3434+// To be able to load them again add `Deserialize`.
3535+#[derive(Debug, Serialize, Deserialize)]
3636+struct Mascot {
3737+ name: String,
3838+ species: String,
3939+ year_of_birth: u32,
4040+}
4141+4242+fn main() -> Result<(), Box<dyn Error>> {
4343+ let ferris = Mascot {
4444+ name: "Ferris".to_owned(),
4545+ species: "crab".to_owned(),
4646+ year_of_birth: 2015,
4747+ };
4848+4949+ let ferris_file = File::create("examples/ferris.cbor")?;
5050+ // Write Ferris to the given file.
5151+ // Instead of a file you can use any type that implements `io::Write`
5252+ // like a HTTP body, database connection etc.
5353+ serde_ipld_dagcbor::to_writer(ferris_file, &ferris)?;
5454+5555+ let tux_file = File::open("examples/tux.cbor")?;
5656+ let tux_reader = BufReader::new(tux_file);
5757+ // Load Tux from a file.
5858+ // Serde IPLD DAG-CBOR performs roundtrip serialization meaning that
5959+ // the data will not change in any way.
6060+ let tux: Mascot = serde_ipld_dagcbor::from_reader(tux_reader)?;
6161+6262+ println!("{:?}", tux);
6363+ // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
6464+6565+ Ok(())
6666+}
6767+```
6868+6969+7070+Features
7171+--------
7272+7373+### `codec`
7474+7575+The `codec` feature is enabled by default, it provides the `Codec` trait, which enables encoding and decoding independent of the IPLD Codec. The minimum supported Rust version (MSRV) can significantly be reduced to 1.64 by disabling this feature.
7676+7777+7878+### `no-cid-as-bytes`
7979+8080+Sometimes it is desired that a CID is not accidentally deserialized into bytes. This can happen because the intermediate serde data model does not retain enough information to be able to differentiate between a bytes container and a CID container when there is a conflicting choice to be made, as in the case of some enum cases. The `no-cid-as-bytes` feature can be enabled in order to error at runtime in such cases.
8181+8282+The problem with that feature is, that it breaks Serde's derive attributes for [internally tagged enums](https://serde.rs/enum-representations.html#internally-tagged) (`#[serde(tag = "sometag")]`) and [untagged enums](https://serde.rs/enum-representations.html#untagged) (`#serde(untagged)`). If this feature is enabled and you still need similar functionality, you could implement a deserializer manually. Examples of how to do that are in the [enum example](examples/enums.rs).
8383+8484+8585+License
8686+-------
8787+8888+Licensed under either of
8989+9090+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
9191+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
9292+9393+at your option.
+137
vendor/git/serde_ipld_dagcbor/examples/enums.rs
···11+/// Serde untagged (`#[serde(untagged)]`) and internaly tagged enums (`#[serde(tag = "tag")]`) are
22+/// not supported by CIDs. Here examples are provided on how to implement similar behaviour. This
33+/// file also contains an example for a kinded enum.
44+use std::convert::{TryFrom, TryInto};
55+66+use ipld_core::{cid::Cid, ipld::Ipld};
77+use serde::{de, Deserialize};
88+use serde_bytes::ByteBuf;
99+use serde_ipld_dagcbor::from_slice;
1010+1111+/// The CID `bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy` encoded as CBOR
1212+/// 42(h'00015512202C26B46B68FFC68FF99B453C1D30413413422D706483BFA0F98A5E886266E7AE')
1313+const CBOR_CID_FIXTURE: [u8; 41] = [
1414+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff, 0xc6,
1515+ 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64, 0x83, 0xbf,
1616+ 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
1717+];
1818+1919+/// This enum shows how an internally tagged enum could be implemented.
2020+#[derive(Debug, PartialEq)]
2121+enum CidInInternallyTaggedEnum {
2222+ MyCid { cid: Cid },
2323+}
2424+2525+// This manual deserializer implementation works as if you would derive `Deserialize` and add
2626+// `#[serde(tag = "type")]` to the `CidInternallyTaggedEnum` enum.
2727+impl<'de> de::Deserialize<'de> for CidInInternallyTaggedEnum {
2828+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2929+ where
3030+ D: de::Deserializer<'de>,
3131+ {
3232+ #[derive(Deserialize)]
3333+ struct Tagged {
3434+ r#type: String,
3535+ cid: Cid,
3636+ }
3737+3838+ let Tagged { r#type, cid } = Deserialize::deserialize(deserializer)?;
3939+ if r#type == "MyCid" {
4040+ Ok(CidInInternallyTaggedEnum::MyCid { cid })
4141+ } else {
4242+ Err(de::Error::custom("No matching enum variant found"))
4343+ }
4444+ }
4545+}
4646+4747+/// This enum shows how an untagged enum could be implemented.
4848+#[derive(Debug, PartialEq)]
4949+enum CidInUntaggedEnum {
5050+ MyCid(Cid),
5151+}
5252+5353+// This manual deserializer implementation works as if you would derive `Deserialize` and add
5454+// `#[serde(untagged)]`.
5555+impl<'de> de::Deserialize<'de> for CidInUntaggedEnum {
5656+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
5757+ where
5858+ D: de::Deserializer<'de>,
5959+ {
6060+ Cid::deserialize(deserializer)
6161+ .map(CidInUntaggedEnum::MyCid)
6262+ .map_err(|_| de::Error::custom("No matching enum variant found"))
6363+ }
6464+}
6565+6666+/// This enum shows how a kinded enum could be implemented.
6767+#[derive(Debug, PartialEq)]
6868+pub enum Kinded {
6969+ Bytes(ByteBuf),
7070+ Link(Cid),
7171+}
7272+7373+impl TryFrom<Ipld> for Kinded {
7474+ type Error = ();
7575+7676+ fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
7777+ match ipld {
7878+ Ipld::Bytes(bytes) => Ok(Self::Bytes(ByteBuf::from(bytes))),
7979+ Ipld::Link(cid) => Ok(Self::Link(cid)),
8080+ _ => Err(()),
8181+ }
8282+ }
8383+}
8484+8585+impl<'de> de::Deserialize<'de> for Kinded {
8686+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
8787+ where
8888+ D: de::Deserializer<'de>,
8989+ {
9090+ Ipld::deserialize(deserializer).and_then(|ipld| {
9191+ ipld.try_into()
9292+ .map_err(|_| de::Error::custom("No matching enum variant found"))
9393+ })
9494+ }
9595+}
9696+9797+pub fn main() {
9898+ let cid: Cid = from_slice(&CBOR_CID_FIXTURE).unwrap();
9999+100100+ // {"type": "MyCid", "cid": 42(h'00015512202C26B46B68FFC68FF99B453C1D30413413422D706483BFA0F98A5E886266E7AE')}
101101+ let cbor_internally_tagged_enum = [
102102+ &[
103103+ 0xa2, 0x64, 0x74, 0x79, 0x70, 0x65, 0x65, 0x4d, 0x79, 0x43, 0x69, 0x64, 0x63, 0x63,
104104+ 0x69, 0x64,
105105+ ],
106106+ &CBOR_CID_FIXTURE[..],
107107+ ]
108108+ .concat();
109109+ assert_eq!(
110110+ from_slice::<CidInInternallyTaggedEnum>(&cbor_internally_tagged_enum).unwrap(),
111111+ CidInInternallyTaggedEnum::MyCid { cid }
112112+ );
113113+114114+ assert_eq!(
115115+ from_slice::<CidInUntaggedEnum>(&CBOR_CID_FIXTURE).unwrap(),
116116+ CidInUntaggedEnum::MyCid(cid)
117117+ );
118118+119119+ assert_eq!(
120120+ from_slice::<Kinded>(&CBOR_CID_FIXTURE).unwrap(),
121121+ Kinded::Link(cid)
122122+ );
123123+124124+ // The CID without the tag 42 prefix, so that it decodes as just bytes.
125125+ let cbor_bytes = &CBOR_CID_FIXTURE[2..];
126126+ let decoded_bytes: Kinded = from_slice(cbor_bytes).unwrap();
127127+ // The CBOR decoded bytes don't contain the prefix with the bytes type identifier and the
128128+ // length.
129129+ let bytes = cbor_bytes[2..].to_vec();
130130+ assert_eq!(decoded_bytes, Kinded::Bytes(ByteBuf::from(bytes)));
131131+}
132132+133133+// Make it possible to run this example as test.
134134+#[test]
135135+fn test_main() {
136136+ main()
137137+}
+50
vendor/git/serde_ipld_dagcbor/examples/readme.rs
···11+// NOTE: This file should be kept in sync with README.md
22+33+#[cfg(feature = "std")]
44+use serde_derive::{Deserialize, Serialize};
55+#[cfg(feature = "std")]
66+use std::error::Error;
77+#[cfg(feature = "std")]
88+use std::fs::File;
99+#[cfg(feature = "std")]
1010+use std::io::BufReader;
1111+1212+// Types annotated with `Serialize` can be stored as DAG-CBOR.
1313+// To be able to load them again add `Deserialize`.
1414+#[cfg(feature = "std")]
1515+#[derive(Debug, Serialize, Deserialize)]
1616+struct Mascot {
1717+ name: String,
1818+ species: String,
1919+ year_of_birth: u32,
2020+}
2121+2222+#[cfg(feature = "std")]
2323+fn main() -> Result<(), Box<dyn Error>> {
2424+ let ferris = Mascot {
2525+ name: "Ferris".to_owned(),
2626+ species: "crab".to_owned(),
2727+ year_of_birth: 2015,
2828+ };
2929+3030+ let ferris_file = File::create("examples/ferris.cbor")?;
3131+ // Write Ferris to the given file.
3232+ // Instead of a file you can use any type that implements `io::Write`
3333+ // like a HTTP body, database connection etc.
3434+ serde_ipld_dagcbor::to_writer(ferris_file, &ferris)?;
3535+3636+ let tux_file = File::open("examples/tux.cbor")?;
3737+ let tux_reader = BufReader::new(tux_file);
3838+ // Load Tux from a file.
3939+ // Serde IPLD DAG-CBOR performs roundtrip serialization meaning that
4040+ // the data will not change in any way.
4141+ let tux: Mascot = serde_ipld_dagcbor::from_reader(tux_reader)?;
4242+4343+ println!("{:?}", tux);
4444+ // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
4545+4646+ Ok(())
4747+}
4848+4949+#[cfg(not(feature = "std"))]
5050+fn main() {}
···11+//! DAG-CBOR serialization and deserialization.
22+//!
33+//! # Usage
44+//!
55+//! Add this to your `Cargo.toml`:
66+//! ```toml
77+//! [dependencies]
88+//! serde_ipld_dagcbor = "0.1.0"
99+//! ```
1010+//!
1111+//! Storing and loading Rust types is easy and requires only
1212+//! minimal modifications to the program code.
1313+//!
1414+//! ```rust
1515+//! # #[cfg(not(feature = "std"))]
1616+//! # fn main() {}
1717+//! use serde_derive::{Deserialize, Serialize};
1818+//! use std::error::Error;
1919+//! use std::fs::File;
2020+//! use std::io::BufReader;
2121+//!
2222+//! // Types annotated with `Serialize` can be stored as CBOR.
2323+//! // To be able to load them again add `Deserialize`.
2424+//! #[derive(Debug, Serialize, Deserialize)]
2525+//! struct Mascot {
2626+//! name: String,
2727+//! species: String,
2828+//! year_of_birth: u32,
2929+//! }
3030+//!
3131+//! # #[cfg(feature = "std")]
3232+//! fn main() -> Result<(), Box<dyn Error>> {
3333+//! let ferris = Mascot {
3434+//! name: "Ferris".to_owned(),
3535+//! species: "crab".to_owned(),
3636+//! year_of_birth: 2015,
3737+//! };
3838+//!
3939+//! let ferris_file = File::create("examples/ferris.cbor")?;
4040+//! // Write Ferris to the given file.
4141+//! // Instead of a file you can use any type that implements `io::Write`
4242+//! // like a HTTP body, database connection etc.
4343+//! serde_ipld_dagcbor::to_writer(ferris_file, &ferris)?;
4444+//!
4545+//! let tux_file = File::open("examples/tux.cbor")?;
4646+//! let tux_reader = BufReader::new(tux_file);
4747+//! // Load Tux from a file.
4848+//! // Serde CBOR performs roundtrip serialization meaning that
4949+//! // the data will not change in any way.
5050+//! let tux: Mascot = serde_ipld_dagcbor::from_reader(tux_reader)?;
5151+//!
5252+//! println!("{:?}", tux);
5353+//! // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
5454+//!
5555+//! Ok(())
5656+//! }
5757+//! ```
5858+//!
5959+//! There are a lot of options available to customize the format.
6060+//! To operate on untyped DAG-CBOR values have a look at the [`ipld_core::ipld::Ipld`] type.
6161+//!
6262+//! # Type-based Serialization and Deserialization
6363+//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
6464+//! from CBOR via the serialization API. To be able to serialize a piece of data, it must implement
6565+//! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
6666+//! `serde::Deserialize` trait. Serde provides an annotation to automatically generate the
6767+//! code for these traits: `#[derive(Serialize, Deserialize)]`.
6868+//!
6969+//! Read a general CBOR value with an unknown content.
7070+//!
7171+//! ```rust
7272+//! use serde_ipld_dagcbor::from_slice;
7373+//! use ipld_core::ipld::Ipld;
7474+//!
7575+//! let slice = b"\x82\x01\xa1aaab";
7676+//! let value: Ipld = from_slice(slice).unwrap();
7777+//! println!("{:?}", value); // List([Integer(1), Map({"a": String("b")})])
7878+//! ```
7979+//!
8080+//! Serialize an object.
8181+//!
8282+//! ```rust
8383+//! use std::collections::BTreeMap;
8484+//! use serde_ipld_dagcbor::to_vec;
8585+//!
8686+//! let mut programming_languages = BTreeMap::new();
8787+//! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]);
8888+//! programming_languages.insert("python", vec!["powerful", "friendly", "open"]);
8989+//! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]);
9090+//! let encoded = to_vec(&programming_languages);
9191+//! assert_eq!(encoded.unwrap().len(), 103);
9292+//! ```
9393+//!
9494+//! # `no-std` support
9595+//!
9696+//! Serde CBOR supports building in a `no_std` context, use the following lines
9797+//! in your `Cargo.toml` dependencies:
9898+//! ``` toml
9999+//! [dependencies]
100100+//! serde = { version = "1.0", default-features = false }
101101+//! serde_ipld_dagcbor = { version = "0.1.0", default-features = false }
102102+//! ```
103103+//!
104104+//! Without the `std` feature the functions [from_reader], and [to_writer] are not exported.
105105+//!
106106+//! *Note*: to use derive macros in serde you will need to declare `serde`
107107+//! dependency like so:
108108+//! ``` toml
109109+//! serde = { version = "1.0", default-features = false, features = ["derive"] }
110110+//! ```
111111+112112+#![deny(missing_docs)]
113113+#![cfg_attr(not(feature = "std"), no_std)]
114114+115115+extern crate alloc;
116116+117117+mod cbor4ii_nonpub;
118118+// The `Codec` implementation is only available if the `no-cid-as-bytes` feature is disabled, due
119119+// to the links being extracted with a Serde based approach.
120120+#[cfg(all(feature = "std", not(feature = "no-cid-as-bytes"), feature = "codec"))]
121121+pub mod codec;
122122+pub mod de;
123123+pub mod error;
124124+pub mod ser;
125125+126126+#[doc(inline)]
127127+pub use crate::error::{DecodeError, EncodeError};
128128+129129+// Convenience functions for serialization and deserialization.
130130+#[doc(inline)]
131131+pub use crate::de::from_slice;
132132+133133+#[cfg(feature = "std")]
134134+#[doc(inline)]
135135+pub use crate::de::from_reader;
136136+137137+#[doc(inline)]
138138+pub use crate::ser::to_vec;
139139+140140+#[cfg(feature = "std")]
141141+#[doc(inline)]
142142+pub use crate::ser::to_writer;
143143+144144+/// The multicodec code for DAG-CBOR.
145145+pub const DAG_CBOR_CODE: u64 = 0x71;
146146+147147+/// The CBOR tag that is used for CIDs.
148148+const CBOR_TAGS_CID: u64 = 42;
+699
vendor/git/serde_ipld_dagcbor/src/ser.rs
···11+//! Serialization.
22+#[cfg(not(feature = "std"))]
33+use alloc::{collections::TryReserveError, string::ToString, vec::Vec};
44+#[cfg(feature = "std")]
55+use std::collections::TryReserveError;
66+77+pub use cbor4ii::core::utils::BufWriter;
88+#[cfg(feature = "std")]
99+use cbor4ii::core::utils::IoWriter;
1010+use cbor4ii::core::{
1111+ enc::{self, Encode},
1212+ types,
1313+};
1414+use ipld_core::cid::serde::CID_SERDE_PRIVATE_IDENTIFIER;
1515+use serde::{ser, Serialize};
1616+1717+use crate::error::EncodeError;
1818+use crate::CBOR_TAGS_CID;
1919+2020+/// Serializes a value to a vector.
2121+pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, EncodeError<TryReserveError>>
2222+where
2323+ T: Serialize + ?Sized,
2424+{
2525+ let writer = BufWriter::new(Vec::new());
2626+ let mut serializer = Serializer::new(writer);
2727+ value.serialize(&mut serializer)?;
2828+ Ok(serializer.into_inner().into_inner())
2929+}
3030+3131+/// Serializes a value to a writer.
3232+#[cfg(feature = "std")]
3333+pub fn to_writer<W, T>(writer: W, value: &T) -> Result<(), EncodeError<std::io::Error>>
3434+where
3535+ W: std::io::Write,
3636+ T: Serialize,
3737+{
3838+ let mut serializer = Serializer::new(IoWriter::new(writer));
3939+ value.serialize(&mut serializer)
4040+}
4141+4242+/// A structure for serializing Rust values to DAG-CBOR.
4343+pub struct Serializer<W> {
4444+ writer: W,
4545+}
4646+4747+impl<W> Serializer<W> {
4848+ /// Creates a new CBOR serializer.
4949+ pub fn new(writer: W) -> Serializer<W> {
5050+ Serializer { writer }
5151+ }
5252+5353+ /// Returns the underlying writer.
5454+ pub fn into_inner(self) -> W {
5555+ self.writer
5656+ }
5757+}
5858+5959+impl<'a, W: enc::Write> serde::Serializer for &'a mut Serializer<W> {
6060+ type Ok = ();
6161+ type Error = EncodeError<W::Error>;
6262+6363+ type SerializeSeq = CollectSeq<'a, W>;
6464+ type SerializeTuple = BoundedCollect<'a, W>;
6565+ type SerializeTupleStruct = BoundedCollect<'a, W>;
6666+ type SerializeTupleVariant = BoundedCollect<'a, W>;
6767+ type SerializeMap = CollectMap<'a, W>;
6868+ type SerializeStruct = CollectMap<'a, W>;
6969+ type SerializeStructVariant = CollectMap<'a, W>;
7070+7171+ #[inline]
7272+ fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
7373+ v.encode(&mut self.writer)?;
7474+ Ok(())
7575+ }
7676+7777+ #[inline]
7878+ fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
7979+ v.encode(&mut self.writer)?;
8080+ Ok(())
8181+ }
8282+8383+ #[inline]
8484+ fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
8585+ v.encode(&mut self.writer)?;
8686+ Ok(())
8787+ }
8888+8989+ #[inline]
9090+ fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
9191+ v.encode(&mut self.writer)?;
9292+ Ok(())
9393+ }
9494+9595+ #[inline]
9696+ fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
9797+ v.encode(&mut self.writer)?;
9898+ Ok(())
9999+ }
100100+101101+ #[inline]
102102+ fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
103103+ v.encode(&mut self.writer)?;
104104+ Ok(())
105105+ }
106106+107107+ #[inline]
108108+ fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
109109+ v.encode(&mut self.writer)?;
110110+ Ok(())
111111+ }
112112+113113+ #[inline]
114114+ fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
115115+ v.encode(&mut self.writer)?;
116116+ Ok(())
117117+ }
118118+119119+ #[inline]
120120+ fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
121121+ v.encode(&mut self.writer)?;
122122+ Ok(())
123123+ }
124124+125125+ #[inline]
126126+ fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
127127+ // In DAG-CBOR floats are always encoded as f64.
128128+ self.serialize_f64(f64::from(v))
129129+ }
130130+131131+ #[inline]
132132+ fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
133133+ // In DAG-CBOR only finite floats are supported.
134134+ if !v.is_finite() {
135135+ Err(EncodeError::Msg(
136136+ "Float must be a finite number, not Infinity or NaN".into(),
137137+ ))
138138+ } else {
139139+ v.encode(&mut self.writer)?;
140140+ Ok(())
141141+ }
142142+ }
143143+144144+ #[inline]
145145+ fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
146146+ let mut buf = [0; 4];
147147+ self.serialize_str(v.encode_utf8(&mut buf))
148148+ }
149149+150150+ #[inline]
151151+ fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
152152+ v.encode(&mut self.writer)?;
153153+ Ok(())
154154+ }
155155+156156+ #[inline]
157157+ fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
158158+ types::Bytes(v).encode(&mut self.writer)?;
159159+ Ok(())
160160+ }
161161+162162+ #[inline]
163163+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
164164+ types::Null.encode(&mut self.writer)?;
165165+ Ok(())
166166+ }
167167+168168+ #[inline]
169169+ fn serialize_some<T: Serialize + ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> {
170170+ value.serialize(self)
171171+ }
172172+173173+ #[inline]
174174+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
175175+ // The cbor4ii Serde implementation encodes unit as an empty array, for DAG-CBOR we encode
176176+ // it as `NULL`.
177177+ types::Null.encode(&mut self.writer)?;
178178+ Ok(())
179179+ }
180180+181181+ #[inline]
182182+ fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
183183+ self.serialize_unit()
184184+ }
185185+186186+ #[inline]
187187+ fn serialize_unit_variant(
188188+ self,
189189+ _name: &'static str,
190190+ _variant_index: u32,
191191+ variant: &'static str,
192192+ ) -> Result<Self::Ok, Self::Error> {
193193+ self.serialize_str(variant)
194194+ }
195195+196196+ #[inline]
197197+ fn serialize_newtype_struct<T: Serialize + ?Sized>(
198198+ self,
199199+ name: &'static str,
200200+ value: &T,
201201+ ) -> Result<Self::Ok, Self::Error> {
202202+ if name == CID_SERDE_PRIVATE_IDENTIFIER {
203203+ value.serialize(&mut CidSerializer(self))
204204+ } else {
205205+ value.serialize(self)
206206+ }
207207+ }
208208+209209+ #[inline]
210210+ fn serialize_newtype_variant<T: Serialize + ?Sized>(
211211+ self,
212212+ _name: &'static str,
213213+ _variant_index: u32,
214214+ variant: &'static str,
215215+ value: &T,
216216+ ) -> Result<Self::Ok, Self::Error> {
217217+ enc::MapStartBounded(1).encode(&mut self.writer)?;
218218+ variant.encode(&mut self.writer)?;
219219+ value.serialize(self)
220220+ }
221221+222222+ #[inline]
223223+ fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
224224+ CollectSeq::new(self, len)
225225+ }
226226+227227+ #[inline]
228228+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
229229+ enc::ArrayStartBounded(len).encode(&mut self.writer)?;
230230+ Ok(BoundedCollect { ser: self })
231231+ }
232232+233233+ #[inline]
234234+ fn serialize_tuple_struct(
235235+ self,
236236+ _name: &'static str,
237237+ len: usize,
238238+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
239239+ self.serialize_tuple(len)
240240+ }
241241+242242+ #[inline]
243243+ fn serialize_tuple_variant(
244244+ self,
245245+ _name: &'static str,
246246+ _variant_index: u32,
247247+ variant: &'static str,
248248+ len: usize,
249249+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
250250+ enc::MapStartBounded(1).encode(&mut self.writer)?;
251251+ variant.encode(&mut self.writer)?;
252252+ enc::ArrayStartBounded(len).encode(&mut self.writer)?;
253253+ Ok(BoundedCollect { ser: self })
254254+ }
255255+256256+ #[inline]
257257+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
258258+ Ok(CollectMap::new(self))
259259+ }
260260+261261+ #[inline]
262262+ fn serialize_struct(
263263+ self,
264264+ _name: &'static str,
265265+ len: usize,
266266+ ) -> Result<Self::SerializeStruct, Self::Error> {
267267+ enc::MapStartBounded(len).encode(&mut self.writer)?;
268268+ Ok(CollectMap::new(self))
269269+ }
270270+271271+ #[inline]
272272+ fn serialize_struct_variant(
273273+ self,
274274+ _name: &'static str,
275275+ _variant_index: u32,
276276+ variant: &'static str,
277277+ len: usize,
278278+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
279279+ enc::MapStartBounded(1).encode(&mut self.writer)?;
280280+ variant.encode(&mut self.writer)?;
281281+ enc::MapStartBounded(len).encode(&mut self.writer)?;
282282+ Ok(CollectMap::new(self))
283283+ }
284284+285285+ #[inline]
286286+ fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
287287+ if !(u64::MAX as i128 >= v && -(u64::MAX as i128 + 1) <= v) {
288288+ return Err(EncodeError::Msg(
289289+ "Integer must be within [-u64::MAX-1, u64::MAX] range".into(),
290290+ ));
291291+ }
292292+293293+ v.encode(&mut self.writer)?;
294294+ Ok(())
295295+ }
296296+297297+ #[inline]
298298+ fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
299299+ if (u64::MAX as u128) < v {
300300+ return Err(EncodeError::Msg(
301301+ "Unsigned integer must be within [0, u64::MAX] range".into(),
302302+ ));
303303+ }
304304+ v.encode(&mut self.writer)?;
305305+ Ok(())
306306+ }
307307+308308+ #[inline]
309309+ fn is_human_readable(&self) -> bool {
310310+ false
311311+ }
312312+}
313313+314314+/// Struct for implementign SerializeSeq.
315315+pub struct CollectSeq<'a, W> {
316316+ /// The number of elements. This is used in case the number of elements is not known
317317+ /// beforehand.
318318+ count: usize,
319319+ ser: &'a mut Serializer<W>,
320320+ /// An in-memory serializer in case the number of elements is not known beforehand.
321321+ mem_ser: Option<Serializer<BufWriter>>,
322322+}
323323+324324+impl<'a, W: enc::Write> CollectSeq<'a, W> {
325325+ /// If the length of the sequence is given, use it. Else buffer the sequence in order to count
326326+ /// the number of elements, which is then written before the elements are.
327327+ fn new(ser: &'a mut Serializer<W>, len: Option<usize>) -> Result<Self, EncodeError<W::Error>> {
328328+ let mem_ser = if let Some(len) = len {
329329+ enc::ArrayStartBounded(len).encode(&mut ser.writer)?;
330330+ None
331331+ } else {
332332+ Some(Serializer::new(BufWriter::new(Vec::new())))
333333+ };
334334+ Ok(Self {
335335+ count: 0,
336336+ ser,
337337+ mem_ser,
338338+ })
339339+ }
340340+}
341341+342342+/// Helper for processing collections.
343343+pub struct BoundedCollect<'a, W> {
344344+ ser: &'a mut Serializer<W>,
345345+}
346346+347347+impl<W: enc::Write> serde::ser::SerializeSeq for CollectSeq<'_, W> {
348348+ type Ok = ();
349349+ type Error = EncodeError<W::Error>;
350350+351351+ #[inline]
352352+ fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> {
353353+ self.count += 1;
354354+ if let Some(ser) = self.mem_ser.as_mut() {
355355+ value
356356+ .serialize(&mut *ser)
357357+ .map_err(|_| EncodeError::Msg("List element cannot be serialized".to_string()))
358358+ } else {
359359+ value.serialize(&mut *self.ser)
360360+ }
361361+ }
362362+363363+ #[inline]
364364+ fn end(self) -> Result<Self::Ok, Self::Error> {
365365+ // Data was buffered in order to be able to write out the number of elements before they
366366+ // are serialized.
367367+ if let Some(ser) = self.mem_ser {
368368+ enc::ArrayStartBounded(self.count).encode(&mut self.ser.writer)?;
369369+ self.ser.writer.push(&ser.into_inner().into_inner())?;
370370+ }
371371+372372+ Ok(())
373373+ }
374374+}
375375+376376+impl<W: enc::Write> serde::ser::SerializeTuple for BoundedCollect<'_, W> {
377377+ type Ok = ();
378378+ type Error = EncodeError<W::Error>;
379379+380380+ #[inline]
381381+ fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> {
382382+ value.serialize(&mut *self.ser)
383383+ }
384384+385385+ #[inline]
386386+ fn end(self) -> Result<Self::Ok, Self::Error> {
387387+ Ok(())
388388+ }
389389+}
390390+391391+impl<W: enc::Write> serde::ser::SerializeTupleStruct for BoundedCollect<'_, W> {
392392+ type Ok = ();
393393+ type Error = EncodeError<W::Error>;
394394+395395+ #[inline]
396396+ fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> {
397397+ value.serialize(&mut *self.ser)
398398+ }
399399+400400+ #[inline]
401401+ fn end(self) -> Result<Self::Ok, Self::Error> {
402402+ Ok(())
403403+ }
404404+}
405405+406406+impl<W: enc::Write> serde::ser::SerializeTupleVariant for BoundedCollect<'_, W> {
407407+ type Ok = ();
408408+ type Error = EncodeError<W::Error>;
409409+410410+ #[inline]
411411+ fn serialize_field<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> {
412412+ value.serialize(&mut *self.ser)
413413+ }
414414+415415+ #[inline]
416416+ fn end(self) -> Result<Self::Ok, Self::Error> {
417417+ Ok(())
418418+ }
419419+}
420420+421421+/// CBOR RFC-7049 specifies a canonical sort order, where keys are sorted by length first. This
422422+/// was later revised with RFC-8949, but we need to stick to the original order to stay compatible
423423+/// with existing data.
424424+/// We first serialize each map entry (the key and the value) into a buffer and then sort those
425425+/// buffers. Once sorted they are written to the actual output.
426426+pub struct CollectMap<'a, W> {
427427+ buffer: BufWriter,
428428+ entries: Vec<Vec<u8>>,
429429+ ser: &'a mut Serializer<W>,
430430+}
431431+432432+impl<'a, W> CollectMap<'a, W>
433433+where
434434+ W: enc::Write,
435435+{
436436+ fn new(ser: &'a mut Serializer<W>) -> Self {
437437+ Self {
438438+ buffer: BufWriter::new(Vec::new()),
439439+ entries: Vec::new(),
440440+ ser,
441441+ }
442442+ }
443443+444444+ fn serialize<T: Serialize + ?Sized>(
445445+ &mut self,
446446+ maybe_key: Option<&'static str>,
447447+ value: &T,
448448+ ) -> Result<(), EncodeError<W::Error>> {
449449+ // Instantiate a new serializer, so that the buffer can be re-used.
450450+ let mut mem_serializer = Serializer::new(&mut self.buffer);
451451+ if let Some(key) = maybe_key {
452452+ key.serialize(&mut mem_serializer)
453453+ .map_err(|_| EncodeError::Msg("Struct key cannot be serialized.".to_string()))?;
454454+ }
455455+ value
456456+ .serialize(&mut mem_serializer)
457457+ .map_err(|_| EncodeError::Msg("Struct value cannot be serialized.".to_string()))?;
458458+459459+ self.entries.push(self.buffer.buffer().to_vec());
460460+ self.buffer.clear();
461461+462462+ Ok(())
463463+ }
464464+465465+ fn end(mut self) -> Result<(), EncodeError<W::Error>> {
466466+ // This sorting step makes sure we have the expected order of the keys. Byte-wise
467467+ // comparison over the encoded forms gives us the right order as keys in DAG-CBOR are
468468+ // always (text) strings, hence have the same CBOR major type 3. The length of the string
469469+ // is encoded in the prefix bits along with the major type. This means that a shorter string
470470+ // always sorts before a longer string even with the compact length representation.
471471+ self.entries.sort_unstable();
472472+ for entry in self.entries {
473473+ self.ser.writer.push(&entry)?;
474474+ }
475475+ Ok(())
476476+ }
477477+}
478478+479479+impl<W> serde::ser::SerializeMap for CollectMap<'_, W>
480480+where
481481+ W: enc::Write,
482482+{
483483+ type Ok = ();
484484+ type Error = EncodeError<W::Error>;
485485+486486+ #[inline]
487487+ fn serialize_key<T: Serialize + ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> {
488488+ // The key needs to be add to the buffer without any further operations. Serializing the
489489+ // value will then do the necessary flushing etc.
490490+ let mut mem_serializer = Serializer::new(&mut self.buffer);
491491+ key.serialize(&mut mem_serializer)
492492+ .map_err(|_| EncodeError::Msg("Map key cannot be serialized.".to_string()))?;
493493+ Ok(())
494494+ }
495495+496496+ #[inline]
497497+ fn serialize_value<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> {
498498+ self.serialize(None, value)
499499+ }
500500+501501+ #[inline]
502502+ fn end(self) -> Result<Self::Ok, Self::Error> {
503503+ enc::MapStartBounded(self.entries.len()).encode(&mut self.ser.writer)?;
504504+ self.end()
505505+ }
506506+}
507507+508508+impl<W> serde::ser::SerializeStruct for CollectMap<'_, W>
509509+where
510510+ W: enc::Write,
511511+{
512512+ type Ok = ();
513513+ type Error = EncodeError<W::Error>;
514514+515515+ #[inline]
516516+ fn serialize_field<T: Serialize + ?Sized>(
517517+ &mut self,
518518+ key: &'static str,
519519+ value: &T,
520520+ ) -> Result<(), Self::Error> {
521521+ self.serialize(Some(key), value)
522522+ }
523523+524524+ #[inline]
525525+ fn end(self) -> Result<Self::Ok, Self::Error> {
526526+ self.end()
527527+ }
528528+}
529529+530530+impl<W> serde::ser::SerializeStructVariant for CollectMap<'_, W>
531531+where
532532+ W: enc::Write,
533533+{
534534+ type Ok = ();
535535+ type Error = EncodeError<W::Error>;
536536+537537+ #[inline]
538538+ fn serialize_field<T: Serialize + ?Sized>(
539539+ &mut self,
540540+ key: &'static str,
541541+ value: &T,
542542+ ) -> Result<(), Self::Error> {
543543+ self.serialize(Some(key), value)
544544+ }
545545+546546+ #[inline]
547547+ fn end(self) -> Result<Self::Ok, Self::Error> {
548548+ self.end()
549549+ }
550550+}
551551+552552+/// Serializing a CID correctly as DAG-CBOR.
553553+struct CidSerializer<'a, W>(&'a mut Serializer<W>);
554554+555555+impl<'a, W: enc::Write> ser::Serializer for &'a mut CidSerializer<'a, W>
556556+where
557557+ W::Error: core::fmt::Debug,
558558+{
559559+ type Ok = ();
560560+ type Error = EncodeError<W::Error>;
561561+562562+ type SerializeSeq = ser::Impossible<Self::Ok, Self::Error>;
563563+ type SerializeTuple = ser::Impossible<Self::Ok, Self::Error>;
564564+ type SerializeTupleStruct = ser::Impossible<Self::Ok, Self::Error>;
565565+ type SerializeTupleVariant = ser::Impossible<Self::Ok, Self::Error>;
566566+ type SerializeMap = ser::Impossible<Self::Ok, Self::Error>;
567567+ type SerializeStruct = ser::Impossible<Self::Ok, Self::Error>;
568568+ type SerializeStructVariant = ser::Impossible<Self::Ok, Self::Error>;
569569+570570+ fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
571571+ Err(ser::Error::custom("unreachable"))
572572+ }
573573+ fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> {
574574+ Err(ser::Error::custom("unreachable"))
575575+ }
576576+ fn serialize_i16(self, _value: i16) -> Result<Self::Ok, Self::Error> {
577577+ Err(ser::Error::custom("unreachable"))
578578+ }
579579+ fn serialize_i32(self, _value: i32) -> Result<Self::Ok, Self::Error> {
580580+ Err(ser::Error::custom("unreachable"))
581581+ }
582582+ fn serialize_i64(self, _value: i64) -> Result<Self::Ok, Self::Error> {
583583+ Err(ser::Error::custom("unreachable"))
584584+ }
585585+ fn serialize_u8(self, _value: u8) -> Result<Self::Ok, Self::Error> {
586586+ Err(ser::Error::custom("unreachable"))
587587+ }
588588+ fn serialize_u16(self, _value: u16) -> Result<Self::Ok, Self::Error> {
589589+ Err(ser::Error::custom("unreachable"))
590590+ }
591591+ fn serialize_u32(self, _value: u32) -> Result<Self::Ok, Self::Error> {
592592+ Err(ser::Error::custom("unreachable"))
593593+ }
594594+ fn serialize_u64(self, _value: u64) -> Result<Self::Ok, Self::Error> {
595595+ Err(ser::Error::custom("unreachable"))
596596+ }
597597+ fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> {
598598+ Err(ser::Error::custom("unreachable"))
599599+ }
600600+ fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> {
601601+ Err(ser::Error::custom("unreachable"))
602602+ }
603603+ fn serialize_char(self, _value: char) -> Result<Self::Ok, Self::Error> {
604604+ Err(ser::Error::custom("unreachable"))
605605+ }
606606+ fn serialize_str(self, _value: &str) -> Result<Self::Ok, Self::Error> {
607607+ Err(ser::Error::custom("unreachable"))
608608+ }
609609+610610+ fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
611611+ // The bytes of the CID is prefixed with a null byte when encoded as CBOR.
612612+ let prefixed = [&[0x00], value].concat();
613613+ // CIDs are serialized with CBOR tag 42.
614614+ types::Tag(CBOR_TAGS_CID, types::Bytes(&prefixed[..])).encode(&mut self.0.writer)?;
615615+ Ok(())
616616+ }
617617+618618+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
619619+ Err(ser::Error::custom("unreachable"))
620620+ }
621621+ fn serialize_some<T: ?Sized + ser::Serialize>(
622622+ self,
623623+ _value: &T,
624624+ ) -> Result<Self::Ok, Self::Error> {
625625+ Err(ser::Error::custom("unreachable"))
626626+ }
627627+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
628628+ Err(ser::Error::custom("unreachable"))
629629+ }
630630+ fn serialize_unit_struct(self, _name: &str) -> Result<Self::Ok, Self::Error> {
631631+ Err(ser::Error::custom("unreachable"))
632632+ }
633633+ fn serialize_unit_variant(
634634+ self,
635635+ _name: &str,
636636+ _variant_index: u32,
637637+ _variant: &str,
638638+ ) -> Result<Self::Ok, Self::Error> {
639639+ Err(ser::Error::custom("unreachable"))
640640+ }
641641+642642+ fn serialize_newtype_struct<T: ?Sized + ser::Serialize>(
643643+ self,
644644+ _name: &str,
645645+ _value: &T,
646646+ ) -> Result<Self::Ok, Self::Error> {
647647+ Err(ser::Error::custom("unreachable"))
648648+ }
649649+ fn serialize_newtype_variant<T: ?Sized + ser::Serialize>(
650650+ self,
651651+ _name: &str,
652652+ _variant_index: u32,
653653+ _variant: &str,
654654+ _value: &T,
655655+ ) -> Result<Self::Ok, Self::Error> {
656656+ Err(ser::Error::custom("unreachable"))
657657+ }
658658+ fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
659659+ Err(ser::Error::custom("unreachable"))
660660+ }
661661+ fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
662662+ Err(ser::Error::custom("unreachable"))
663663+ }
664664+ fn serialize_tuple_struct(
665665+ self,
666666+ _name: &str,
667667+ _len: usize,
668668+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
669669+ Err(ser::Error::custom("unreachable"))
670670+ }
671671+ fn serialize_tuple_variant(
672672+ self,
673673+ _name: &str,
674674+ _variant_index: u32,
675675+ _variant: &str,
676676+ _len: usize,
677677+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
678678+ Err(ser::Error::custom("unreachable"))
679679+ }
680680+ fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
681681+ Err(ser::Error::custom("unreachable"))
682682+ }
683683+ fn serialize_struct(
684684+ self,
685685+ _name: &str,
686686+ _len: usize,
687687+ ) -> Result<Self::SerializeStruct, Self::Error> {
688688+ Err(ser::Error::custom("unreachable"))
689689+ }
690690+ fn serialize_struct_variant(
691691+ self,
692692+ _name: &str,
693693+ _variant_index: u32,
694694+ _variant: &str,
695695+ _len: usize,
696696+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
697697+ Err(ser::Error::custom("unreachable"))
698698+ }
699699+}
+355
vendor/git/serde_ipld_dagcbor/tests/cid.rs
···11+use std::convert::{TryFrom, TryInto};
22+use std::str::FromStr;
33+44+use ipld_core::{cid::Cid, ipld::Ipld};
55+use serde::de;
66+use serde_bytes::ByteBuf;
77+use serde_derive::{Deserialize, Serialize};
88+use serde_ipld_dagcbor::{from_slice, to_vec};
99+1010+#[test]
1111+fn test_cid_struct() {
1212+ #[derive(Debug, PartialEq, Deserialize, Serialize)]
1313+ struct MyStruct {
1414+ cid: Cid,
1515+ data: bool,
1616+ }
1717+1818+ let cid = Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
1919+ let cid_encoded = to_vec(&cid).unwrap();
2020+ assert_eq!(
2121+ cid_encoded,
2222+ [
2323+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68,
2424+ 0xff, 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d,
2525+ 0x70, 0x64, 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
2626+ ]
2727+ );
2828+2929+ let cid_decoded_as_cid: Cid = from_slice(&cid_encoded).unwrap();
3030+ assert_eq!(cid_decoded_as_cid, cid);
3131+3232+ let cid_decoded_as_ipld: Ipld = from_slice(&cid_encoded).unwrap();
3333+ assert_eq!(cid_decoded_as_ipld, Ipld::Link(cid));
3434+3535+ // Tests with the Type nested in a struct
3636+3737+ let mystruct = MyStruct { cid, data: true };
3838+ let mystruct_encoded = to_vec(&mystruct).unwrap();
3939+ assert_eq!(
4040+ mystruct_encoded,
4141+ [
4242+ 0xa2, 0x63, 0x63, 0x69, 0x64, 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20,
4343+ 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff, 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30,
4444+ 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64, 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88,
4545+ 0x62, 0x66, 0xe7, 0xae, 0x64, 0x64, 0x61, 0x74, 0x61, 0xf5
4646+ ]
4747+ );
4848+4949+ let mystruct_decoded_as_mystruct: MyStruct = from_slice(&mystruct_encoded).unwrap();
5050+ assert_eq!(mystruct_decoded_as_mystruct, mystruct);
5151+5252+ let mystruct_decoded_as_ipld: Ipld = from_slice(&mystruct_encoded).unwrap();
5353+ let mut expected_map = std::collections::BTreeMap::new();
5454+ expected_map.insert("cid".to_string(), Ipld::Link(cid));
5555+ expected_map.insert("data".to_string(), Ipld::Bool(true));
5656+ assert_eq!(mystruct_decoded_as_ipld, Ipld::Map(expected_map));
5757+}
5858+5959+/// Test that arbitrary bytes are not interpreted as CID.
6060+#[test]
6161+fn test_binary_not_as_cid() {
6262+ // h'affe'
6363+ // 42 # bytes(2)
6464+ // AFFE # "\xAF\xFE"
6565+ let bytes = [0x42, 0xaf, 0xfe];
6666+ let bytes_as_ipld: Ipld = from_slice(&bytes).unwrap();
6767+ assert_eq!(bytes_as_ipld, Ipld::Bytes(vec![0xaf, 0xfe]));
6868+}
6969+7070+/// Test that CIDs don't decode into byte buffers, lists, etc.
7171+#[test]
7272+fn test_cid_not_as_bytes() {
7373+ let cbor_cid = [
7474+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
7575+ 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
7676+ 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
7777+ ];
7878+ from_slice::<Vec<u8>>(&cbor_cid).expect_err("shouldn't have parsed a tagged CID as a sequence");
7979+ from_slice::<serde_bytes::ByteBuf>(&cbor_cid)
8080+ .expect_err("shouldn't have parsed a tagged CID as a byte array");
8181+ from_slice::<serde_bytes::ByteBuf>(&cbor_cid[2..])
8282+ .expect("should have parsed an untagged CID as a byte array");
8383+8484+ #[derive(Debug, Deserialize, PartialEq)]
8585+ struct NewType(ByteBuf);
8686+8787+ #[derive(Debug, Deserialize, PartialEq)]
8888+ #[serde(untagged)]
8989+ enum BytesInEnum {
9090+ MyCid(NewType),
9191+ }
9292+9393+ // With the `no-cid-as-bytes` feature enabled, we make sure that it will error, when we try to
9494+ // decode a CID as bytes.
9595+ #[cfg(feature = "no-cid-as-bytes")]
9696+ from_slice::<BytesInEnum>(&cbor_cid)
9797+ .expect_err("shouldn't have parsed a tagged CID as byte array");
9898+9999+ // With that feature disabled, then it will decode the CID (without the TAG and the zero
100100+ // prefix) as bytes.
101101+ #[cfg(not(feature = "no-cid-as-bytes"))]
102102+ {
103103+ let cid_without_tag = &cbor_cid[5..];
104104+ assert_eq!(
105105+ from_slice::<BytesInEnum>(&cbor_cid).unwrap(),
106106+ BytesInEnum::MyCid(NewType(ByteBuf::from(cid_without_tag)))
107107+ );
108108+ }
109109+}
110110+111111+/// Test whether a binary CID could be serialized if it isn't prefixed by tag 42. It should fail.
112112+#[test]
113113+fn test_cid_bytes_without_tag() {
114114+ let cbor_cid = [
115115+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
116116+ 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
117117+ 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
118118+ ];
119119+ let decoded_cbor_cid: Cid = from_slice(&cbor_cid).unwrap();
120120+ assert_eq!(decoded_cbor_cid.to_bytes(), &cbor_cid[5..]);
121121+122122+ // The CID without the tag 42 prefix
123123+ let cbor_bytes = &cbor_cid[2..];
124124+ from_slice::<Cid>(cbor_bytes).expect_err("should have failed to decode bytes as cid");
125125+}
126126+127127+/// This test shows how a kinded enum could be implemented.
128128+#[test]
129129+fn test_cid_in_kinded_enum() {
130130+ #[derive(Debug, PartialEq)]
131131+ pub enum Kinded {
132132+ Bytes(ByteBuf),
133133+ Link(Cid),
134134+ }
135135+136136+ let cbor_cid = [
137137+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
138138+ 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
139139+ 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
140140+ ];
141141+142142+ impl TryFrom<Ipld> for Kinded {
143143+ type Error = ();
144144+145145+ fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
146146+ match ipld {
147147+ Ipld::Bytes(bytes) => Ok(Self::Bytes(ByteBuf::from(bytes))),
148148+ Ipld::Link(cid) => Ok(Self::Link(cid)),
149149+ _ => Err(()),
150150+ }
151151+ }
152152+ }
153153+154154+ impl<'de> de::Deserialize<'de> for Kinded {
155155+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
156156+ where
157157+ D: de::Deserializer<'de>,
158158+ {
159159+ Ipld::deserialize(deserializer).and_then(|ipld| {
160160+ ipld.try_into()
161161+ .map_err(|_| de::Error::custom("No matching enum variant found"))
162162+ })
163163+ }
164164+ }
165165+166166+ let decoded_cid: Kinded = from_slice(&cbor_cid).unwrap();
167167+ let cid = Cid::try_from(&cbor_cid[5..]).unwrap();
168168+ assert_eq!(decoded_cid, Kinded::Link(cid));
169169+170170+ // The CID without the tag 42 prefix
171171+ let cbor_bytes = &cbor_cid[2..];
172172+ let decoded_bytes: Kinded = from_slice(cbor_bytes).unwrap();
173173+ // The CBOR decoded bytes don't contain the prefix with the bytes type identifier and the
174174+ // length.
175175+ let bytes = cbor_bytes[2..].to_vec();
176176+ assert_eq!(decoded_bytes, Kinded::Bytes(ByteBuf::from(bytes)));
177177+178178+ // Check that random bytes cannot be deserialized.
179179+ let random_bytes = &cbor_cid[10..];
180180+ let decoded_random_bytes: Result<Kinded, _> = from_slice(random_bytes);
181181+ assert!(decoded_random_bytes.is_err());
182182+}
183183+184184+/// This test shows how a kinded enum could be implemented, when bytes as well as a CID are wrapped
185185+/// in a newtype struct.
186186+#[test]
187187+fn test_cid_in_kinded_enum_with_newtype() {
188188+ #[derive(Debug, Deserialize, PartialEq)]
189189+ pub struct Foo(#[serde(with = "serde_bytes")] Vec<u8>);
190190+191191+ #[derive(Debug, PartialEq)]
192192+ pub enum Kinded {
193193+ MyBytes(Foo),
194194+ Link(Cid),
195195+ }
196196+197197+ let cbor_cid = [
198198+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
199199+ 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
200200+ 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
201201+ ];
202202+203203+ impl TryFrom<Ipld> for Kinded {
204204+ type Error = ();
205205+206206+ fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
207207+ match ipld {
208208+ Ipld::Bytes(bytes) => Ok(Self::MyBytes(Foo(bytes))),
209209+ Ipld::Link(cid) => Ok(Self::Link(cid)),
210210+ _ => Err(()),
211211+ }
212212+ }
213213+ }
214214+215215+ impl<'de> de::Deserialize<'de> for Kinded {
216216+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
217217+ where
218218+ D: de::Deserializer<'de>,
219219+ {
220220+ Ipld::deserialize(deserializer).and_then(|ipld| {
221221+ ipld.try_into()
222222+ .map_err(|_| de::Error::custom("No matching enum variant found"))
223223+ })
224224+ }
225225+ }
226226+227227+ let decoded_cid: Kinded = from_slice(&cbor_cid).unwrap();
228228+ // The actual CID is without the CBOR tag 42, the byte identifier and the data length.
229229+ let cid = Cid::try_from(&cbor_cid[5..]).unwrap();
230230+ assert_eq!(decoded_cid, Kinded::Link(cid));
231231+232232+ // The CID without the tag 42 prefix
233233+ let cbor_bytes = &cbor_cid[2..];
234234+ let decoded_bytes: Kinded = from_slice(cbor_bytes).unwrap();
235235+ // The CBOR decoded bytes don't contain the prefix with the bytes type identifier and the
236236+ // length.
237237+ let bytes = cbor_bytes[2..].to_vec();
238238+ assert_eq!(decoded_bytes, Kinded::MyBytes(Foo(bytes)));
239239+240240+ // Check that random bytes cannot be deserialized.
241241+ let random_bytes = &cbor_cid[10..];
242242+ let decoded_random_bytes: Result<Kinded, _> = from_slice(random_bytes);
243243+ assert!(decoded_random_bytes.is_err());
244244+}
245245+246246+#[test]
247247+fn test_cid_in_tagged_enum() {
248248+ #[derive(Debug, Deserialize, PartialEq)]
249249+ pub enum Externally {
250250+ Cid(Cid),
251251+ }
252252+253253+ #[derive(Debug, Deserialize, PartialEq)]
254254+ #[serde(tag = "type")]
255255+ pub enum Internally {
256256+ Cid { cid: Cid },
257257+ }
258258+259259+ #[derive(Debug, Deserialize, PartialEq)]
260260+ #[serde(untagged)]
261261+ pub enum Untagged {
262262+ Cid(Cid),
263263+ }
264264+265265+ let cbor_cid = [
266266+ 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
267267+ 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
268268+ 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
269269+ ];
270270+271271+ // {"Cid": cid}
272272+ let cbor_map1 = [vec![0xa1, 0x63, 0x43, 0x69, 0x64], Vec::from(cbor_cid)].concat();
273273+274274+ // {"cid": cid, "type": "Cid"}
275275+ let cbor_map2 = [
276276+ vec![
277277+ 0xa2, 0x64, 0x74, 0x79, 0x70, 0x65, 0x63, 0x43, 0x69, 0x64, 0x63, 0x63, 0x69, 0x64,
278278+ ],
279279+ Vec::from(cbor_cid),
280280+ ]
281281+ .concat();
282282+283283+ let cid = Cid::try_from(&cbor_cid[5..]).unwrap();
284284+285285+ let decoded: Externally = from_slice(&cbor_map1).unwrap();
286286+ assert_eq!(decoded, Externally::Cid(cid));
287287+288288+ // With the `no-cid-as-bytes` feature enabled, it's not possible to use internally tagged or
289289+ // untaggd enums. This behaviour is *not* intentionally, but incidentally due to how Serde
290290+ // internally works.. This test is only added to see what one could expect, and to get
291291+ // notified in case it ever gets supported.
292292+ #[cfg(feature = "no-cid-as-bytes")]
293293+ {
294294+ from_slice::<Internally>(&cbor_map2)
295295+ .expect_err("shouldn't be able to decode the intanlly tagged enum");
296296+ from_slice::<Untagged>(&cbor_cid)
297297+ .expect_err("shouldn't be able to decode the untagged enum");
298298+ }
299299+300300+ // With that feature disabled, it's the expected desired behaviour.
301301+ #[cfg(not(feature = "no-cid-as-bytes"))]
302302+ {
303303+ let decoded: Internally = from_slice(&cbor_map2).unwrap();
304304+ assert_eq!(decoded, Internally::Cid { cid });
305305+306306+ let decoded: Untagged = from_slice(&cbor_cid).unwrap();
307307+ assert_eq!(decoded, Untagged::Cid(cid));
308308+ }
309309+}
310310+311311+#[test]
312312+fn test_cid_empty_errors() {
313313+ // Tag 42 with zero bytes
314314+ let cbor_empty_cid = [0xd8, 0x2a, 0x40];
315315+316316+ let decoded: Result<Cid, _> = from_slice(&cbor_empty_cid);
317317+ assert!(decoded.is_err());
318318+}
319319+320320+#[test]
321321+fn test_cid_non_minimally_encoded() {
322322+ let cid = Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
323323+ let cid_encoded = to_vec(&cid).unwrap();
324324+325325+ let decoded: Cid = from_slice(&cid_encoded).unwrap();
326326+ assert_eq!(decoded, cid);
327327+328328+ // Strip off the CBOR tag.
329329+ let without_tag = &cid_encoded[2..];
330330+331331+ let tag_2_bytes_encoded = [&[0xd9, 0x00, 0x2a], without_tag].concat();
332332+ let tag_2_bytes_decoded: Cid = from_slice(&tag_2_bytes_encoded).unwrap();
333333+ assert_eq!(tag_2_bytes_decoded, cid);
334334+335335+ let tag_4_bytes_encoded = [&[0xda, 0x00, 0x00, 0x00, 0x2a], without_tag].concat();
336336+ let tag_4_bytes_decoded: Cid = from_slice(&tag_4_bytes_encoded).unwrap();
337337+ assert_eq!(tag_4_bytes_decoded, cid);
338338+339339+ let tag_8_bytes_encoded = [
340340+ &[0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a],
341341+ without_tag,
342342+ ]
343343+ .concat();
344344+ let tag_8_bytes_decoded: Cid = from_slice(&tag_8_bytes_encoded).unwrap();
345345+ assert_eq!(tag_8_bytes_decoded, cid);
346346+}
347347+348348+#[test]
349349+fn test_cid_decode_from_reader() {
350350+ let cid_encoded = [
351351+ 0xd8, 0x2a, 0x49, 0x00, 0x01, 0xce, 0x01, 0x9b, 0x01, 0x02, 0x63, 0xc8,
352352+ ];
353353+ let cid_decoded: Cid = from_slice(&cid_encoded).unwrap();
354354+ assert_eq!(&cid_encoded[4..], &cid_decoded.to_bytes());
355355+}
+66
vendor/git/serde_ipld_dagcbor/tests/codec.rs
···11+#![cfg(all(feature = "std", not(feature = "no-cid-as-bytes")))]
22+33+use core::{convert::TryFrom, iter};
44+55+use ipld_core::{
66+ cid::Cid,
77+ codec::{Codec, Links},
88+ ipld,
99+ ipld::Ipld,
1010+};
1111+use serde_ipld_dagcbor::codec::DagCborCodec;
1212+1313+#[test]
1414+fn test_codec_encode() {
1515+ let data = "hello world!".to_string();
1616+ let expected = b"\x6chello world!";
1717+1818+ let mut output = Vec::new();
1919+ DagCborCodec::encode(&mut output, &data).unwrap();
2020+ assert_eq!(output, expected);
2121+2222+ let encoded = DagCborCodec::encode_to_vec(&data).unwrap();
2323+ assert_eq!(encoded, expected);
2424+}
2525+2626+#[test]
2727+fn test_codec_decode() {
2828+ let data = b"\x6chello world!";
2929+ let expected = "hello world!".to_string();
3030+3131+ let decoded: String = DagCborCodec::decode(&data[..]).unwrap();
3232+ assert_eq!(decoded, expected);
3333+3434+ let decoded_from_slice: String = DagCborCodec::decode_from_slice(data).unwrap();
3535+ assert_eq!(decoded_from_slice, expected);
3636+}
3737+3838+#[test]
3939+fn test_codec_links() {
4040+ let cid = Cid::try_from("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
4141+ let data: Ipld = ipld!({"some": {"nested": cid}, "or": [cid, cid], "foo": true});
4242+ let expected = iter::repeat_n(cid, 3).collect::<Vec<_>>();
4343+4444+ let mut encoded = Vec::new();
4545+ DagCborCodec::encode(&mut encoded, &data).unwrap();
4646+4747+ let links = DagCborCodec::links(&encoded).unwrap();
4848+ assert_eq!(links.collect::<Vec<_>>(), expected);
4949+}
5050+5151+#[test]
5252+fn test_codec_generic() {
5353+ fn encode_generic<C, T>(value: T) -> Vec<u8>
5454+ where
5555+ C: Codec<T>,
5656+ C::Error: std::fmt::Debug,
5757+ {
5858+ C::encode_to_vec(&value).unwrap()
5959+ }
6060+6161+ let data = "hello world!".to_string();
6262+ let expected = b"\x6chello world!";
6363+6464+ let encoded = encode_generic::<DagCborCodec, _>(data);
6565+ assert_eq!(encoded, expected);
6666+}
vendor/git/serde_ipld_dagcbor/tests/crash.cbor
This is a binary file and will not be displayed.
+688
vendor/git/serde_ipld_dagcbor/tests/de.rs
···11+use std::collections::BTreeMap;
22+33+use ipld_core::ipld::Ipld;
44+use serde::{Deserialize, Serialize};
55+use serde_ipld_dagcbor::{de, to_vec, DecodeError};
66+use serde_tuple::{Deserialize_tuple, Serialize_tuple};
77+use std::convert::Infallible;
88+99+#[test]
1010+fn test_string1() {
1111+ let ipld: Result<Ipld, _> = de::from_slice(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
1212+ assert_eq!(ipld.unwrap(), Ipld::String("foobar".to_string()));
1313+}
1414+1515+#[test]
1616+fn test_string2() {
1717+ let ipld: Result<Ipld, _> = de::from_slice(&[
1818+ 0x71, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65, 0x6c,
1919+ 0x6c, 0x65, 0x72,
2020+ ]);
2121+ assert_eq!(ipld.unwrap(), Ipld::String("I met a traveller".to_string()));
2222+}
2323+2424+#[test]
2525+fn test_string3() {
2626+ let slice = b"\x78\x2fI met a traveller from an antique land who said";
2727+ let ipld: Result<Ipld, _> = de::from_slice(slice);
2828+ assert_eq!(
2929+ ipld.unwrap(),
3030+ Ipld::String("I met a traveller from an antique land who said".to_string())
3131+ );
3232+}
3333+3434+#[test]
3535+fn test_byte_string() {
3636+ let ipld: Result<Ipld, _> = de::from_slice(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
3737+ assert_eq!(ipld.unwrap(), Ipld::Bytes(b"foobar".to_vec()));
3838+}
3939+4040+#[test]
4141+fn test_numbers1() {
4242+ let ipld: Result<Ipld, _> = de::from_slice(&[0x00]);
4343+ assert_eq!(ipld.unwrap(), Ipld::Integer(0));
4444+}
4545+4646+#[test]
4747+fn test_numbers2() {
4848+ let ipld: Result<Ipld, _> = de::from_slice(&[0x1a, 0x00, 0xbc, 0x61, 0x4e]);
4949+ assert_eq!(ipld.unwrap(), Ipld::Integer(12345678));
5050+}
5151+5252+#[test]
5353+fn test_numbers3() {
5454+ let ipld: Result<Ipld, _> = de::from_slice(&[0x39, 0x07, 0xde]);
5555+ assert_eq!(ipld.unwrap(), Ipld::Integer(-2015));
5656+}
5757+5858+#[test]
5959+fn test_numbers_large_negative() {
6060+ let ipld: Result<Ipld, _> =
6161+ de::from_slice(&[0x3b, 0xa5, 0xf7, 0x02, 0xb3, 0xa5, 0xf7, 0x02, 0xb3]);
6262+ let expected: i128 = -11959030306112471732;
6363+ assert!(expected < i128::from(i64::MIN));
6464+ assert_eq!(ipld.unwrap(), Ipld::Integer(expected));
6565+}
6666+6767+#[test]
6868+fn test_bool() {
6969+ let ipld: Result<Ipld, _> = de::from_slice(b"\xf4");
7070+ assert_eq!(ipld.unwrap(), Ipld::Bool(false));
7171+}
7272+7373+#[test]
7474+fn test_trailing_bytes() {
7575+ let ipld: Result<Ipld, _> = de::from_slice(b"\xf4trailing");
7676+ assert!(matches!(ipld.unwrap_err(), DecodeError::TrailingData));
7777+}
7878+7979+#[test]
8080+fn test_list1() {
8181+ let ipld: Result<Ipld, _> = de::from_slice(b"\x83\x01\x02\x03");
8282+ assert_eq!(
8383+ ipld.unwrap(),
8484+ Ipld::List(vec![Ipld::Integer(1), Ipld::Integer(2), Ipld::Integer(3)])
8585+ );
8686+}
8787+8888+#[test]
8989+fn test_list2() {
9090+ let ipld: Result<Ipld, _> = de::from_slice(b"\x82\x01\x82\x02\x81\x03");
9191+ assert_eq!(
9292+ ipld.unwrap(),
9393+ Ipld::List(vec![
9494+ Ipld::Integer(1),
9595+ Ipld::List(vec![Ipld::Integer(2), Ipld::List(vec![Ipld::Integer(3)])])
9696+ ])
9797+ );
9898+}
9999+100100+#[test]
101101+fn test_object() {
102102+ let ipld: Result<Ipld, _> = de::from_slice(b"\xa5aaaAabaBacaCadaDaeaE");
103103+ let mut object = BTreeMap::new();
104104+ object.insert("a".to_string(), Ipld::String("A".to_string()));
105105+ object.insert("b".to_string(), Ipld::String("B".to_string()));
106106+ object.insert("c".to_string(), Ipld::String("C".to_string()));
107107+ object.insert("d".to_string(), Ipld::String("D".to_string()));
108108+ object.insert("e".to_string(), Ipld::String("E".to_string()));
109109+ assert_eq!(ipld.unwrap(), Ipld::Map(object));
110110+}
111111+112112+#[test]
113113+fn test_indefinite_object_error() {
114114+ let ipld: Result<Ipld, _> = de::from_slice(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff");
115115+ let mut object = BTreeMap::new();
116116+ object.insert("a".to_string(), Ipld::Integer(1));
117117+ object.insert(
118118+ "b".to_string(),
119119+ Ipld::List(vec![Ipld::Integer(2), Ipld::Integer(3)]),
120120+ );
121121+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
122122+}
123123+124124+#[test]
125125+fn test_indefinite_list_error() {
126126+ let ipld: Result<Ipld, _> = de::from_slice(b"\x9f\x01\x02\x03\xff");
127127+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
128128+}
129129+130130+#[test]
131131+fn test_indefinite_string_error() {
132132+ let ipld: Result<Ipld, _> =
133133+ de::from_slice(b"\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff");
134134+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
135135+}
136136+137137+#[test]
138138+fn test_indefinite_byte_string_error() {
139139+ let ipld: Result<Ipld, _> = de::from_slice(b"\x5f\x42\x01\x23\x42\x45\x67\xff");
140140+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
141141+}
142142+143143+#[test]
144144+fn test_multiple_indefinite_strings_error() {
145145+ let input = b"\x82\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff\x5f\x42\x01\x23\x42\x45\x67\xff";
146146+ let ipld: Result<Ipld, _> = de::from_slice(input);
147147+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
148148+}
149149+150150+#[test]
151151+fn test_float() {
152152+ // 0xfb (f64) followed by 8 bytes of IEEE 754 double precision for 100000.0
153153+ let ipld: Result<Ipld, _> = de::from_slice(b"\xfb\x40\xf8\x6a\x00\x00\x00\x00\x00");
154154+ assert_eq!(ipld.unwrap(), Ipld::Float(100000.0));
155155+}
156156+157157+#[test]
158158+fn test_rejected_tag() {
159159+ let ipld: Result<Ipld, _> =
160160+ de::from_slice(&[0xd9, 0xd9, 0xf7, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
161161+ assert!(matches!(
162162+ ipld.unwrap_err(),
163163+ DecodeError::TypeMismatch {
164164+ name: "CBOR tag",
165165+ byte: 0xf7
166166+ }
167167+ ));
168168+}
169169+170170+#[test]
171171+fn test_crazy_list() {
172172+ let slice = b"\x86\x1b\x00\x00\x00\x1c\xbe\x99\x1d\xc7\x3b\x00\x7a\xcf\x51\xdc\x51\x70\xdb\x3a\x1b\x3a\x06\xdd\xf5\xf6\xfb\x41\x76\x5e\xb1\xf8\x00\x00\x00";
173173+ let ipld: Vec<Ipld> = de::from_slice(slice).unwrap();
174174+ assert_eq!(
175175+ ipld,
176176+ vec![
177177+ Ipld::Integer(123456789959),
178178+ Ipld::Integer(-34567897654325468),
179179+ Ipld::Integer(-456787678),
180180+ Ipld::Bool(true),
181181+ Ipld::Null,
182182+ Ipld::Float(23456543.5),
183183+ ]
184184+ );
185185+}
186186+187187+#[test]
188188+fn test_nan() {
189189+ let ipld: Result<f64, _> = de::from_slice(b"\xf9\x7e\x00");
190190+ assert!(matches!(
191191+ ipld.unwrap_err(),
192192+ DecodeError::TypeMismatch { .. }
193193+ ));
194194+}
195195+196196+#[test]
197197+// The file was reported as not working by user kie0tauB
198198+// but it parses to a cbor value.
199199+fn test_kietaub_file() {
200200+ let file = include_bytes!("kietaub.cbor");
201201+ let value_result: Result<Ipld, _> = de::from_slice(file);
202202+ value_result.unwrap();
203203+}
204204+205205+#[test]
206206+fn test_option_roundtrip() {
207207+ let obj1 = Some(10u32);
208208+209209+ let v = to_vec(&obj1).unwrap();
210210+ let obj2: Result<Option<u32>, _> = de::from_slice(&v[..]);
211211+ println!("{:?}", obj2);
212212+213213+ assert_eq!(obj1, obj2.unwrap());
214214+}
215215+216216+#[test]
217217+fn test_option_none_roundtrip() {
218218+ let obj1 = None;
219219+220220+ let v = to_vec(&obj1).unwrap();
221221+ println!("{:?}", v);
222222+ let obj2: Result<Option<u32>, _> = de::from_slice(&v[..]);
223223+224224+ assert_eq!(obj1, obj2.unwrap());
225225+}
226226+227227+#[test]
228228+fn test_unit() {
229229+ #[allow(clippy::let_unit_value)]
230230+ let unit = ();
231231+ let v = to_vec(&unit).unwrap();
232232+ assert_eq!(v, [0xf6], "unit is serialized as NULL.");
233233+ let result: Result<(), _> = from_slice(&v);
234234+ assert!(result.is_ok(), "unit was successfully deserialized");
235235+}
236236+237237+#[test]
238238+fn test_variable_length_map_error() {
239239+ let slice = b"\xbf\x67\x6d\x65\x73\x73\x61\x67\x65\x64\x70\x6f\x6e\x67\xff";
240240+ let ipld: Result<Ipld, _> = de::from_slice(slice);
241241+ assert!(matches!(ipld.unwrap_err(), DecodeError::IndefiniteSize));
242242+}
243243+244244+#[test]
245245+fn test_object_determinism_roundtrip() {
246246+ let expected = b"\xa2aa\x01ab\x82\x02\x03";
247247+248248+ // 0.1% chance of not catching failure
249249+ for _ in 0..10 {
250250+ assert_eq!(
251251+ &to_vec(&de::from_slice::<Ipld>(expected).unwrap()).unwrap(),
252252+ expected
253253+ );
254254+ }
255255+}
256256+257257+#[cfg(feature = "std")]
258258+#[test]
259259+fn test_from_reader_once() {
260260+ let v: &[u8] = &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x0a];
261261+ let mut reader = std::io::Cursor::new(v);
262262+ let value_1: String = de::from_reader_once(&mut reader).unwrap();
263263+ assert_eq!(value_1, "foobar");
264264+ let value_2: i32 = de::from_reader_once(&mut reader).unwrap();
265265+ assert_eq!(value_2, 10);
266266+ assert_eq!(v.len(), reader.position() as usize);
267267+}
268268+269269+#[cfg(feature = "std")]
270270+#[test]
271271+fn test_stream_deserializer() {
272272+ let v: &[u8] = &[
273273+ 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x63, 0x62, 0x61, 0x7A,
274274+ ];
275275+ let reader = std::io::Cursor::new(v);
276276+ let reader = cbor4ii::core::utils::IoReader::new(reader);
277277+ let mut i = de::Deserializer::from_reader(reader).into_iter();
278278+ let value_1: String = i.next().unwrap().unwrap();
279279+ assert_eq!(value_1, "foobar");
280280+ let value_2: String = i.next().unwrap().unwrap();
281281+ assert_eq!(value_2, "baz");
282282+ assert!(i.next().is_none());
283283+}
284284+285285+#[cfg(feature = "std")]
286286+#[test]
287287+fn test_stream_deserializer_marker_traits() {
288288+ use std::rc::Rc;
289289+290290+ fn is_send<T: Send>(_: &T) {}
291291+292292+ let v: &[u8] = &[
293293+ 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x63, 0x62, 0x61, 0x7A,
294294+ ];
295295+ let reader = std::io::Cursor::new(v);
296296+ let reader = cbor4ii::core::utils::IoReader::new(reader);
297297+ let mut i = de::Deserializer::from_reader(reader).into_iter();
298298+ is_send(&i);
299299+ let value_1: Rc<String> = i.next().unwrap().unwrap();
300300+ assert_eq!(value_1.as_str(), "foobar");
301301+}
302302+303303+#[cfg(feature = "std")]
304304+#[test]
305305+fn test_stream_deserializer_trailing_data() {
306306+ // one byte missing on the end
307307+ let v: &[u8] = &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x63, 0x62, 0x61];
308308+ let reader = std::io::Cursor::new(v);
309309+ let reader = cbor4ii::core::utils::IoReader::new(reader);
310310+ let mut i = de::Deserializer::from_reader(reader).into_iter();
311311+ let value_1: String = i.next().unwrap().unwrap();
312312+ assert_eq!(value_1, "foobar");
313313+314314+ // we should get back an Eof error
315315+ assert!(matches!(i.next(), Some(Err(DecodeError::Eof))));
316316+}
317317+318318+#[test]
319319+fn crash() {
320320+ let file = include_bytes!("crash.cbor");
321321+ let value_result: Result<Ipld, _> = de::from_slice(file);
322322+ assert!(matches!(value_result.unwrap_err(), DecodeError::Eof));
323323+}
324324+325325+use serde_ipld_dagcbor::de::from_slice;
326326+use std::net::{IpAddr, Ipv4Addr};
327327+#[test]
328328+fn test_ipaddr_deserialization() {
329329+ let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
330330+ let buf = to_vec(&ip).unwrap();
331331+ let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap();
332332+ assert_eq!(ip, deserialized_ip);
333333+}
334334+335335+#[test]
336336+fn attempt_stack_overflow() {
337337+ // Create a tag 17, followed by 999 more tag 17:
338338+ // 17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(...
339339+ // This causes deep recursion in the decoder and may
340340+ // exhaust the stack and therfore result in a stack overflow.
341341+ let input = vec![0xd1; 1000];
342342+ serde_ipld_dagcbor::from_slice::<Ipld>(&input).expect_err("recursion limit");
343343+}
344344+345345+#[test]
346346+fn truncated_object() {
347347+ let input: Vec<u8> = [
348348+ &b"\x84\x87\xD8\x2A\x58\x27\x00\x01\x71\xA0\xE4\x02\x20\x83\xEC\x9F\x76\x1D"[..],
349349+ &b"\xB5\xEE\xA0\xC8\xE1\xB5\x74\x0D\x1F\x0A\x1D\xB1\x8A\x52\x6B\xCB\x42\x69"[..],
350350+ &b"\xFD\x99\x24\x9E\xCE\xA9\xE8\xFD\x24\xD8\x2A\x58\x27\x00\x01\x71\xA0\xE4"[..],
351351+ &b"\x02\x20\xF1\x9B\xC1\x42\x83\x31\xB1\x39\xB3\x3F\x43\x02\x87\xCC\x1C\x12"[..],
352352+ &b"\xF2\x84\x47\xA3\x9B\x07\x59\x40\x17\x68\xFE\xE8\x09\xBB\xF2\x54\xD8\x2A"[..],
353353+ &b"\x58\x27\x00\x01\x71\xA0\xE4\x02\x20\xB0\x75\x09\x92\x78\x6B\x6B\x4C\xED"[..],
354354+ &b"\xF0\xE1\x50\xA3\x1C\xAB\xDF\x25\xA9\x26\x8C\x63\xDD\xCB\x25\x73\x6B\xF5"[..],
355355+ &b"\x8D\xE8\xA4\x24\x29"[..],
356356+ ]
357357+ .concat();
358358+ serde_ipld_dagcbor::from_slice::<Ipld>(&input).expect_err("truncated");
359359+}
360360+361361+#[test]
362362+fn invalid_string() {
363363+ // Non UTF-8 byte sequence, but using major type 3 (text string)
364364+ let input = [0x63, 0xc5, 0x01, 0x02];
365365+ let result = serde_ipld_dagcbor::from_slice::<Ipld>(&input);
366366+ assert!(matches!(
367367+ result.unwrap_err(),
368368+ DecodeError::InvalidUtf8 { .. }
369369+ ));
370370+}
371371+372372+#[test]
373373+fn error_on_undefined() {
374374+ // CBOR smple type `undefined`
375375+ let input = [0xf7];
376376+ let result = serde_ipld_dagcbor::from_slice::<Ipld>(&input);
377377+ assert!(matches!(
378378+ result.unwrap_err(),
379379+ DecodeError::Unsupported { .. }
380380+ ));
381381+}
382382+383383+// Test for default values inside tuple structs
384384+#[derive(Debug, PartialEq, Deserialize_tuple, Serialize_tuple, Default, Clone)]
385385+struct TupleWithDefaultsStruct {
386386+ #[serde(default)]
387387+ a: u32,
388388+ #[serde(default)]
389389+ b: String,
390390+}
391391+392392+// Test for default values inside tuple structs nested inside other tuple structs
393393+#[derive(Debug, PartialEq, Deserialize_tuple, Serialize_tuple, Clone)]
394394+struct TupleOuterStruct {
395395+ boop: u64,
396396+ inner: TupleWithDefaultsStruct,
397397+ #[serde(default)]
398398+ bop: u64,
399399+}
400400+401401+// Test for default values inside tuple structs nested inside other tuple structs where
402402+// the outer struct has a default value itself
403403+#[derive(Debug, PartialEq, Deserialize_tuple, Serialize_tuple, Clone)]
404404+struct TupleOuterDefaultableStruct {
405405+ boop: u64,
406406+ #[serde(default)]
407407+ inner: TupleWithDefaultsStruct,
408408+}
409409+410410+// Test for tuple structs with overflow where the types are the same so the overflow could
411411+// spill into the next field of the outer struct
412412+#[derive(Debug, PartialEq, Deserialize_tuple, Serialize_tuple, Clone)]
413413+struct TupleIntInner {
414414+ a: u32,
415415+ b: u32,
416416+}
417417+418418+#[derive(Debug, PartialEq, Deserialize_tuple, Serialize_tuple, Clone)]
419419+struct TupleIntOuterWithOverflow {
420420+ inner: TupleIntInner,
421421+ #[serde(default)]
422422+ c: u32,
423423+}
424424+425425+// Test for tuple structs with overflow where the types are the same so the overflow could
426426+// spill into the next field of the outer struct
427427+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
428428+#[serde(deny_unknown_fields)]
429429+struct MapIntInner {
430430+ a: u32,
431431+ b: u32,
432432+}
433433+434434+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
435435+#[serde(deny_unknown_fields)]
436436+struct MapIntOuterWithOverflow {
437437+ inner: MapIntInner,
438438+ #[serde(default)]
439439+ c: u32,
440440+}
441441+442442+// The expected result is either an Ok value or an error check closure.
443443+enum Expected<T> {
444444+ Ok(T),
445445+ Err(fn(&DecodeError<Infallible>) -> bool),
446446+}
447447+448448+struct TestCase<T> {
449449+ hex: &'static str,
450450+ expected: Expected<T>,
451451+}
452452+453453+#[test]
454454+fn test_default_values() {
455455+ let basic_cases = [
456456+ // [] -> default
457457+ TestCase {
458458+ hex: "80",
459459+ expected: Expected::Ok(TupleWithDefaultsStruct {
460460+ a: 0, // default
461461+ b: "".to_string(), // default
462462+ }),
463463+ },
464464+ // [101] -> set a and default b
465465+ TestCase {
466466+ hex: "811865",
467467+ expected: Expected::Ok(TupleWithDefaultsStruct {
468468+ a: 101,
469469+ b: "".to_string(), // default
470470+ }),
471471+ },
472472+ // [202, "yep"]
473473+ TestCase {
474474+ hex: "8218ca63796570",
475475+ expected: Expected::Ok(TupleWithDefaultsStruct {
476476+ a: 202,
477477+ b: "yep".to_string(),
478478+ }),
479479+ },
480480+ // [202,"nup",false] has too many elements so it errors with RequireLength
481481+ TestCase {
482482+ hex: "8318ca636e7570f4",
483483+ expected: Expected::Err(
484484+ |err| matches!(err, DecodeError::RequireLength{ name, expect, value} if *name == "TupleWithDefaultsStruct" && *expect == 2 && *value == 3),
485485+ ),
486486+ },
487487+ ];
488488+489489+ let outer_cases = [
490490+ // [505,[],606]
491491+ TestCase {
492492+ hex: "831901f98019025e",
493493+ expected: Expected::Ok(TupleOuterStruct {
494494+ boop: 505,
495495+ inner: TupleWithDefaultsStruct {
496496+ a: 0, // default
497497+ b: "".to_string(), // default
498498+ },
499499+ bop: 606,
500500+ }),
501501+ },
502502+ // [505,[202,"yep"],606]
503503+ TestCase {
504504+ hex: "831901f98218ca6379657019025e",
505505+ expected: Expected::Ok(TupleOuterStruct {
506506+ boop: 505,
507507+ inner: TupleWithDefaultsStruct {
508508+ a: 202,
509509+ b: "yep".to_string(),
510510+ },
511511+ bop: 606,
512512+ }),
513513+ },
514514+ // [505,[202,"nup",false],606] has too many elements on inner so it errors with RequireLength
515515+ TestCase {
516516+ hex: "831901f98318ca636e7570f419025e",
517517+ expected: Expected::Err(
518518+ |err| matches!(err, DecodeError::RequireLength{ name, expect, value} if *name == "TupleWithDefaultsStruct" && *expect == 2 && *value == 3),
519519+ ),
520520+ },
521521+ // [505,[]]
522522+ TestCase {
523523+ hex: "821901f980",
524524+ expected: Expected::Ok(TupleOuterStruct {
525525+ boop: 505,
526526+ inner: TupleWithDefaultsStruct {
527527+ a: 0, // default
528528+ b: "".to_string(), // default
529529+ },
530530+ bop: 0, // default
531531+ }),
532532+ },
533533+ // [505,[202,"yep"]]
534534+ TestCase {
535535+ hex: "821901f98218ca63796570",
536536+ expected: Expected::Ok(TupleOuterStruct {
537537+ boop: 505,
538538+ inner: TupleWithDefaultsStruct {
539539+ a: 202,
540540+ b: "yep".to_string(),
541541+ },
542542+ bop: 0, // default
543543+ }),
544544+ },
545545+ ];
546546+547547+ let outer_defaultable_cases = [
548548+ // [404] -> default inner
549549+ TestCase {
550550+ hex: "81190194",
551551+ expected: Expected::Ok(TupleOuterDefaultableStruct {
552552+ boop: 404,
553553+ inner: TupleWithDefaultsStruct {
554554+ // default
555555+ a: 0,
556556+ b: "".to_string(),
557557+ },
558558+ }),
559559+ },
560560+ // [404,[]] -> default inner
561561+ TestCase {
562562+ hex: "8219019480",
563563+ expected: Expected::Ok(TupleOuterDefaultableStruct {
564564+ boop: 404,
565565+ inner: TupleWithDefaultsStruct {
566566+ a: 0, // default
567567+ b: "".to_string(), // default
568568+ },
569569+ }),
570570+ },
571571+ // [] -> error because inner has too few elements
572572+ TestCase {
573573+ hex: "80",
574574+ expected: Expected::Err(
575575+ |err| matches!(err, DecodeError::Msg(ref m) if m == "invalid length 0, expected tuple struct Inner with 2 elements"),
576576+ ),
577577+ },
578578+ ];
579579+580580+ let tuple_overflow_cases = [
581581+ // [[1,2],3] -> expected layout
582582+ TestCase {
583583+ hex: "8282010203",
584584+ expected: Expected::Ok(TupleIntOuterWithOverflow {
585585+ inner: TupleIntInner { a: 1, b: 2 },
586586+ c: 3,
587587+ }),
588588+ },
589589+ // [[1],2] -> error because inner has too few elements
590590+ TestCase {
591591+ hex: "82820102",
592592+ expected: Expected::Err(|err| matches!(err, DecodeError::Eof)),
593593+ },
594594+ // [[1,2,3],4] -> error because inner has too many elements
595595+ TestCase {
596596+ hex: "828301020304",
597597+ expected: Expected::Err(
598598+ |err| matches!(err, DecodeError::RequireLength{ name, expect, value} if *name == "TupleIntInner" && *expect == 2 && *value == 3),
599599+ ),
600600+ },
601601+ // [[1,2]] + 3 -> error because there's a trailing element
602602+ TestCase {
603603+ hex: "8182010203",
604604+ expected: Expected::Err(|err| matches!(err, DecodeError::TrailingData)),
605605+ },
606606+ // [[1,2,3]] -> error because outer has too few elements
607607+ TestCase {
608608+ hex: "8183010203",
609609+ expected: Expected::Err(
610610+ |err| matches!(err, DecodeError::RequireLength{ name, expect, value} if *name == "TupleIntInner" && *expect == 2 && *value == 3),
611611+ ),
612612+ },
613613+ ];
614614+615615+ let map_overflow_cases = [
616616+ // {"inner":{"a":1,"b":2},"c":3} -> expected layout
617617+ TestCase {
618618+ hex: "a261630365696e6e6572a2616101616202",
619619+ expected: Expected::Ok(MapIntOuterWithOverflow {
620620+ inner: MapIntInner { a: 1, b: 2 },
621621+ c: 3,
622622+ }),
623623+ },
624624+ // {"inner":{"a":1},"c":3} -> error because inner has too few elements
625625+ TestCase {
626626+ hex: "a261630365696e6e6572a1616101",
627627+ expected: Expected::Err(
628628+ |err| matches!(err, DecodeError::Msg(ref m) if m == "missing field `b`"),
629629+ ),
630630+ },
631631+ // {"inner":{"a":1,"b":2,"c":3},"c":4} -> error because inner has too many elements
632632+ TestCase {
633633+ hex: "a261630465696e6e6572a3616101616202616303",
634634+ expected: Expected::Err(
635635+ |err| matches!(err, DecodeError::Msg(ref m) if m == "unknown field `c`, expected `a` or `b`"),
636636+ ),
637637+ },
638638+ // {"inner":{"a":1,"b":2}} + "c":3 -> error because there's a trailing element
639639+ TestCase {
640640+ hex: "a165696e6e6572a2616101616202616303",
641641+ expected: Expected::Err(|err| matches!(err, DecodeError::TrailingData)),
642642+ },
643643+ // {"inner":{"a":1,"b":2,"c":3}} -> error because outer has too few elements
644644+ TestCase {
645645+ hex: "a165696e6e6572a3616101616202616303",
646646+ expected: Expected::Err(
647647+ |err| matches!(err, DecodeError::Msg(ref m) if m == "unknown field `c`, expected `a` or `b`"),
648648+ ),
649649+ },
650650+ ];
651651+652652+ check_cases(&basic_cases);
653653+ check_cases(&outer_cases);
654654+ check_cases(&outer_defaultable_cases);
655655+ check_cases(&tuple_overflow_cases);
656656+ check_cases(&map_overflow_cases);
657657+658658+ fn check_cases<T>(test_cases: &[TestCase<T>])
659659+ where
660660+ T: serde::de::DeserializeOwned + std::fmt::Debug + PartialEq,
661661+ {
662662+ for case in test_cases {
663663+ let input = const_hex::decode(case.hex).unwrap();
664664+ let result = from_slice::<T>(&input);
665665+ match case.expected {
666666+ Expected::Ok(ref expected_val) => match result {
667667+ Ok(val) => assert_eq!(val, *expected_val, "for input {}", case.hex),
668668+ Err(err) => panic!(
669669+ "for input {} expected success with {:?} but got error: {:?}",
670670+ case.hex, expected_val, err
671671+ ),
672672+ },
673673+ Expected::Err(check) => match result {
674674+ Ok(val) => panic!(
675675+ "for input {} expected an error but got success with value: {:?}",
676676+ case.hex, val
677677+ ),
678678+ Err(err) => assert!(
679679+ check(&err),
680680+ "for input {} got unexpected error: {:?}",
681681+ case.hex,
682682+ err
683683+ ),
684684+ },
685685+ }
686686+ }
687687+ }
688688+}