array_bytes/
lib.rs

1#![deny(clippy::all, missing_docs, unused_crate_dependencies)]
2#![allow(clippy::items_after_test_module, clippy::tabs_in_doc_comments)]
3#![no_std]
4
5//! A collection of Array/Bytes/Hex utilities with full No-STD compatibility.
6//!
7//! Completely optimized for blockchain development.
8//! Especially the Polkadot-SDK.
9//!
10//! # Usage
11//! Here are a few quick examples of the most commonly used operations: hexifying and dehexifying.
12//!
13//! However, this crate also offers many other utilities for Array/Bytes/Hex, each with comprehensive documentation and examples. Check them out on [docs.rs](https://docs.rs/array-bytes)!
14//!
15//! ```rust
16//! use array_bytes::{Dehexify, Error, Hexify};
17//! use smallvec::SmallVec;
18//!
19//! // Hexify.
20//! // Unsigned.
21//! assert_eq!(52_u8.hexify(), "34");
22//! assert_eq!(520_u16.hexify_upper(), "208");
23//! assert_eq!(5_201_314_u32.hexify_prefixed(), "0x4f5da2");
24//! assert_eq!(5_201_314_u64.hexify_prefixed_upper(), "0x4F5DA2");
25//! assert_eq!(5_201_314_u128.hexify(), "4f5da2");
26//! assert_eq!(5_201_314_usize.hexify_upper(), "4F5DA2");
27//! // `[u8; N]`.
28//! assert_eq!(*b"Love Jane Forever".hexify(), String::from("4c6f7665204a616e6520466f7265766572"));
29//! // `&[u8; N]`.
30//! assert_eq!(
31//! 	b"Love Jane Forever".hexify_upper(),
32//! 	String::from("4C6F7665204A616E6520466F7265766572")
33//! );
34//! // `&[u8]`.
35//! assert_eq!(
36//! 	b"Love Jane Forever".as_slice().hexify_prefixed(),
37//! 	String::from("0x4c6f7665204a616e6520466f7265766572")
38//! );
39//! // `Vec<u8>`.
40//! assert_eq!(
41//! 	b"Love Jane Forever".to_vec().hexify_prefixed_upper(),
42//! 	String::from("0x4C6F7665204A616E6520466F7265766572")
43//! );
44//! // `&Vec<u8>`.
45//! assert_eq!(
46//! 	(&b"Love Jane Forever".to_vec()).hexify(),
47//! 	String::from("4c6f7665204a616e6520466f7265766572")
48//! );
49//! // Dehexify.
50//! // Unsigned.
51//! assert_eq!(u8::dehexify("34"), Ok(52));
52//! assert_eq!(u16::dehexify("208"), Ok(520));
53//! assert_eq!(u32::dehexify("0x4f5da2"), Ok(5_201_314));
54//! assert_eq!(u64::dehexify("0x4F5DA2"), Ok(5_201_314));
55//! assert_eq!(u128::dehexify("4f5da2"), Ok(5_201_314));
56//! assert_eq!(usize::dehexify("4F5DA2"), Ok(5_201_314));
57//! // Array.
58//! assert_eq!(
59//! 	<[u8; 17]>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
60//! 	Ok(*b"Love Jane Forever")
61//! );
62//! // SmallVec.
63//! assert_eq!(
64//! 	SmallVec::dehexify("0x4c6f7665204a616e6520466f7265766572").unwrap().into_vec(),
65//! 	b"Love Jane Forever".to_vec()
66//! );
67//! assert_eq!(SmallVec::dehexify("我爱你"), Err(Error::InvalidLength));
68//! assert_eq!(SmallVec::dehexify("0x我爱你"), Err(Error::InvalidLength));
69//! // Vec.
70//! assert_eq!(
71//! 	<Vec<u8>>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
72//! 	Ok(b"Love Jane Forever".to_vec())
73//! );
74//! assert_eq!(
75//! 	<Vec<u8>>::dehexify("我爱你 "),
76//! 	Err(Error::InvalidCharacter { character: 'æ', index: 0 })
77//! );
78//! assert_eq!(
79//! 	<Vec<u8>>::dehexify(" 我爱你"),
80//! 	Err(Error::InvalidCharacter { character: ' ', index: 0 })
81//! );
82//! ```
83
84extern crate alloc;
85
86mod hex;
87pub use hex::*;
88
89mod op;
90pub use op::*;
91
92#[cfg(feature = "serde")] mod serde;
93#[cfg(feature = "serde")] pub use serde::*;
94
95mod prelude {
96	pub use alloc::{string::String, vec::Vec};
97
98	pub use smallvec::SmallVec;
99
100	pub use crate::{Error, Result};
101
102	pub(crate) use crate::op;
103
104	#[cfg(test)]
105	mod test {
106		// Suppress `unused_crate_dependencies` error.
107		use const_hex as _;
108		use criterion as _;
109		use faster_hex as _;
110		use hex_crate as _;
111		use rustc_hex as _;
112		use serde as _;
113		use serde_json as _;
114
115		// self
116		use super::*;
117
118		#[derive(Debug, PartialEq)]
119		pub struct Ljf(pub Vec<u8>);
120		impl From<Vec<u8>> for Ljf {
121			fn from(bytes: Vec<u8>) -> Self {
122				Self(bytes)
123			}
124		}
125
126		#[derive(Debug, PartialEq)]
127		pub struct Ljfn(pub [u8; 17]);
128		impl From<[u8; 17]> for Ljfn {
129			fn from(array: [u8; 17]) -> Self {
130				Self(array)
131			}
132		}
133	}
134	#[cfg(test)] pub use test::*;
135}
136
137#[cfg(feature = "serde")] pub use serde_bytes;
138
139#[allow(missing_docs)]
140pub type Result<T, E = Error> = core::result::Result<T, E>;
141
142#[allow(missing_docs)]
143#[derive(Debug, PartialEq, Eq)]
144pub enum Error {
145	/// The length must not be odd.
146	InvalidLength,
147	/// Found the invalid character at `index`.
148	InvalidCharacter {
149		/// The invalid character.
150		character: char,
151		/// The invalid character's index.
152		index: usize,
153	},
154	/// The data can not fit the array/slice length well.
155	MismatchedLength {
156		/// Expected length.
157		expect: usize,
158	},
159	/// Failed to parse the hex number from hex string.
160	Utf8Error(core::str::Utf8Error),
161	/// Failed to parse the hex number from hex string.
162	ParseIntError(core::num::ParseIntError),
163}