multibase-0.9.1/.cargo/config.toml010064400017500001750000000000431375123515700152100ustar 00000000000000[unstable] features = ["host_dep"] multibase-0.9.1/.cargo_vcs_info.json0000644000000001121375124017500130650ustar { "git": { "sha1": "3c36b28e0072de4b5302bfceedc318aec5c125b0" } } multibase-0.9.1/.github/workflows/build.yml010064400017500001750000000035611375123515700171240ustar 00000000000000on: [push, pull_request] name: build jobs: build: name: Lints and Test strategy: matrix: platform: [ubuntu-latest, macos-latest, windows-latest] toolchain: [stable] runs-on: ${{ matrix.platform }} steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true components: rustfmt, clippy - name: Run cargo fmt uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check - name: Run cargo clippy uses: actions-rs/cargo@v1 with: command: clippy args: --all --all-targets -- -D warnings - name: Run cargo test uses: actions-rs/cargo@v1 with: command: test ensure_no_std: name: Ensure no_std runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: nightly override: true - name: Install thumbv6m-none-eabi run: rustup target add thumbv6m-none-eabi - name: Build thumbv6m-none-eabi run: cargo build --target thumbv6m-none-eabi --no-default-features coverage: name: Code Coverage runs-on: ubuntu-latest steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install stable Rust toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable override: true - name: Run cargo-tarpaulin uses: actions-rs/tarpaulin@v0.1 with: args: '-- --test-threads 1' - name: Upload to codecov.io uses: codecov/codecov-action@v1.0.6 multibase-0.9.1/.gitignore010064400017500001750000000000261362344705000136610ustar 00000000000000target Cargo.lock *.bkmultibase-0.9.1/Cargo.toml0000644000000024301375124017500110700ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "multibase" version = "0.9.1" authors = ["Friedel Ziegelmayer "] description = "multibase in rust" homepage = "https://github.com/multiformats/rust-multibase" readme = "README.md" keywords = ["ipld", "ipfs", "multihash", "cid", "no_std"] license = "MIT" repository = "https://github.com/multiformats/rust-multibase" [[bench]] name = "multibase" harness = false [dependencies.base-x] version = "0.2.7" default-features = false [dependencies.data-encoding] version = "2.3.1" features = ["alloc"] default-features = false [dependencies.data-encoding-macro] version = "0.1.9" [dev-dependencies.criterion] version = "0.3" [dev-dependencies.rand] version = "0.7" [features] default = ["std"] std = ["data-encoding/std"] multibase-0.9.1/Cargo.toml.orig010064400017500001750000000013571375124017400145700ustar 00000000000000[package] name = "multibase" version = "0.9.1" authors = ["Friedel Ziegelmayer "] edition = "2018" license = "MIT" readme = "README.md" description = "multibase in rust" homepage = "https://github.com/multiformats/rust-multibase" repository = "https://github.com/multiformats/rust-multibase" keywords = ["ipld", "ipfs", "multihash", "cid", "no_std"] [features] default = ["std"] std = ["data-encoding/std"] [dependencies] base-x = { version = "0.2.7", default-features = false } data-encoding = { version = "2.3.1", default-features = false, features = ["alloc"] } data-encoding-macro = "0.1.9" [dev-dependencies] criterion = "0.3" rand = "0.7" [[bench]] name = "multibase" harness = false [workspace] members = ["cli"] multibase-0.9.1/README.md010064400017500001750000000060271375123515700131640ustar 00000000000000# rust-multibase [![](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-multibase/workflows/build/badge.svg)](https://github.com/multiformats/rust-multibase/actions) [![License](https://img.shields.io/crates/l/multibase?style=flat-square)](LICENSE) [![Crates.io](https://img.shields.io/crates/v/multibase?style=flat-square)](https://crates.io/crates/multibase) [![Documentation](https://docs.rs/multibase/badge.svg?style=flat-square)](https://docs.rs/multibase) [![Dependency Status](https://deps.rs/repo/github/multiformats/rust-multibase/status.svg)](https://deps.rs/repo/github/multiformats/rust-multibase) [![Coverage Status]( https://img.shields.io/codecov/c/github/multiformats/rust-multibase?style=flat-square)](https://codecov.io/gh/multiformats/rust-multibase) > [multibase](https://github.com/multiformats/multibase) implementation in Rust. ## Table of Contents - [Install](#install) - [Usage](#usage) - [Maintainers](#maintainers) - [Contribute](#contribute) - [License](#license) ## Install First add this to your `Cargo.toml` ```toml [dependencies] multibase = "0.9" ``` For `no_std` ``` [dependencies] multibase = { version ="0.9", default-features = false } ``` **note**: This crate relies on the [currently unstable](https://github.com/rust-lang/cargo/issues/7915) `host_dep` feature to [compile proc macros with the proper dependencies](https://docs.rs/data-encoding-macro/0.1.10/data_encoding_macro/), thus **requiring nightly rustc** to use. Then run `cargo build`. ## Usage ```rust use multibase::Base; let base64 = multibase::encode(Base::Base64, b"hello world"); let (base, data) = multibase::decode(base64); ``` **Note**: `base32` and `base64` are orders of magnitude faster due to byte alignment. Don't be surprised if using a different base turns into a performance bottleneck. You were warned! ## Maintainers Captain: [@dignifiedquire](https://github.com/dignifiedquire). ## Contribute Contributions welcome. Please check out [the issues](https://github.com/multiformats/rust-multibase/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 multibase-0.9.1/benches/multibase.rs010064400017500001750000000042601362477030700156440ustar 00000000000000use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rand::Rng; use multibase::{decode, encode, Base}; fn bench_encode(c: &mut Criterion) { let mut rng = rand::thread_rng(); let data: Vec = (0..1024).map(|_| rng.gen()).collect(); let mut group = c.benchmark_group("encode"); group.bench_function("base32", |b| { b.iter(|| { let _ = black_box(encode(Base::Base32Upper, &data)); }) }); group.bench_function("base58btc", |b| { b.iter(|| { let _ = black_box(encode(Base::Base58Btc, &data)); }) }); group.bench_function("base64", |b| { b.iter(|| { let _ = black_box(encode(Base::Base64, &data)); }) }); group.finish(); } fn bench_decode(c: &mut Criterion) { let mut rng = rand::thread_rng(); let data: Vec = (0..1024).map(|_| rng.gen()).collect(); let base32 = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; let base58 = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; let base64 = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; let mut base32_data = data .iter() .map(|i| base32[i % 31] as char) .collect::(); base32_data.insert(0, Base::Base32Upper.code()); let mut base58_data = data .iter() .map(|i| base58[i % 57] as char) .collect::(); base58_data.insert(0, Base::Base58Btc.code()); let mut base64_data = data .iter() .map(|i| base64[i % 64] as char) .collect::(); base64_data.insert(0, Base::Base64.code()); let mut group = c.benchmark_group("decode"); group.bench_function("base32", |b| { b.iter(|| { let _ = black_box(decode(&base32_data).unwrap()); }) }); group.bench_function("base58btc", |b| { b.iter(|| { let _ = black_box(decode(&base58_data).unwrap()); }) }); group.bench_function("base64", |b| { b.iter(|| { let _ = black_box(decode(&base64_data).unwrap()); }) }); group.finish(); } criterion_group!(benches, bench_encode, bench_decode); criterion_main!(benches); multibase-0.9.1/src/base.rs010064400017500001750000000076441375123515700137620ustar 00000000000000use crate::error::{Error, Result}; use crate::impls::*; #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; macro_rules! build_base_enum { ( $(#[$attr:meta] $code:expr => $base:ident,)* ) => { /// List of types currently supported in the multibase spec. /// /// Not all base types are supported by this library. #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum Base { $( #[$attr] $base, )* } impl Base { /// Convert a number to the matching base algorithm, or `Error` if no algorithm is matching. pub fn from_code(code: char) -> Result { match code { $( $code => Ok(Self::$base), )* _ => Err(Error::UnknownBase(code)), } } /// Get the code corresponding to the base algorithm. pub fn code(&self) -> char { match self { $( Self::$base => $code, )* } } /// Encode the given byte slice to base string. pub fn encode>(&self, input: I) -> String { match self { $( Self::$base => $base::encode(input), )* } } /// Decode the base string. pub fn decode>(&self, input: I) -> Result> { match self { $( Self::$base => $base::decode(input), )* } } } } } build_base_enum! { /// 8-bit binary (encoder and decoder keeps data unmodified). '\x00' => Identity, /// Base2 (alphabet: 01). '0' => Base2, /// Base8 (alphabet: 01234567). '7' => Base8, /// Base10 (alphabet: 0123456789). '9' => Base10, /// Base16 lower hexadecimal (alphabet: 0123456789abcdef). 'f' => Base16Lower, /// Base16 upper hexadecimal (alphabet: 0123456789ABCDEF). 'F' => Base16Upper, /// Base32, rfc4648 no padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). 'b' => Base32Lower, /// Base32, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). 'B' => Base32Upper, /// Base32, rfc4648 with padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). 'c' => Base32PadLower, /// Base32, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). 'C' => Base32PadUpper, /// Base32hex, rfc4648 no padding (alphabet: 0123456789abcdefghijklmnopqrstuv). 'v' => Base32HexLower, /// Base32hex, rfc4648 no padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). 'V' => Base32HexUpper, /// Base32hex, rfc4648 with padding (alphabet: 0123456789abcdefghijklmnopqrstuv). 't' => Base32HexPadLower, /// Base32hex, rfc4648 with padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). 'T' => Base32HexPadUpper, /// z-base-32 (used by Tahoe-LAFS) (alphabet: ybndrfg8ejkmcpqxot1uwisza345h769). 'h' => Base32Z, /// Base36, [0-9a-z] no padding (alphabet: 0123456789abcdefghijklmnopqrstuvwxyz). 'k' => Base36Lower, /// Base36, [0-9A-Z] no padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ). 'K' => Base36Upper, /// Base58 flicker (alphabet: 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ). 'Z' => Base58Flickr, /// Base58 bitcoin (alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz). 'z' => Base58Btc, /// Base64, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). 'm' => Base64, /// Base64, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). 'M' => Base64Pad, /// Base64 url, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). 'u' => Base64Url, /// Base64 url, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). 'U' => Base64UrlPad, } multibase-0.9.1/src/encoding.rs010064400017500001750000000105411375024105600146160ustar 00000000000000use data_encoding::Encoding; use data_encoding_macro::new_encoding; // Base2 (alphabet: 01) pub const BASE2: Encoding = new_encoding! { symbols: "01", }; // Base8 (alphabet: 01234567) pub const BASE8: Encoding = new_encoding! { symbols: "01234567", }; /// Base10 (alphabet: 0123456789) pub const BASE10: &str = "0123456789"; // Base16 lower hexadecimal (alphabet: 0123456789abcdef) pub const BASE16_LOWER: Encoding = data_encoding::HEXLOWER_PERMISSIVE; // Base16 upper hexadecimal (alphabet: 0123456789ABCDEF). pub const BASE16_UPPER: Encoding = data_encoding::HEXUPPER_PERMISSIVE; // Base32, rfc4648 no padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). pub const BASE32_NOPAD_LOWER: Encoding = new_encoding! { symbols: "abcdefghijklmnopqrstuvwxyz234567", translate_from: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", translate_to: "abcdefghijklmnopqrstuvwxyz", }; // Base32, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). pub const BASE32_NOPAD_UPPER: Encoding = new_encoding! { symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", translate_from: "abcdefghijklmnopqrstuvwxyz", translate_to: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", }; // Base32, rfc4648 with padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). pub const BASE32_PAD_LOWER: Encoding = new_encoding! { symbols: "abcdefghijklmnopqrstuvwxyz234567", translate_from: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", translate_to: "abcdefghijklmnopqrstuvwxyz", padding: '=', }; // Base32, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). pub const BASE32_PAD_UPPER: Encoding = new_encoding! { symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", translate_from: "abcdefghijklmnopqrstuvwxyz", translate_to: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", padding: '=', }; // Base32hex, rfc4648 no padding (alphabet: 0123456789abcdefghijklmnopqrstuv). pub const BASE32HEX_NOPAD_LOWER: Encoding = new_encoding! { symbols: "0123456789abcdefghijklmnopqrstuv", translate_from: "ABCDEFGHIJKLMNOPQRSTUV", translate_to: "abcdefghijklmnopqrstuv", }; // Base32hex, rfc4648 no padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). pub const BASE32HEX_NOPAD_UPPER: Encoding = new_encoding! { symbols: "0123456789ABCDEFGHIJKLMNOPQRSTUV", translate_from: "abcdefghijklmnopqrstuv", translate_to: "ABCDEFGHIJKLMNOPQRSTUV", }; // Base32hex, rfc4648 with padding (alphabet: 0123456789abcdefghijklmnopqrstuv). pub const BASE32HEX_PAD_LOWER: Encoding = new_encoding! { symbols: "0123456789abcdefghijklmnopqrstuv", translate_from: "ABCDEFGHIJKLMNOPQRSTUV", translate_to: "abcdefghijklmnopqrstuv", padding: '=', }; /// Base32hex, rfc4648 with padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). pub const BASE32HEX_PAD_UPPER: Encoding = new_encoding! { symbols: "0123456789ABCDEFGHIJKLMNOPQRSTUV", translate_from: "abcdefghijklmnopqrstuv", translate_to: "ABCDEFGHIJKLMNOPQRSTUV", padding: '=', }; // z-base-32 (used by Tahoe-LAFS) (alphabet: ybndrfg8ejkmcpqxot1uwisza345h769). pub const BASE32Z: Encoding = new_encoding! { symbols: "ybndrfg8ejkmcpqxot1uwisza345h769", }; /// Base36, [0-9a-z] no padding (alphabet: 0123456789abcdefghijklmnopqrstuvwxyz). pub const BASE36_LOWER: &str = "0123456789abcdefghijklmnopqrstuvwxyz"; /// Base36, [0-9A-Z] no padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ). pub const BASE36_UPPER: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Base58 Flickr's alphabet for creating short urls from photo ids. pub const BASE58_FLICKR: &str = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"; // Base58 Bitcoin's alphabet as defined in their Base58Check encoding. pub const BASE58_BITCOIN: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; // Base64, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). pub const BASE64_NOPAD: Encoding = data_encoding::BASE64_NOPAD; // Base64, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). pub const BASE64_PAD: Encoding = data_encoding::BASE64; // Base64 url, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). pub const BASE64URL_NOPAD: Encoding = data_encoding::BASE64URL_NOPAD; // Base64 url, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). pub const BASE64URL_PAD: Encoding = data_encoding::BASE64URL; multibase-0.9.1/src/error.rs010064400017500001750000000016401375123515700141670ustar 00000000000000use core::fmt; /// Type alias to use this library's [`Error`] type in a `Result`. pub type Result = core::result::Result; /// Error types #[derive(PartialEq, Eq, Clone, Debug)] pub enum Error { /// Unknown base code. UnknownBase(char), /// Invalid string. InvalidBaseString, } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Error::UnknownBase(code) => write!(f, "Unknown base code: {}", code), Error::InvalidBaseString => write!(f, "Invalid base string"), } } } #[cfg(feature = "std")] impl std::error::Error for Error {} impl From for Error { fn from(_: base_x::DecodeError) -> Self { Self::InvalidBaseString } } impl From for Error { fn from(_: data_encoding::DecodeError) -> Self { Self::InvalidBaseString } } multibase-0.9.1/src/impls.rs010064400017500001750000000130041375123515700141570ustar 00000000000000use crate::encoding; use crate::error::Result; #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; macro_rules! derive_base_encoding { ( $(#[$doc:meta] $type:ident, $encoding:expr;)* ) => { $( #[$doc] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub(crate) struct $type; impl BaseCodec for $type { fn encode>(input: I) -> String { $encoding.encode(input.as_ref()) } fn decode>(input: I) -> Result> { Ok($encoding.decode(input.as_ref().as_bytes())?) } } )* }; } macro_rules! derive_base_x { ( $(#[$doc:meta] $type:ident, $encoding:expr;)* ) => { $( #[$doc] #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub(crate) struct $type; impl BaseCodec for $type { fn encode>(input: I) -> String { base_x::encode($encoding, input.as_ref()) } fn decode>(input: I) -> Result> { Ok(base_x::decode($encoding, input.as_ref())?) } } )* }; } pub(crate) trait BaseCodec { /// Encode with the given byte slice. fn encode>(input: I) -> String; /// Decode with the given string. fn decode>(input: I) -> Result>; } /// Identity, 8-bit binary (encoder and decoder keeps data unmodified). #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub(crate) struct Identity; impl BaseCodec for Identity { fn encode>(input: I) -> String { String::from_utf8(input.as_ref().to_vec()).expect("input must be valid UTF-8 bytes") } fn decode>(input: I) -> Result> { Ok(input.as_ref().as_bytes().to_vec()) } } derive_base_encoding! { /// Base2 (alphabet: 01). Base2, encoding::BASE2; /// Base8 (alphabet: 01234567). Base8, encoding::BASE8; /// Base16 lower hexadecimal (alphabet: 0123456789abcdef). Base16Lower, encoding::BASE16_LOWER; /// Base16 upper hexadecimal (alphabet: 0123456789ABCDEF). Base16Upper, encoding::BASE16_UPPER; /// Base32, rfc4648 no padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). Base32Lower, encoding::BASE32_NOPAD_LOWER; /// Base32, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). Base32Upper, encoding::BASE32_NOPAD_UPPER; /// Base32, rfc4648 with padding (alphabet: abcdefghijklmnopqrstuvwxyz234567). Base32PadLower, encoding::BASE32_PAD_LOWER; /// Base32, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ234567). Base32PadUpper, encoding::BASE32_PAD_UPPER; /// Base32hex, rfc4648 no padding (alphabet: 0123456789abcdefghijklmnopqrstuv). Base32HexLower, encoding::BASE32HEX_NOPAD_LOWER; /// Base32hex, rfc4648 no padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). Base32HexUpper, encoding::BASE32HEX_NOPAD_UPPER; /// Base32hex, rfc4648 with padding (alphabet: 0123456789abcdefghijklmnopqrstuv). Base32HexPadLower, encoding::BASE32HEX_PAD_LOWER; /// Base32hex, rfc4648 with padding (alphabet: 0123456789ABCDEFGHIJKLMNOPQRSTUV). Base32HexPadUpper, encoding::BASE32HEX_PAD_UPPER; /// z-base-32 (used by Tahoe-LAFS) (alphabet: ybndrfg8ejkmcpqxot1uwisza345h769). Base32Z, encoding::BASE32Z; /// Base64, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). Base64, encoding::BASE64_NOPAD; /// Base64, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/). Base64Pad, encoding::BASE64_PAD; /// Base64 url, rfc4648 no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). Base64Url, encoding::BASE64URL_NOPAD; /// Base64 url, rfc4648 with padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_). Base64UrlPad, encoding::BASE64URL_PAD; } derive_base_x! { /// Base10 (alphabet: 0123456789). Base10, encoding::BASE10; /// Base58 flicker (alphabet: 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ). Base58Flickr, encoding::BASE58_FLICKR; /// Base58 bitcoin (alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz). Base58Btc, encoding::BASE58_BITCOIN; } /// Base36, [0-9a-z] no padding (alphabet: abcdefghijklmnopqrstuvwxyz0123456789). #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub(crate) struct Base36Lower; impl BaseCodec for Base36Lower { fn encode>(input: I) -> String { base_x::encode(encoding::BASE36_LOWER, input.as_ref()) } fn decode>(input: I) -> Result> { // The input is case insensitive, hence lowercase it let lowercased = input.as_ref().to_ascii_lowercase(); Ok(base_x::decode(encoding::BASE36_LOWER, &lowercased)?) } } /// Base36, [0-9A-Z] no padding (alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789). #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub(crate) struct Base36Upper; impl BaseCodec for Base36Upper { fn encode>(input: I) -> String { base_x::encode(encoding::BASE36_UPPER, input.as_ref()) } fn decode>(input: I) -> Result> { // The input is case insensitive, hence uppercase it let uppercased = input.as_ref().to_ascii_uppercase(); Ok(base_x::decode(encoding::BASE36_UPPER, &uppercased)?) } } multibase-0.9.1/src/lib.rs010064400017500001750000000024261375123515700136070ustar 00000000000000//! # multibase //! //! Implementation of [multibase](https://github.com/multiformats/multibase) in Rust. #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; mod base; mod encoding; mod error; mod impls; pub use self::base::Base; pub use self::error::{Error, Result}; /// Decode the base string. /// /// # Examples /// /// ``` /// use multibase::{Base, decode}; /// /// assert_eq!( /// decode("zCn8eVZg").unwrap(), /// (Base::Base58Btc, b"hello".to_vec()) /// ); /// ``` pub fn decode>(input: T) -> Result<(Base, Vec)> { let input = input.as_ref(); let code = input.chars().next().ok_or(Error::InvalidBaseString)?; let base = Base::from_code(code)?; let decoded = base.decode(&input[code.len_utf8()..])?; Ok((base, decoded)) } /// Encode with the given byte slice to base string. /// /// # Examples /// /// ``` /// use multibase::{Base, encode}; /// /// assert_eq!(encode(Base::Base58Btc, b"hello"), "zCn8eVZg"); /// ``` pub fn encode>(base: Base, input: T) -> String { let input = input.as_ref(); let mut encoded = base.encode(input.as_ref()); encoded.insert(0, base.code()); encoded } multibase-0.9.1/tests/lib.rs010064400017500001750000000130611374777357700142010ustar 00000000000000use multibase::{decode, encode, Base, Base::*}; fn encode_decode_assert(input: &[u8], test_cases: Vec<(Base, &str)>) { for (base, output) in test_cases { assert_eq!(encode(base, input), output); assert_eq!(decode(output).unwrap(), (base, input.to_vec())); } } #[test] fn test_bases_code() { assert_eq!(Identity.code(), '\x00'); assert_eq!(Base2.code(), '0'); } #[test] fn test_bases_from_code() { assert_eq!(Base::from_code('\x00').unwrap(), Identity); assert_eq!(Base::from_code('0').unwrap(), Base2); } #[test] fn test_round_trip() { let test_cases: &[&str] = &[ "helloworld", "we all want decentralization", "zdj7WfBb6j58iSJuAzDcSZgy2SxFhdpJ4H87uvMpfyN6hRGyH", ]; for case in test_cases { let encoded = encode(Base58Btc, case); let decoded = decode(encoded).unwrap(); assert_eq!(decoded, (Base58Btc, case.as_bytes().to_vec())) } } #[test] fn test_basic() { let input = b"yes mani !"; let test_cases = vec![ (Identity, "\x00yes mani !"), ( Base2, "001111001011001010111001100100000011011010110000101101110011010010010000000100001", ), (Base8, "7362625631006654133464440102"), (Base10, "9573277761329450583662625"), (Base16Lower, "f796573206d616e692021"), (Base16Upper, "F796573206D616E692021"), (Base32Lower, "bpfsxgidnmfxgsibb"), (Base32Upper, "BPFSXGIDNMFXGSIBB"), (Base32HexLower, "vf5in683dc5n6i811"), (Base32HexUpper, "VF5IN683DC5N6I811"), (Base32PadLower, "cpfsxgidnmfxgsibb"), (Base32PadUpper, "CPFSXGIDNMFXGSIBB"), (Base32HexPadLower, "tf5in683dc5n6i811"), (Base32HexPadUpper, "TF5IN683DC5N6I811"), (Base32Z, "hxf1zgedpcfzg1ebb"), (Base36Lower, "k2lcpzo5yikidynfl"), (Base36Upper, "K2LCPZO5YIKIDYNFL"), (Base58Flickr, "Z7Pznk19XTTzBtx"), (Base58Btc, "z7paNL19xttacUY"), (Base64, "meWVzIG1hbmkgIQ"), (Base64Pad, "MeWVzIG1hbmkgIQ=="), (Base64Url, "ueWVzIG1hbmkgIQ"), (Base64UrlPad, "UeWVzIG1hbmkgIQ=="), ]; encode_decode_assert(input, test_cases); } #[test] fn preserves_leading_zero() { let input = b"\x00yes mani !"; let test_cases = vec![ (Identity, "\x00\x00yes mani !"), (Base2, "00000000001111001011001010111001100100000011011010110000101101110011010010010000000100001"), (Base8, "7000745453462015530267151100204"), (Base10, "90573277761329450583662625"), (Base16Lower, "f00796573206d616e692021"), (Base16Upper, "F00796573206D616E692021"), (Base32Lower, "bab4wk4zanvqw42jaee"), (Base32Upper, "BAB4WK4ZANVQW42JAEE"), (Base32HexLower, "v01smasp0dlgmsq9044"), (Base32HexUpper, "V01SMASP0DLGMSQ9044"), (Base32PadLower, "cab4wk4zanvqw42jaee======"), (Base32PadUpper, "CAB4WK4ZANVQW42JAEE======"), (Base32HexPadLower, "t01smasp0dlgmsq9044======"), (Base32HexPadUpper, "T01SMASP0DLGMSQ9044======"), (Base32Z, "hybhskh3ypiosh4jyrr"), (Base36Lower, "k02lcpzo5yikidynfl"), (Base36Upper, "K02LCPZO5YIKIDYNFL"), (Base58Flickr, "Z17Pznk19XTTzBtx"), (Base58Btc, "z17paNL19xttacUY"), (Base64, "mAHllcyBtYW5pICE"), (Base64Pad, "MAHllcyBtYW5pICE="), (Base64Url, "uAHllcyBtYW5pICE"), (Base64UrlPad, "UAHllcyBtYW5pICE="), ]; encode_decode_assert(input, test_cases); } #[test] fn preserves_two_leading_zeroes() { let input = b"\x00\x00yes mani !"; let test_cases = vec![ (Identity, "\x00\x00\x00yes mani !"), (Base2, "0000000000000000001111001011001010111001100100000011011010110000101101110011010010010000000100001"), (Base8, "700000171312714403326055632220041"), (Base10, "900573277761329450583662625"), (Base16Lower, "f0000796573206d616e692021"), (Base16Upper, "F0000796573206D616E692021"), (Base32Lower, "baaahszltebwwc3tjeaqq"), (Base32Upper, "BAAAHSZLTEBWWC3TJEAQQ"), (Base32HexLower, "v0007ipbj41mm2rj940gg"), (Base32HexUpper, "V0007IPBJ41MM2RJ940GG"), (Base32PadLower, "caaahszltebwwc3tjeaqq===="), (Base32PadUpper, "CAAAHSZLTEBWWC3TJEAQQ===="), (Base32HexPadLower, "t0007ipbj41mm2rj940gg===="), (Base32HexPadUpper, "T0007IPBJ41MM2RJ940GG===="), (Base32Z, "hyyy813murbssn5ujryoo"), (Base36Lower, "k002lcpzo5yikidynfl"), (Base36Upper, "K002LCPZO5YIKIDYNFL"), (Base58Flickr, "Z117Pznk19XTTzBtx"), (Base58Btc, "z117paNL19xttacUY"), (Base64, "mAAB5ZXMgbWFuaSAh"), (Base64Pad, "MAAB5ZXMgbWFuaSAh"), (Base64Url, "uAAB5ZXMgbWFuaSAh"), (Base64UrlPad, "UAAB5ZXMgbWFuaSAh"), ]; encode_decode_assert(input, test_cases); } #[test] fn case_insensitivity() { let input = b"hello world"; let test_cases = vec![ (Base16Lower, "f68656c6c6f20776F726C64"), (Base16Upper, "F68656c6c6f20776F726C64"), (Base32Lower, "bnbswy3dpeB3W64TMMQ"), (Base32Upper, "Bnbswy3dpeB3W64TMMQ"), (Base32HexLower, "vd1imor3f41RMUSJCCG"), (Base32HexUpper, "Vd1imor3f41RMUSJCCG"), (Base32PadLower, "cnbswy3dpeB3W64TMMQ======"), (Base32PadUpper, "Cnbswy3dpeB3W64TMMQ======"), (Base32HexPadLower, "td1imor3f41RMUSJCCG======"), (Base32HexPadUpper, "Td1imor3f41RMUSJCCG======"), (Base36Lower, "kfUvrsIvVnfRbjWaJo"), (Base36Upper, "KfUVrSIVVnFRbJWAJo"), ]; for (base, output) in test_cases { assert_eq!(decode(output).unwrap(), (base, input.to_vec())); } }