sp_core/
hexdisplay.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Wrapper type for byte collections that outputs hex.
19
20/// Simple wrapper to display hex representation of bytes.
21pub struct HexDisplay<'a>(&'a [u8]);
22
23impl<'a> HexDisplay<'a> {
24	/// Create new instance that will display `d` as a hex string when displayed.
25	pub fn from<R: AsBytesRef>(d: &'a R) -> Self {
26		HexDisplay(d.as_bytes_ref())
27	}
28}
29
30impl<'a> core::fmt::Display for HexDisplay<'a> {
31	fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
32		if self.0.len() < 1027 {
33			for byte in self.0 {
34				f.write_fmt(format_args!("{:02x}", byte))?;
35			}
36		} else {
37			for byte in &self.0[0..512] {
38				f.write_fmt(format_args!("{:02x}", byte))?;
39			}
40			f.write_str("...")?;
41			for byte in &self.0[self.0.len() - 512..] {
42				f.write_fmt(format_args!("{:02x}", byte))?;
43			}
44		}
45		Ok(())
46	}
47}
48
49impl<'a> core::fmt::Debug for HexDisplay<'a> {
50	fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
51		for byte in self.0 {
52			f.write_fmt(format_args!("{:02x}", byte))?;
53		}
54		Ok(())
55	}
56}
57
58/// Simple trait to transform various types to `&[u8]`
59pub trait AsBytesRef {
60	/// Transform `self` into `&[u8]`.
61	fn as_bytes_ref(&self) -> &[u8];
62}
63
64impl AsBytesRef for &[u8] {
65	fn as_bytes_ref(&self) -> &[u8] {
66		self
67	}
68}
69
70impl AsBytesRef for [u8] {
71	fn as_bytes_ref(&self) -> &[u8] {
72		self
73	}
74}
75
76impl AsBytesRef for alloc::vec::Vec<u8> {
77	fn as_bytes_ref(&self) -> &[u8] {
78		self
79	}
80}
81
82impl AsBytesRef for sp_storage::StorageKey {
83	fn as_bytes_ref(&self) -> &[u8] {
84		self.as_ref()
85	}
86}
87
88macro_rules! impl_non_endians {
89	( $( $t:ty ),* ) => { $(
90		impl AsBytesRef for $t {
91			fn as_bytes_ref(&self) -> &[u8] { &self[..] }
92		}
93	)* }
94}
95
96impl_non_endians!(
97	[u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12],
98	[u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], [u8; 48], [u8; 56],
99	[u8; 64], [u8; 65], [u8; 80], [u8; 96], [u8; 112], [u8; 128], [u8; 144], [u8; 177]
100);
101
102/// Format into ASCII + # + hex, suitable for storage key preimages.
103#[cfg(feature = "std")]
104pub fn ascii_format(asciish: &[u8]) -> String {
105	let mut r = String::new();
106	let mut latch = false;
107	for c in asciish {
108		match (latch, *c) {
109			(false, 32..=127) => r.push(*c as char),
110			_ => {
111				if !latch {
112					r.push('#');
113					latch = true;
114				}
115				r.push_str(&format!("{:02x}", *c));
116			},
117		}
118	}
119	r
120}