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}