refactor(cipher-core): extract shared block parsing logic

Add generic BlockInt trait and parse_block_int<T>() function to
cipher-core, eliminating duplicate parsing code in aes and des crates.
    - BlockInt trait abstracts over u64/u128 integer types
    - Supports hex (0x), binary (0b), and ASCII string formats
    - Improved BlockError::InvalidByteStringLength with max/actual fields
This commit is contained in:
2025-12-30 23:55:52 +02:00
parent 656e112d9f
commit 451986d702
5 changed files with 120 additions and 112 deletions

View File

@@ -1,5 +1,5 @@
use crate::block::{lr::LR, secret_block};
use cipher_core::{BlockError, InputBlock};
use cipher_core::{parse_block_int, BlockError, InputBlock};
use std::{
slice::{from_raw_parts, from_raw_parts_mut},
str::FromStr,
@@ -48,63 +48,10 @@ impl Block64 {
impl FromStr for Block64 {
type Err = BlockError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(parse_string_to_u64(s)?))
Ok(Self(parse_block_int(s)?))
}
}
fn parse_string_to_u64(s: &str) -> Result<u64, BlockError> {
let trimmed = s.trim();
if trimmed.is_empty() {
return Err(BlockError::EmptyBlock);
}
// Hexadecimal with 0x/0X prefix
if let Some(hex_str) = trimmed
.strip_prefix("0x")
.or_else(|| trimmed.strip_prefix("0X"))
{
return parse_radix(hex_str, 16);
}
// Binary with 0b/0B prefix
if let Some(bin_str) = trimmed
.strip_prefix("0b")
.or_else(|| trimmed.strip_prefix("0B"))
{
return parse_radix(bin_str, 2);
}
ascii_string_to_u64(trimmed)
}
fn parse_radix(s: &str, radix: u32) -> Result<u64, BlockError> {
let trimmed = s.trim_start_matches('0');
if trimmed.is_empty() {
return Ok(0);
}
u64::from_str_radix(trimmed, radix).map_err(BlockError::from)
}
fn ascii_string_to_u64(s: &str) -> Result<u64, BlockError> {
if s.len() > 8 {
return Err(BlockError::InvalidByteStringLength(s.len()));
}
if !s.is_ascii() {
return Err(BlockError::conversion_error(
"u64",
"String contains non-ASCII characters",
));
}
let mut bytes = [0u8; 8];
let offset = 8 - s.len();
bytes[offset..].copy_from_slice(s.as_bytes());
Ok(u64::from_be_bytes(bytes))
}
impl From<[u8; 8]> for Block64 {
fn from(bytes: [u8; 8]) -> Self {
Self::from_be_bytes(bytes)