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, Hexify, Error};
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!(b"Love Jane Forever".hexify_upper(), String::from("4C6F7665204A616E6520466F7265766572"));
31//! // `&[u8]`.
32//! assert_eq!(
33//! 	b"Love Jane Forever".as_slice().hexify_prefixed(),
34//! 	String::from("0x4c6f7665204a616e6520466f7265766572")
35//! );
36//! // `Vec<u8>`.
37//! assert_eq!(
38//! 	b"Love Jane Forever".to_vec().hexify_prefixed_upper(),
39//! 	String::from("0x4C6F7665204A616E6520466F7265766572")
40//! );
41//! // `&Vec<u8>`.
42//! assert_eq!(
43//! 	(&b"Love Jane Forever".to_vec()).hexify(),
44//! 	String::from("4c6f7665204a616e6520466f7265766572")
45//! );
46//! // Dehexify.
47//! // Unsigned.
48//! assert_eq!(u8::dehexify("34"), Ok(52));
49//! assert_eq!(u16::dehexify("208"), Ok(520));
50//! assert_eq!(u32::dehexify("0x4f5da2"), Ok(5_201_314));
51//! assert_eq!(u64::dehexify("0x4F5DA2"), Ok(5_201_314));
52//! assert_eq!(u128::dehexify("4f5da2"), Ok(5_201_314));
53//! assert_eq!(usize::dehexify("4F5DA2"), Ok(5_201_314));
54//! // Array.
55//! assert_eq!(<[u8; 17]>::dehexify("0x4c6f7665204a616e6520466f7265766572"), Ok(*b"Love Jane Forever"));
56//! // SmallVec.
57//! assert_eq!(
58//! 	SmallVec::dehexify("0x4c6f7665204a616e6520466f7265766572").unwrap().into_vec(),
59//! 	b"Love Jane Forever".to_vec()
60//! );
61//! assert_eq!(SmallVec::dehexify("我爱你"), Err(Error::InvalidLength));
62//! assert_eq!(SmallVec::dehexify("0x我爱你"), Err(Error::InvalidLength));
63//! // Vec.
64//! assert_eq!(
65//! 	<Vec<u8>>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
66//! 	Ok(b"Love Jane Forever".to_vec())
67//! );
68//! assert_eq!(
69//! 	<Vec<u8>>::dehexify("我爱你 "),
70//! 	Err(Error::InvalidCharacter { character: 'æ', index: 0 })
71//! );
72//! assert_eq!(
73//! 	<Vec<u8>>::dehexify(" 我爱你"),
74//! 	Err(Error::InvalidCharacter { character: ' ', index: 0 })
75//! );
76//! ```
77
78extern crate alloc;
79
80mod hex;
81pub use hex::*;
82
83mod op;
84pub use op::*;
85
86#[cfg(feature = "serde")] mod serde;
87#[cfg(feature = "serde")] pub use serde::*;
88
89mod prelude {
90	pub use alloc::{string::String, vec::Vec};
91
92	pub use smallvec::SmallVec;
93
94	pub use crate::{Error, Result};
95
96	pub(crate) use crate::op;
97
98	#[cfg(test)]
99	mod test {
100		// Suppress `unused_crate_dependencies` error.
101		use const_hex as _;
102		use criterion as _;
103		use faster_hex as _;
104		use hex_crate as _;
105		use rustc_hex as _;
106		use serde as _;
107		use serde_json as _;
108
109		// self
110		use super::*;
111
112		#[derive(Debug, PartialEq)]
113		pub struct Ljf(pub Vec<u8>);
114		impl From<Vec<u8>> for Ljf {
115			fn from(bytes: Vec<u8>) -> Self {
116				Self(bytes)
117			}
118		}
119
120		#[derive(Debug, PartialEq)]
121		pub struct Ljfn(pub [u8; 17]);
122		impl From<[u8; 17]> for Ljfn {
123			fn from(array: [u8; 17]) -> Self {
124				Self(array)
125			}
126		}
127	}
128	#[cfg(test)] pub use test::*;
129}
130
131#[cfg(feature = "serde")] pub use serde_bytes;
132
133#[allow(missing_docs)]
134pub type Result<T, E = Error> = core::result::Result<T, E>;
135
136#[allow(missing_docs)]
137#[derive(Debug, PartialEq, Eq)]
138pub enum Error {
139	/// The length must not be odd.
140	InvalidLength,
141	/// Found the invalid character at `index`.
142	InvalidCharacter {
143		/// The invalid character.
144		character: char,
145		/// The invalid character's index.
146		index: usize,
147	},
148	/// The data can not fit the array/slice length well.
149	MismatchedLength {
150		/// Expected length.
151		expect: usize,
152	},
153	/// Failed to parse the hex number from hex string.
154	Utf8Error(core::str::Utf8Error),
155	/// Failed to parse the hex number from hex string.
156	ParseIntError(core::num::ParseIntError),
157}