mirror of
https://github.com/kristoferssolo/cipher-workshop.git
synced 2026-02-04 06:42:11 +00:00
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:
@@ -2,7 +2,7 @@ use crate::{
|
||||
block::{Block32, secret_block},
|
||||
sbox::SboxLookup,
|
||||
};
|
||||
use cipher_core::{BlockError, InputBlock};
|
||||
use cipher_core::{parse_block_int, BlockError, InputBlock};
|
||||
use std::{
|
||||
ops::BitXor,
|
||||
slice::{from_raw_parts, from_raw_parts_mut},
|
||||
@@ -68,63 +68,10 @@ impl Block128 {
|
||||
impl FromStr for Block128 {
|
||||
type Err = BlockError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(parse_string_to_u128(s)?))
|
||||
Ok(Self(parse_block_int(s)?))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string_to_u128(s: &str) -> Result<u128, 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_u128(trimmed)
|
||||
}
|
||||
|
||||
fn parse_radix(s: &str, radix: u32) -> Result<u128, BlockError> {
|
||||
let trimmed = s.trim_start_matches('0');
|
||||
if trimmed.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
u128::from_str_radix(trimmed, radix).map_err(BlockError::from)
|
||||
}
|
||||
|
||||
fn ascii_string_to_u128(s: &str) -> Result<u128, BlockError> {
|
||||
if s.len() > 16 {
|
||||
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; 16];
|
||||
let offset = 16 - s.len();
|
||||
bytes[offset..].copy_from_slice(s.as_bytes());
|
||||
|
||||
Ok(u128::from_be_bytes(bytes))
|
||||
}
|
||||
|
||||
impl From<[u8; 16]> for Block128 {
|
||||
fn from(bytes: [u8; 16]) -> Self {
|
||||
Self::from_be_bytes(bytes)
|
||||
|
||||
Reference in New Issue
Block a user