cid-0.10.1/.cargo_vcs_info.json0000644000000001360000000000100116520ustar { "git": { "sha1": "1df4e3fe0f6bcb8845655d2ccefd9da5ef81a1cd" }, "path_in_vcs": "" }cid-0.10.1/.github/codecov.yml000064400000000000000000000000431046102023000141440ustar 00000000000000coverage: status: patch: off cid-0.10.1/.github/dependabot.yml000064400000000000000000000003161046102023000146320ustar 00000000000000version: 2 updates: - package-ecosystem: "cargo" directory: "/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" cid-0.10.1/.github/workflows/build.yml000064400000000000000000000052751046102023000156720ustar 00000000000000name: build on: [push, pull_request] jobs: build: name: Build strategy: fail-fast: false matrix: platform: [ubuntu-latest, macos-latest, windows-latest] toolchain: [stable] runs-on: ${{ matrix.platform }} steps: - name: Checkout Sources uses: actions/checkout@v3 - name: Cache Dependencies & Build Outputs uses: actions/cache@v3 with: path: ~/.cargo key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install Rust Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true components: rustfmt, clippy - name: Check Code Format uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check - name: Code Lint uses: actions-rs/cargo@v1 with: command: clippy args: --all-targets --all-features -- -D warnings - name: Test uses: actions-rs/cargo@v1 with: command: test args: --all-features build-no-std: name: Build no_std runs-on: ubuntu-latest steps: - name: Checkout Sources uses: actions/checkout@v3 - name: Install Rust Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true target: thumbv6m-none-eabi - name: Build uses: actions-rs/cargo@v1 with: command: build args: --no-default-features --target thumbv6m-none-eabi build-no-std-serde: name: Build no_std, but with `serde-codec` feature enabled runs-on: ubuntu-latest steps: - name: Checkout Sources uses: actions/checkout@v3 - name: Install Rust Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable - name: Build uses: actions-rs/cargo@v1 with: command: build # `thumbv6m-none-eabi` can't be used as Serde doesn't compile there. args: --no-default-features --features serde-codec coverage: name: Code Coverage runs-on: ubuntu-latest steps: - name: Checkout Sources uses: actions/checkout@v3 - name: Install Rust Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - name: Generate Code Coverage uses: actions-rs/tarpaulin@v0.1 with: args: --all-features - name: Upload Code Coverage uses: codecov/codecov-action@v3 cid-0.10.1/.gitignore000064400000000000000000000000351046102023000124300ustar 00000000000000target Cargo.lock *.bk .idea cid-0.10.1/CHANGELOG.md000064400000000000000000000017371046102023000122630ustar 00000000000000# [v0.10.1](https://github.com/multiformats/rust-cid/compare/v0.10.0...v0.10.1) (2023-01-09) ### Bug Fixes * the arb feature needs more multihash features ([#133](https://github.com/multiformats/rust-cid/issues/133)) ([ceca4d9](https://github.com/multiformats/rust-cid/commit/ceca4d93bd90f8ac30987bcc5814f6a655484787)) # [v0.10.0](https://github.com/multiformats/rust-cid/compare/v0.9.0...v0.10.0) (2022-12-22) ### chore * upgrade to Rust edition 2021 and set MSRV ([#130](https://github.com/multiformats/rust-cid/issues/130)) ([91fd35e](https://github.com/multiformats/rust-cid/commit/91fd35e06f8ae24d66f6ba4598830d8dbc259c8a)) ### Features * add `encoded_len` and written bytes ([#129](https://github.com/multiformats/rust-cid/issues/129)) ([715771c](https://github.com/multiformats/rust-cid/commit/715771c48fd47969e733ed1faad8b82d9ddbd7ca)) ### BREAKING CHANGES * Return `Result` (instead of `Result<()>`) now from `Cid::write_bytes`. * Rust edition 2021 is now used cid-0.10.1/Cargo.lock0000644000000362100000000000100076270ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] [[package]] name = "arbitrary" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29d47fbf90d5149a107494b15a7dc8d69b351be2db3bb9691740e88ec17fd880" [[package]] name = "arrayref" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "base-x" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "blake2b_simd" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" dependencies = [ "arrayref", "arrayvec", "constant_time_eq", ] [[package]] name = "blake2s_simd" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" dependencies = [ "arrayref", "arrayvec", "constant_time_eq", ] [[package]] name = "blake3" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] [[package]] name = "byte-slice-cast" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "cc" version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cid" version = "0.10.1" dependencies = [ "arbitrary", "core2", "multibase", "multihash", "parity-scale-codec", "quickcheck", "rand", "serde", "serde_bytes", "serde_json", "unsigned-varint", ] [[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ "memchr", ] [[package]] name = "cpufeatures" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "data-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" [[package]] name = "data-encoding-macro" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca" dependencies = [ "data-encoding", "data-encoding-macro-internal", ] [[package]] name = "data-encoding-macro-internal" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" dependencies = [ "data-encoding", "syn", ] [[package]] name = "digest" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "env_logger" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "log", "regex", ] [[package]] name = "generic-array" version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "impl-trait-for-tuples" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "itoa" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "keccak" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" dependencies = [ "cpufeatures", ] [[package]] name = "libc" version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "multibase" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" dependencies = [ "base-x", "data-encoding", "data-encoding-macro", ] [[package]] name = "multihash" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15e5d911412e631e1de11eb313e4dd71f73fd964401102aab23d6c8327c431ba" dependencies = [ "arbitrary", "blake2b_simd", "blake2s_simd", "blake3", "core2", "digest", "multihash-derive", "parity-scale-codec", "quickcheck", "rand", "serde", "serde-big-array", "sha2", "sha3", "unsigned-varint", ] [[package]] name = "multihash-derive" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "parity-scale-codec" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366e44391a8af4cfd6002ef6ba072bae071a96aafca98d7d448a34c5dca38b6a" dependencies = [ "arrayvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", ] [[package]] name = "parity-scale-codec-derive" version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", ] [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn", "version_check", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check", ] [[package]] name = "proc-macro2" version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "quickcheck" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger", "log", "rand", ] [[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "regex" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde-big-array" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4" dependencies = [ "serde", ] [[package]] name = "serde_bytes" version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "sha2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha3" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" dependencies = [ "digest", "keccak", ] [[package]] name = "syn" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "synstructure" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", "syn", "unicode-xid", ] [[package]] name = "thiserror" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "toml" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsigned-varint" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" cid-0.10.1/Cargo.toml0000644000000042010000000000100076450ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60" name = "cid" version = "0.10.1" authors = ["Friedel Ziegelmayer "] description = "CID in rust" homepage = "https://github.com/multiformats/rust-cid" readme = "README.md" keywords = [ "ipld", "ipfs", "cid", "multihash", "multiformats", ] license = "MIT" [dependencies.arbitrary] version = "1.1.0" optional = true [dependencies.core2] version = "0.4" default-features = false [dependencies.multibase] version = "0.9.1" optional = true default-features = false [dependencies.multihash] version = "0.18.0" default-features = false [dependencies.parity-scale-codec] version = "3.0.0" features = ["derive"] optional = true default-features = false [dependencies.quickcheck] version = "1.0" optional = true [dependencies.rand] version = "0.8.5" features = ["small_rng"] optional = true [dependencies.serde] version = "1.0.116" optional = true default-features = false [dependencies.serde_bytes] version = "0.11.5" optional = true [dependencies.unsigned-varint] version = "0.7.0" default-features = false [dev-dependencies.serde_json] version = "1.0.59" [features] alloc = [ "multibase", "multihash/alloc", "core2/alloc", "serde/alloc", ] arb = [ "quickcheck", "rand", "multihash/arb", "multihash/multihash-impl", "multihash/sha2", "arbitrary", ] default = [ "std", "multihash/default", ] scale-codec = [ "parity-scale-codec", "multihash/scale-codec", ] serde-codec = [ "alloc", "serde", "multihash/serde-codec", "serde_bytes", ] std = [ "multihash/std", "unsigned-varint/std", "alloc", "multibase/std", "serde/std", ] cid-0.10.1/Cargo.toml.orig000064400000000000000000000027361046102023000133410ustar 00000000000000[package] name = "cid" version = "0.10.1" description = "CID in rust" homepage = "https://github.com/multiformats/rust-cid" authors = ["Friedel Ziegelmayer "] keywords = ["ipld", "ipfs", "cid", "multihash", "multiformats"] license = "MIT" readme = "README.md" edition = "2021" rust-version = "1.60" [features] default = ["std", "multihash/default"] std = ["multihash/std", "unsigned-varint/std", "alloc", "multibase/std", "serde/std"] alloc = ["multibase", "multihash/alloc", "core2/alloc", "serde/alloc"] arb = ["quickcheck", "rand", "multihash/arb", "multihash/multihash-impl", "multihash/sha2", "arbitrary"] scale-codec = ["parity-scale-codec", "multihash/scale-codec"] serde-codec = ["alloc", "serde", "multihash/serde-codec", "serde_bytes"] [dependencies] multihash = { version = "0.18.0", default-features = false } unsigned-varint = { version = "0.7.0", default-features = false } multibase = { version = "0.9.1", optional = true, default-features = false } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"], optional = true } quickcheck = { version = "1.0", optional = true } rand = { version = "0.8.5", optional = true, features = ["small_rng"]} serde = { version = "1.0.116", default-features = false, optional = true } serde_bytes = { version = "0.11.5", optional = true } arbitrary = { version = "1.1.0", optional = true } core2 = { version = "0.4", default-features = false } [dev-dependencies] serde_json = "1.0.59" cid-0.10.1/README.md000064400000000000000000000055641046102023000117330ustar 00000000000000# rust-cid [![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io) [![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) [![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) [![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) [![Build Status](https://github.com/multiformats/rust-cid/workflows/build/badge.svg)](https://github.com/multiformats/rust-cid/actions) [![Crates.io](https://img.shields.io/crates/v/cid?style=flat-square)](https://crates.io/crates/cid) [![License](https://img.shields.io/crates/l/cid?style=flat-square)](LICENSE) [![Documentation](https://docs.rs/cid/badge.svg?style=flat-square)](https://docs.rs/cid) [![Dependency Status](https://deps.rs/repo/github/multiformats/rust-cid/status.svg)](https://deps.rs/repo/github/multiformats/rust-cid) [![Coverage Status](https://img.shields.io/codecov/c/github/multiformats/rust-cid?style=flat-square)](https://codecov.io/gh/multiformats/rust-cid) > [CID](https://github.com/ipld/cid) implementation in Rust. ## Table of Contents - [Usage](#usage) - [Testing](#testing) - [Maintainers](#maintainers) - [Contribute](#contribute) - [License](#license) ## Usage ```rust use cid::multihash::{Code, MultihashDigest}; use cid::Cid; use std::convert::TryFrom; const RAW: u64 = 0x55; fn main() { let h = Code::Sha2_256.digest(b"beep boop"); let cid = Cid::new_v1(RAW, h); let data = cid.to_bytes(); let out = Cid::try_from(data).unwrap(); assert_eq!(cid, out); let cid_string = cid.to_string(); assert_eq!( cid_string, "bafkreieq5jui4j25lacwomsqgjeswwl3y5zcdrresptwgmfylxo2depppq" ); println!("{}", cid_string); } ``` Your `Cargo.toml` needs these dependencies: ```toml [dependencies] cid = "0.7.0" ``` You can also run this example from this checkout with `cargo run --example readme`. ## Testing You can run the tests using this command: `cargo test --all-features` ## Maintainers Captain: [@dignifiedquire](https://github.com/dignifiedquire). ## Contribute Contributions welcome. Please check out [the issues](https://github.com/multiformats/rust-cid/issues). Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. ## License [MIT](LICENSE) © 2017 Friedel Ziegelmayer cid-0.10.1/RELEASE.md000064400000000000000000000020511046102023000120420ustar 00000000000000Release process =============== Generating Changelog -------------------- Install dependencies ```sh $ npm install -g conventional-changelog-cli $ cd rust-cid $ conventional-changelog --preset angular ``` Add the output of that to `CHANGELOG.md`, and write a human-centric summary of changes. Update the linked output to reference the new version, which conventional-changelog doesn't know about: ```md # [](https://github.com/multiformats/rust-cid/compare/v0.9.0...v) (2022-12-22) ``` becomes: ```md # [v0.10.0](https://github.com/multiformats/rust-cid/compare/v0.9.0...v0.10.0) (2022-12-22) ``` ## Publishing Publishing on crates.io, bumping version & generating tags is done using [`cargo-release`](https://github.com/crate-ci/cargo-release). This requires the following permissions - on github.com/multiformats/rust-cid - creating tags - pushing to `master` - on crates.io - publish access to all published crates Dry run ```sh $ cargo release ``` Actual publishing ```sh $ cargo release --execute ``` cid-0.10.1/examples/readme.rs000064400000000000000000000007611046102023000140670ustar 00000000000000use cid::multihash::{Code, MultihashDigest}; use cid::Cid; use std::convert::TryFrom; const RAW: u64 = 0x55; fn main() { let h = Code::Sha2_256.digest(b"beep boop"); let cid = Cid::new_v1(RAW, h); let data = cid.to_bytes(); let out = Cid::try_from(data).unwrap(); assert_eq!(cid, out); let cid_string = cid.to_string(); assert_eq!( cid_string, "bafkreieq5jui4j25lacwomsqgjeswwl3y5zcdrresptwgmfylxo2depppq" ); println!("{}", cid_string); } cid-0.10.1/src/arb.rs000064400000000000000000000100031046102023000123350ustar 00000000000000#![cfg(feature = "arb")] use std::convert::TryFrom; use multihash::{Code, MultihashDigest, MultihashGeneric}; use quickcheck::Gen; use rand::{ distributions::{weighted::WeightedIndex, Distribution}, Rng, }; use arbitrary::{size_hint, Unstructured}; use rand::SeedableRng; use crate::{CidGeneric, Version}; impl quickcheck::Arbitrary for Version { fn arbitrary(g: &mut Gen) -> Self { let version = u64::from(bool::arbitrary(g)); Version::try_from(version).unwrap() } } impl quickcheck::Arbitrary for CidGeneric { fn arbitrary(g: &mut Gen) -> Self { if S >= 32 && Version::arbitrary(g) == Version::V0 { let data: Vec = Vec::arbitrary(g); let hash = Code::Sha2_256 .digest(&data) .resize() .expect("digest too large"); CidGeneric::new_v0(hash).expect("sha2_256 is a valid hash for cid v0") } else { // In real world lower IPLD Codec codes more likely to happen, hence distribute them // with bias towards smaller values. let weights = [128, 32, 4, 4, 2, 2, 1, 1]; let dist = WeightedIndex::new(weights.iter()).unwrap(); let mut rng = rand::rngs::SmallRng::seed_from_u64(u64::arbitrary(g)); let codec = match dist.sample(&mut rng) { 0 => rng.gen_range(0..u64::pow(2, 7)), 1 => rng.gen_range(u64::pow(2, 7)..u64::pow(2, 14)), 2 => rng.gen_range(u64::pow(2, 14)..u64::pow(2, 21)), 3 => rng.gen_range(u64::pow(2, 21)..u64::pow(2, 28)), 4 => rng.gen_range(u64::pow(2, 28)..u64::pow(2, 35)), 5 => rng.gen_range(u64::pow(2, 35)..u64::pow(2, 42)), 6 => rng.gen_range(u64::pow(2, 42)..u64::pow(2, 49)), 7 => rng.gen_range(u64::pow(2, 56)..u64::pow(2, 63)), _ => unreachable!(), }; let hash: MultihashGeneric = quickcheck::Arbitrary::arbitrary(g); CidGeneric::new_v1(codec, hash) } } } impl<'a, const S: usize> arbitrary::Arbitrary<'a> for CidGeneric { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { if S >= 32 && u.ratio(1, 10)? { let mh = MultihashGeneric::wrap(Code::Sha2_256.into(), u.bytes(32)?).unwrap(); return Ok(CidGeneric::new_v0(mh).expect("32 bytes is correct for v0")); } let mut codec = 0u64; let mut len_choice = u.arbitrary::()? | 1; while len_choice & 1 == 1 { len_choice >>= 1; let x = u.arbitrary::(); let next = codec .checked_shl(8) .zip(x.ok()) .map(|(next, x)| next.saturating_add(x as u64)); match next { None => break, Some(next) => codec = next, } } Ok(CidGeneric::new_v1(codec, u.arbitrary()?)) } fn size_hint(depth: usize) -> (usize, Option) { let v1 = size_hint::and_all(&[ <[u8; 2]>::size_hint(depth), (0, Some(8)), as arbitrary::Arbitrary>::size_hint(depth), ]); if S >= 32 { size_hint::and(::size_hint(depth), size_hint::or((32, Some(32)), v1)) } else { v1 } } } #[cfg(test)] mod tests { use crate::CidGeneric; use arbitrary::{Arbitrary, Unstructured}; use multihash::MultihashGeneric; #[test] fn arbitrary() { let mut u = Unstructured::new(&[ 1, 22, 41, 13, 5, 6, 7, 8, 9, 6, 10, 243, 43, 231, 123, 43, 153, 127, 67, 76, 24, 91, 23, 32, 32, 23, 65, 98, 193, 108, 3, ]); let c = as Arbitrary>::arbitrary(&mut u).unwrap(); let c2 = CidGeneric::<16>::new_v1(22, MultihashGeneric::wrap(13, &[6, 7, 8, 9, 6]).unwrap()); assert_eq!(c.hash(), c2.hash()); assert_eq!(c.codec(), c2.codec()); assert_eq!(c, c2) } } cid-0.10.1/src/cid.rs000064400000000000000000000301431046102023000123370ustar 00000000000000//! This module contains the main CID type. //! //! If you are an application developer you likely won't use the `Cid` which is generic over the //! digest size. Intead you would use the concrete top-level `Cid` type. //! //! As a library author that works with CIDs that should support hashes of anysize, you would //! import the `Cid` type from this module. use core::convert::TryFrom; #[cfg(feature = "alloc")] use multibase::{encode as base_encode, Base}; use multihash::MultihashGeneric as Multihash; use unsigned_varint::encode as varint_encode; #[cfg(feature = "alloc")] extern crate alloc; #[cfg(feature = "alloc")] use alloc::{ borrow, string::{String, ToString}, vec::Vec, }; #[cfg(feature = "std")] pub(crate) use unsigned_varint::io::read_u64 as varint_read_u64; /// Reads 64 bits from a byte array into a u64 /// Adapted from unsigned-varint's generated read_u64 function at /// https://github.com/paritytech/unsigned-varint/blob/master/src/io.rs #[cfg(not(feature = "std"))] pub(crate) fn varint_read_u64(mut r: R) -> Result { use unsigned_varint::decode; let mut b = varint_encode::u64_buffer(); for i in 0..b.len() { let n = r.read(&mut (b[i..i + 1]))?; if n == 0 { return Err(Error::VarIntDecodeError); } else if decode::is_last(b[i]) { return Ok(decode::u64(&b[..=i]).unwrap().0); } } Err(Error::VarIntDecodeError) } #[cfg(feature = "std")] use std::io; #[cfg(not(feature = "std"))] use core2::io; use crate::error::{Error, Result}; use crate::version::Version; /// DAG-PB multicodec code const DAG_PB: u64 = 0x70; /// The SHA_256 multicodec code const SHA2_256: u64 = 0x12; /// Representation of a CID. /// /// The generic is about the allocated size of the multihash. #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "scale-codec", derive(parity_scale_codec::Decode))] #[cfg_attr(feature = "scale-codec", derive(parity_scale_codec::Encode))] pub struct Cid { /// The version of CID. version: Version, /// The codec of CID. codec: u64, /// The multihash of CID. hash: Multihash, } impl Cid { /// Create a new CIDv0. pub const fn new_v0(hash: Multihash) -> Result { if hash.code() != SHA2_256 || hash.size() != 32 { return Err(Error::InvalidCidV0Multihash); } Ok(Self { version: Version::V0, codec: DAG_PB, hash, }) } /// Create a new CIDv1. pub const fn new_v1(codec: u64, hash: Multihash) -> Self { Self { version: Version::V1, codec, hash, } } /// Create a new CID. pub const fn new(version: Version, codec: u64, hash: Multihash) -> Result { match version { Version::V0 => { if codec != DAG_PB { return Err(Error::InvalidCidV0Codec); } Self::new_v0(hash) } Version::V1 => Ok(Self::new_v1(codec, hash)), } } /// Convert a CIDv0 to a CIDv1. Returns unchanged if already a CIDv1. pub fn into_v1(self) -> Result { match self.version { Version::V0 => { if self.codec != DAG_PB { return Err(Error::InvalidCidV0Codec); } Ok(Self::new_v1(self.codec, self.hash)) } Version::V1 => Ok(self), } } /// Returns the cid version. pub const fn version(&self) -> Version { self.version } /// Returns the cid codec. pub const fn codec(&self) -> u64 { self.codec } /// Returns the cid multihash. pub const fn hash(&self) -> &Multihash { &self.hash } /// Reads the bytes from a byte stream. pub fn read_bytes(mut r: R) -> Result { let version = varint_read_u64(&mut r)?; let codec = varint_read_u64(&mut r)?; // CIDv0 has the fixed `0x12 0x20` prefix if [version, codec] == [0x12, 0x20] { let mut digest = [0u8; 32]; r.read_exact(&mut digest)?; let mh = Multihash::wrap(version, &digest).expect("Digest is always 32 bytes."); return Self::new_v0(mh); } let version = Version::try_from(version)?; match version { Version::V0 => Err(Error::InvalidExplicitCidV0), Version::V1 => { let mh = Multihash::read(r)?; Self::new(version, codec, mh) } } } fn write_bytes_v1(&self, mut w: W) -> Result { let mut version_buf = varint_encode::u64_buffer(); let version = varint_encode::u64(self.version.into(), &mut version_buf); let mut codec_buf = varint_encode::u64_buffer(); let codec = varint_encode::u64(self.codec, &mut codec_buf); let mut written = version.len() + codec.len(); w.write_all(version)?; w.write_all(codec)?; written += self.hash.write(&mut w)?; Ok(written) } /// Writes the bytes to a byte stream, returns the number of bytes written. pub fn write_bytes(&self, w: W) -> Result { let written = match self.version { Version::V0 => self.hash.write(w)?, Version::V1 => self.write_bytes_v1(w)?, }; Ok(written) } /// Returns the length in bytes needed to encode this cid into bytes. pub fn encoded_len(&self) -> usize { match self.version { Version::V0 => self.hash.encoded_len(), Version::V1 => { let mut version_buf = varint_encode::u64_buffer(); let version = varint_encode::u64(self.version.into(), &mut version_buf); let mut codec_buf = varint_encode::u64_buffer(); let codec = varint_encode::u64(self.codec, &mut codec_buf); version.len() + codec.len() + self.hash.encoded_len() } } } /// Returns the encoded bytes of the `Cid`. #[cfg(feature = "alloc")] pub fn to_bytes(&self) -> Vec { let mut bytes = Vec::new(); let written = self.write_bytes(&mut bytes).unwrap(); debug_assert_eq!(written, bytes.len()); bytes } #[cfg(feature = "alloc")] #[allow(clippy::wrong_self_convention)] fn to_string_v0(&self) -> String { Base::Base58Btc.encode(self.hash.to_bytes()) } #[cfg(feature = "alloc")] #[allow(clippy::wrong_self_convention)] fn to_string_v1(&self) -> String { multibase::encode(Base::Base32Lower, self.to_bytes().as_slice()) } /// Convert CID into a multibase encoded string /// /// # Example /// /// ``` /// use cid::Cid; /// use multibase::Base; /// use multihash::{Code, MultihashDigest}; /// /// const RAW: u64 = 0x55; /// /// let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo")); /// let encoded = cid.to_string_of_base(Base::Base64).unwrap(); /// assert_eq!(encoded, "mAVUSICwmtGto/8aP+ZtFPB0wQTQTQi1wZIO/oPmKXohiZueu"); /// ``` #[cfg(feature = "alloc")] pub fn to_string_of_base(&self, base: Base) -> Result { match self.version { Version::V0 => { if base == Base::Base58Btc { Ok(self.to_string_v0()) } else { Err(Error::InvalidCidV0Base) } } Version::V1 => Ok(base_encode(base, self.to_bytes())), } } } impl Default for Cid { fn default() -> Self { Self { version: Version::V1, codec: 0, hash: Multihash::::default(), } } } // TODO: remove the dependency on alloc by fixing // https://github.com/multiformats/rust-multibase/issues/33 #[cfg(feature = "alloc")] impl core::fmt::Display for Cid { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { let output = match self.version { Version::V0 => self.to_string_v0(), Version::V1 => self.to_string_v1(), }; write!(f, "{}", output) } } #[cfg(feature = "alloc")] impl core::fmt::Debug for Cid { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if f.alternate() { f.debug_struct("Cid") .field("version", &self.version()) .field("codec", &self.codec()) .field("hash", self.hash()) .finish() } else { let output = match self.version { Version::V0 => self.to_string_v0(), Version::V1 => self.to_string_v1(), }; write!(f, "Cid({})", output) } } } #[cfg(feature = "alloc")] impl core::str::FromStr for Cid { type Err = Error; fn from_str(cid_str: &str) -> Result { Self::try_from(cid_str) } } #[cfg(feature = "alloc")] impl TryFrom for Cid { type Error = Error; fn try_from(cid_str: String) -> Result { Self::try_from(cid_str.as_str()) } } #[cfg(feature = "alloc")] impl TryFrom<&str> for Cid { type Error = Error; fn try_from(cid_str: &str) -> Result { static IPFS_DELIMETER: &str = "/ipfs/"; let hash = match cid_str.find(IPFS_DELIMETER) { Some(index) => &cid_str[index + IPFS_DELIMETER.len()..], _ => cid_str, }; if hash.len() < 2 { return Err(Error::InputTooShort); } let decoded = if Version::is_v0_str(hash) { Base::Base58Btc.decode(hash)? } else { let (_, decoded) = multibase::decode(hash)?; decoded }; Self::try_from(decoded) } } #[cfg(feature = "alloc")] impl TryFrom> for Cid { type Error = Error; fn try_from(bytes: Vec) -> Result { Self::try_from(bytes.as_slice()) } } impl TryFrom<&[u8]> for Cid { type Error = Error; fn try_from(mut bytes: &[u8]) -> Result { Self::read_bytes(&mut bytes) } } impl From<&Cid> for Cid { fn from(cid: &Cid) -> Self { *cid } } #[cfg(feature = "alloc")] impl From> for Vec { fn from(cid: Cid) -> Self { cid.to_bytes() } } #[cfg(feature = "alloc")] impl From> for String { fn from(cid: Cid) -> Self { cid.to_string() } } #[cfg(feature = "alloc")] impl<'a, const S: usize> From> for borrow::Cow<'a, Cid> { fn from(from: Cid) -> Self { borrow::Cow::Owned(from) } } #[cfg(feature = "alloc")] impl<'a, const S: usize> From<&'a Cid> for borrow::Cow<'a, Cid> { fn from(from: &'a Cid) -> Self { borrow::Cow::Borrowed(from) } } #[cfg(test)] mod tests { #[test] #[cfg(feature = "scale-codec")] fn test_cid_scale_codec() { use super::Cid; use parity_scale_codec::{Decode, Encode}; let cid = Cid::<64>::default(); let bytes = cid.encode(); let cid2 = Cid::decode(&mut &bytes[..]).unwrap(); assert_eq!(cid, cid2); } #[test] #[cfg(feature = "std")] fn test_debug_instance() { use super::Cid; use std::str::FromStr; let cid = Cid::<64>::from_str("bafyreibjo4xmgaevkgud7mbifn3dzp4v4lyaui4yvqp3f2bqwtxcjrdqg4") .unwrap(); // short debug assert_eq!( &format!("{:?}", cid), "Cid(bafyreibjo4xmgaevkgud7mbifn3dzp4v4lyaui4yvqp3f2bqwtxcjrdqg4)" ); // verbose debug let mut txt = format!("{:#?}", cid); txt.retain(|c| !c.is_whitespace()); assert_eq!(&txt, "Cid{version:V1,codec:113,hash:Multihash{code:18,size:32,digest:[41,119,46,195,0,149,81,168,63,176,40,43,118,60,191,149,226,240,10,35,152,172,31,178,232,48,180,238,36,196,112,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],},}"); } } cid-0.10.1/src/error.rs000064400000000000000000000047211046102023000127340ustar 00000000000000use core::fmt; #[cfg(feature = "std")] use std::io; #[cfg(not(feature = "std"))] use core2::io; /// Type alias to use this library's [`Error`] type in a `Result`. pub type Result = core::result::Result; /// Error types #[derive(Debug)] pub enum Error { /// Unknown CID codec. UnknownCodec, /// Input data is too short. InputTooShort, /// Multibase or multihash codec failure ParsingError, /// Invalid CID version. InvalidCidVersion, /// Invalid CIDv0 codec. InvalidCidV0Codec, /// Invalid CIDv0 multihash. InvalidCidV0Multihash, /// Invalid CIDv0 base encoding. InvalidCidV0Base, /// Varint decode failure. VarIntDecodeError, /// Io error. Io(io::Error), /// Invalid explicit CIDv0. InvalidExplicitCidV0, } #[cfg(feature = "std")] impl std::error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Error::*; let error = match self { UnknownCodec => "Unknown codec", InputTooShort => "Input too short", ParsingError => "Failed to parse multihash", InvalidCidVersion => "Unrecognized CID version", InvalidCidV0Codec => "CIDv0 requires a DagPB codec", InvalidCidV0Multihash => "CIDv0 requires a Sha-256 multihash", InvalidCidV0Base => "CIDv0 requires a Base58 base", VarIntDecodeError => "Failed to decode unsigned varint format", Io(err) => return write!(f, "{}", err), InvalidExplicitCidV0 => "CIDv0 cannot be specified in CIDv1 format", }; f.write_str(error) } } #[cfg(feature = "alloc")] impl From for Error { fn from(_: multibase::Error) -> Error { Error::ParsingError } } impl From for Error { fn from(_: multihash::Error) -> Error { Error::ParsingError } } impl From for Error { fn from(_: unsigned_varint::decode::Error) -> Self { Error::VarIntDecodeError } } #[cfg(feature = "std")] impl From for Error { fn from(err: unsigned_varint::io::ReadError) -> Self { use unsigned_varint::io::ReadError::*; match err { Io(err) => Self::Io(err), _ => Self::VarIntDecodeError, } } } impl From for Error { fn from(err: io::Error) -> Self { Self::Io(err) } } cid-0.10.1/src/lib.rs000064400000000000000000000013161046102023000123460ustar 00000000000000//! # cid //! //! Implementation of [cid](https://github.com/ipld/cid) in Rust. #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] mod cid; mod error; mod version; #[cfg(any(test, feature = "arb"))] mod arb; #[cfg(feature = "serde-codec")] pub mod serde; pub use self::cid::Cid as CidGeneric; pub use self::error::{Error, Result}; pub use self::version::Version; #[cfg(feature = "alloc")] pub use multibase; pub use multihash; /// A Cid that contains a multihash with an allocated size of 512 bits. /// /// This is the same digest size the default multihash code table has. /// /// If you need a CID that is generic over its digest size, use [`CidGeneric`] instead. pub type Cid = CidGeneric<64>; cid-0.10.1/src/serde.rs000064400000000000000000000101721046102023000127020ustar 00000000000000//! CID Serde (de)serialization for the IPLD Data Model. //! //! CIDs cannot directly be represented in any of the native Serde Data model types. In order to //! work around that limitation. a newtype struct is introduced, that is used as a marker for Serde //! (de)serialization. extern crate alloc; use alloc::{format, vec::Vec}; use core::convert::TryFrom; use core::fmt; use serde::{de, ser}; use serde_bytes::ByteBuf; use crate::CidGeneric; /// An identifier that is used internally by Serde implementations that support [`Cid`]s. pub const CID_SERDE_PRIVATE_IDENTIFIER: &str = "$__private__serde__identifier__for__cid"; /// Serialize a CID into the Serde data model as enum. /// /// Custom types are not supported by Serde, hence we map a CID into an enum that can be identified /// as a CID by implementations that support CIDs. The corresponding Rust type would be: /// /// ```text /// struct $__private__serde__identifier__for__cid(serde_bytes::BytesBuf); /// ``` impl ser::Serialize for CidGeneric { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer, { let value = ByteBuf::from(self.to_bytes()); serializer.serialize_newtype_struct(CID_SERDE_PRIVATE_IDENTIFIER, &value) } } /// Visitor to transform bytes into a CID. pub struct BytesToCidVisitor; impl<'de, const SIZE: usize> de::Visitor<'de> for BytesToCidVisitor { type Value = CidGeneric; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "a valid CID in bytes") } fn visit_bytes(self, value: &[u8]) -> Result where E: de::Error, { CidGeneric::::try_from(value) .map_err(|err| de::Error::custom(format!("Failed to deserialize CID: {}", err))) } /// Some Serde data formats interpret a byte stream as a sequence of bytes (e.g. `serde_json`). fn visit_seq(self, mut seq: A) -> Result where A: de::SeqAccess<'de>, { let mut bytes = Vec::new(); while let Some(byte) = seq.next_element()? { bytes.push(byte); } CidGeneric::::try_from(bytes) .map_err(|err| de::Error::custom(format!("Failed to deserialize CID: {}", err))) } } /// Deserialize a CID into a newtype struct. /// /// Deserialize a CID that was serialized as a newtype struct, so that can be identified as a CID. /// Its corresponding Rust type would be: /// /// ```text /// struct $__private__serde__identifier__for__cid(serde_bytes::BytesBuf); /// ``` impl<'de, const SIZE: usize> de::Deserialize<'de> for CidGeneric { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { /// Main visitor to deserialize a CID. /// /// This visitor has only a single entry point to deserialize CIDs, it's /// `visit_new_type_struct()`. This ensures that it isn't accidentally used to decode CIDs /// to bytes. struct MainEntryVisitor; impl<'de, const SIZE: usize> de::Visitor<'de> for MainEntryVisitor { type Value = CidGeneric; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "a valid CID in bytes, wrapped in an newtype struct") } fn visit_newtype_struct(self, deserializer: D) -> Result where D: de::Deserializer<'de>, { deserializer.deserialize_bytes(BytesToCidVisitor) } } deserializer.deserialize_newtype_struct(CID_SERDE_PRIVATE_IDENTIFIER, MainEntryVisitor) } } #[cfg(test)] mod tests { use crate::CidGeneric; #[test] fn test_cid_serde() { let cid = CidGeneric::<70>::try_from( "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", ) .unwrap(); let bytes = serde_json::to_string(&cid).unwrap(); let cid2 = serde_json::from_str(&bytes).unwrap(); assert_eq!(cid, cid2); } } cid-0.10.1/src/version.rs000064400000000000000000000025011046102023000132620ustar 00000000000000use core::convert::TryFrom; use crate::error::{Error, Result}; /// The version of the CID. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)] #[cfg_attr(feature = "scale-codec", derive(parity_scale_codec::Decode))] #[cfg_attr(feature = "scale-codec", derive(parity_scale_codec::Encode))] pub enum Version { /// CID version 0. V0, /// CID version 1. V1, } impl Version { /// Check if the version of `data` string is CIDv0. pub fn is_v0_str(data: &str) -> bool { // v0 is a Base58Btc encoded sha hash, so it has // fixed length and always begins with "Qm" data.len() == 46 && data.starts_with("Qm") } /// Check if the version of `data` bytes is CIDv0. pub fn is_v0_binary(data: &[u8]) -> bool { data.len() == 34 && data.starts_with(&[0x12, 0x20]) } } /// Convert a number to the matching version, or `Error` if no valid version is matching. impl TryFrom for Version { type Error = Error; fn try_from(raw: u64) -> Result { match raw { 0 => Ok(Self::V0), 1 => Ok(Self::V1), _ => Err(Error::InvalidCidVersion), } } } impl From for u64 { fn from(ver: Version) -> u64 { match ver { Version::V0 => 0, Version::V1 => 1, } } } cid-0.10.1/tests/lib.rs000064400000000000000000000132661046102023000127300ustar 00000000000000use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; use std::str::FromStr; use cid::{Cid, CidGeneric, Error, Version}; use multibase::Base; use multihash::{derive::Multihash, Code, MultihashDigest}; const RAW: u64 = 0x55; const DAG_PB: u64 = 0x70; #[test] fn basic_marshalling() { let h = Code::Sha2_256.digest(b"beep boop"); let cid = Cid::new_v1(DAG_PB, h); let data = cid.to_bytes(); let out = Cid::try_from(data.clone()).unwrap(); assert_eq!(cid, out); let out2 = data.try_into().unwrap(); assert_eq!(cid, out2); let s = cid.to_string(); let out3 = Cid::try_from(&s[..]).unwrap(); assert_eq!(cid, out3); let out4 = (&s[..]).try_into().unwrap(); assert_eq!(cid, out4); } #[test] fn empty_string() { assert!(matches!(Cid::try_from(""), Err(Error::InputTooShort))) } #[test] fn v0_handling() { let old = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"; let cid = Cid::try_from(old).unwrap(); assert_eq!(cid.version(), Version::V0); assert_eq!(cid.to_string(), old); } #[test] fn from_str() { let cid: Cid = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n" .parse() .unwrap(); assert_eq!(cid.version(), Version::V0); let bad = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zIII".parse::(); assert!(matches!(bad, Err(Error::ParsingError))); } #[test] fn v0_error() { let bad = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zIII"; assert!(matches!(Cid::try_from(bad), Err(Error::ParsingError))); } #[test] fn from() { let the_hash = "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n"; let cases = vec![ format!("/ipfs/{:}", &the_hash), format!("https://ipfs.io/ipfs/{:}", &the_hash), format!("http://localhost:8080/ipfs/{:}", &the_hash), ]; for case in cases { let cid = Cid::try_from(case).unwrap(); assert_eq!(cid.version(), Version::V0); assert_eq!(cid.to_string(), the_hash); } } #[test] fn test_hash() { let data: Vec = vec![1, 2, 3]; let hash = Code::Sha2_256.digest(&data); let mut map = HashMap::new(); let cid = Cid::new_v0(hash).unwrap(); map.insert(cid, data.clone()); assert_eq!(&data, map.get(&cid).unwrap()); } #[test] fn test_base32() { let cid = Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap(); assert_eq!(cid.version(), Version::V1); assert_eq!(cid.codec(), RAW); assert_eq!(cid.hash(), &Code::Sha2_256.digest(b"foo")); } #[test] fn to_string() { let expected_cid = "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy"; let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo")); assert_eq!(cid.to_string(), expected_cid); } #[test] fn to_string_of_base32() { let expected_cid = "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy"; let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo")); assert_eq!( cid.to_string_of_base(Base::Base32Lower).unwrap(), expected_cid ); } #[test] fn to_string_of_base64() { let expected_cid = "mAVUSICwmtGto/8aP+ZtFPB0wQTQTQi1wZIO/oPmKXohiZueu"; let cid = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo")); assert_eq!(cid.to_string_of_base(Base::Base64).unwrap(), expected_cid); } #[test] fn to_string_of_base58_v0() { let expected_cid = "QmRJzsvyCQyizr73Gmms8ZRtvNxmgqumxc2KUp71dfEmoj"; let cid = Cid::new_v0(Code::Sha2_256.digest(b"foo")).unwrap(); assert_eq!( cid.to_string_of_base(Base::Base58Btc).unwrap(), expected_cid ); } #[test] fn to_string_of_base_v0_error() { let cid = Cid::new_v0(Code::Sha2_256.digest(b"foo")).unwrap(); assert!(matches!( cid.to_string_of_base(Base::Base16Upper), Err(Error::InvalidCidV0Base) )); } #[test] fn explicit_v0_is_disallowed() { use std::io::Cursor; assert!(matches!( Cid::read_bytes(Cursor::new([ 0x00, 0x70, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12 ])), Err(Error::InvalidExplicitCidV0) )); } #[test] fn new_v0_accepts_only_32_bytes() { use multihash::Multihash; const SHA2_256: u64 = 0x12; for i in 1..64 { if i == 32 { continue; } assert!(matches!( Cid::new_v0(Multihash::wrap(SHA2_256, &vec![7; i]).unwrap()), Err(Error::InvalidCidV0Multihash) )); } } fn a_function_that_takes_a_generic_cid(cid: &CidGeneric) -> String { cid.to_string() } // This test is about having something implemented that used the default size of `Cid`. So the code // is using `Cid` instead of `Cid`. The code will still work with other sizes. #[test] fn method_can_take_differently_sized_cids() { #[derive(Clone, Copy, Debug, Eq, PartialEq, Multihash)] #[mh(alloc_size = 128)] enum Code128 { #[mh(code = 0x12, hasher = multihash::Sha2_256)] Sha2_256, } let cid_default = Cid::new_v1(RAW, Code::Sha2_256.digest(b"foo")); let cid_128 = CidGeneric::<128>::new_v1(RAW, Code128::Sha2_256.digest(b"foo")); assert_eq!( a_function_that_takes_a_generic_cid(&cid_default), a_function_that_takes_a_generic_cid(&cid_128) ); } #[test] fn test_into_v1() { let cid = Cid::from_str("QmTPcW343HGMdoxarwvHHoPhkbo5GfNYjnZkyW5DBtpvLe").unwrap(); let cid_v1 = cid.into_v1().unwrap(); assert_eq!(cid_v1.version(), Version::V1); assert_eq!( cid_v1.to_string(), "bafybeiclbsxcvqpfliqcejqz5ghpvw4r7vktjkyk3ruvjvdmam5azct2v4" ); let cid = Cid::from_str("bafyreibjo4xmgaevkgud7mbifn3dzp4v4lyaui4yvqp3f2bqwtxcjrdqg4").unwrap(); let cid_v1 = cid.into_v1().unwrap(); assert_eq!(cid_v1.version(), Version::V1); assert_eq!(cid_v1, cid); }