1
0
Fork 0
forked from wry/wry

opaque: increase size to 192 bits

This commit is contained in:
Julian Orth 2026-04-02 15:54:22 +02:00
parent 5680de7d8c
commit 0a5b00f269
2 changed files with 39 additions and 15 deletions

View file

@ -1,4 +1,5 @@
use { use {
crate::utils::array,
arrayvec::ArrayString, arrayvec::ArrayString,
rand::{RngExt, rng}, rand::{RngExt, rng},
serde::{Deserialize, Deserializer, Serialize, Serializer, de}, serde::{Deserialize, Deserializer, Serialize, Serializer, de},
@ -10,17 +11,19 @@ use {
thiserror::Error, thiserror::Error,
}; };
#[cfg(test)]
mod tests;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct Opaque { pub struct Opaque {
lo: u64, v: [u64; 3],
hi: u64,
} }
pub fn opaque() -> Opaque { pub fn opaque() -> Opaque {
let mut rng = rng(); let mut rng = rng();
Opaque { Opaque {
lo: rng.random(), v: array::from_fn(|_| rng.random()),
hi: rng.random(),
} }
} }
@ -35,8 +38,9 @@ impl Opaque {
impl Display for Opaque { impl Display for Opaque {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:016x}", self.hi)?; write!(f, "{:016x}", self.v[2])?;
write!(f, "{:016x}", self.lo)?; write!(f, "{:016x}", self.v[1])?;
write!(f, "{:016x}", self.v[0])?;
Ok(()) Ok(())
} }
} }
@ -72,24 +76,32 @@ impl FromStr for Opaque {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() != OPAQUE_LEN { if s.len() != OPAQUE_LEN {
return Err(OpaqueError::InvalidLength); return Err(OpaqueError::InvalidStringLength);
} }
if !s.is_char_boundary(OPAQUE_LEN / 2) { if !s.is_char_boundary(OPAQUE_SEGMENT) {
return Err(OpaqueError::NotAscii); return Err(OpaqueError::NotAscii);
} }
let (hi, lo) = s.split_at(OPAQUE_LEN / 2); let (a, s) = s.split_at(OPAQUE_SEGMENT);
let hi = u64::from_str_radix(hi, 16).map_err(OpaqueError::Parse)?; if !s.is_char_boundary(OPAQUE_SEGMENT) {
let lo = u64::from_str_radix(lo, 16).map_err(OpaqueError::Parse)?; return Err(OpaqueError::NotAscii);
Ok(Self { lo, hi }) }
let (b, c) = s.split_at(OPAQUE_SEGMENT);
let v = [
u64::from_str_radix(c, 16).map_err(OpaqueError::Parse)?,
u64::from_str_radix(b, 16).map_err(OpaqueError::Parse)?,
u64::from_str_radix(a, 16).map_err(OpaqueError::Parse)?,
];
Ok(Self { v })
} }
} }
pub const OPAQUE_LEN: usize = 32; pub const OPAQUE_LEN: usize = 48;
const OPAQUE_SEGMENT: usize = OPAQUE_LEN / 3;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum OpaqueError { pub enum OpaqueError {
#[error("The string is not exactly 32 bytes long")] #[error("The string is not exactly {OPAQUE_LEN} bytes long")]
InvalidLength, InvalidStringLength,
#[error("The string is not ascii")] #[error("The string is not ascii")]
NotAscii, NotAscii,
#[error("Could not parse the string as a hex number")] #[error("Could not parse the string as a hex number")]

12
src/utils/opaque/tests.rs Normal file
View file

@ -0,0 +1,12 @@
use {
crate::utils::opaque::{Opaque, opaque},
std::str::FromStr,
};
#[test]
fn roundtrip() {
let v1 = opaque();
let s = v1.to_string();
let v2 = Opaque::from_str(&s).unwrap();
assert_eq!(v1, v2);
}