1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::fmt::Write;
use std::num::ParseIntError;
/// A simple trait allowing something to be converted into a hex
/// string.
pub trait ToHexString {
fn to_hex_string(&self) -> String;
}
/// A simple trait allowing something to be converted from a hex
/// string.
pub trait FromHexString {
type Error;
fn from_hex_string(&self) -> Result<Vec<u8>, Self::Error>;
}
/// A default implementation for byte slices.
impl ToHexString for [u8] {
fn to_hex_string(&self) -> String {
let size = 2 + (2 * self.len());
let mut hexstr = String::with_capacity(size);
// Prepend "0x"
write!(hexstr, "0x").unwrap();
// Write each byte
for b in self {
write!(hexstr, "{:02x}", b).unwrap();
}
// Done
hexstr
}
}
/// A default implementation for string slices
impl FromHexString for str {
type Error = ParseIntError;
//
fn from_hex_string(&self) -> Result<Vec<u8>, Self::Error> {
let mut bytes: Vec<u8> = Vec::new();
// Remove prepended "0x" (only if present)
let slice = if self.len() > 2 && &self[0..2] == "0x" {
&self[2..]
} else {
&self
};
// Parse contents of string
for i in (0..slice.len()).step_by(2) {
// Pull out the byte
let byte = u8::from_str_radix(&slice[i..i + 2], 16)?;
// Push it!
bytes.push(byte);
}
//
Ok(bytes)
}
}