Skip to content

Commit 635a6ae

Browse files
elichaidr-orlovsky
authored andcommitted
Add to_hex converter and add tests for hex conversion
1 parent 24a9c9c commit 635a6ae

File tree

1 file changed

+50
-3
lines changed

1 file changed

+50
-3
lines changed

src/lib.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ pub use secp256k1_sys as ffi;
137137
#[cfg(all(test, target_arch = "wasm32"))] extern crate wasm_bindgen_test;
138138
#[cfg(feature = "alloc")] extern crate alloc;
139139

140-
use core::{fmt, ptr, str};
141140

142141
#[macro_use]
143142
mod macros;
@@ -156,7 +155,7 @@ pub use key::PublicKey;
156155
pub use context::*;
157156
use core::marker::PhantomData;
158157
use core::ops::Deref;
159-
use core::mem;
158+
use core::{mem, fmt, ptr, str};
160159
use ffi::{CPtr, types::AlignedType};
161160

162161
#[cfg(feature = "global-context-less-secure")]
@@ -851,6 +850,28 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
851850
Ok(idx / 2)
852851
}
853852

853+
/// Utility function used to encode hex into a target u8 buffer. Returns
854+
/// a reference to the target buffer as an str.
855+
// it returns an error if the target buffer isn't big enough
856+
#[inline]
857+
fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
858+
let hex_len = src.len() * 2;
859+
if target.len() < hex_len {
860+
return Err(());
861+
}
862+
const HEX_TABLE: [u8; 16] = *b"0123456789abcdef";
863+
864+
let mut i = 0;
865+
for &b in src {
866+
target[i] = HEX_TABLE[usize::from(b >> 4)];
867+
target[i+1] = HEX_TABLE[usize::from(b & 0b00001111)];
868+
i +=2 ;
869+
}
870+
let result = &target[..hex_len];
871+
debug_assert!(str::from_utf8(result).is_ok());
872+
return unsafe { Ok(str::from_utf8_unchecked(result)) };
873+
}
874+
854875

855876
#[cfg(test)]
856877
mod tests {
@@ -859,7 +880,7 @@ mod tests {
859880
use std::marker::PhantomData;
860881

861882
use key::{SecretKey, PublicKey};
862-
use super::from_hex;
883+
use super::{from_hex, to_hex};
863884
use super::constants;
864885
use super::{Secp256k1, Signature, Message};
865886
use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature};
@@ -1186,6 +1207,32 @@ mod tests {
11861207
assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok());
11871208
}
11881209

1210+
#[test]
1211+
fn test_hex() {
1212+
let mut rng = thread_rng();
1213+
const AMOUNT: usize = 1024;
1214+
for i in 0..AMOUNT {
1215+
// 255 isn't a valid utf8 character.
1216+
let mut hex_buf = [255u8; AMOUNT*2];
1217+
let mut src_buf = [0u8; AMOUNT];
1218+
let mut result_buf = [0u8; AMOUNT];
1219+
let src = &mut src_buf[0..i];
1220+
rng.fill_bytes(src);
1221+
1222+
let hex = to_hex(src, &mut hex_buf).unwrap();
1223+
assert_eq!(from_hex(hex, &mut result_buf).unwrap(), i);
1224+
assert_eq!(src, &result_buf[..i]);
1225+
}
1226+
1227+
1228+
assert!(to_hex(&[1;2], &mut [0u8; 3]).is_err());
1229+
assert!(to_hex(&[1;2], &mut [0u8; 4]).is_ok());
1230+
assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err());
1231+
assert!(from_hex("deadbeaf", &mut [0u8; 4]).is_ok());
1232+
assert!(from_hex("a", &mut [0u8; 4]).is_err());
1233+
assert!(from_hex("ag", &mut [0u8; 4]).is_err());
1234+
}
1235+
11891236
#[test]
11901237
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
11911238
fn test_low_s() {

0 commit comments

Comments
 (0)