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}