implement to and from be bytes for stored type
This commit is contained in:
@@ -46,12 +46,16 @@
|
||||
|
||||
const U26_VALUE_MASK: u32 = 0xFFFFFFc0;
|
||||
const U26_MAX_VALUE: u32 = 0x03FFFFFF;
|
||||
const U26_HEMMING_MASK: u32 = 0x0000003e;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum U26Error {
|
||||
InvalidCodeWord,
|
||||
IncorrectibleError,
|
||||
Overflow,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// this type is used for storing data on memory devices the concern here is mostly protecting against memory corruption
|
||||
/// du to faulty memory cells. Here one bit errors are the most probabl cause of errors so this types uses a build in
|
||||
/// hemming code for one mit error correction.
|
||||
@@ -68,6 +72,38 @@ impl Stored_U26 {
|
||||
let hemming_code = calc_hemming(value);
|
||||
Self((value << 6) | ((hemming_code & 0x3F) << 1) as u32)
|
||||
}
|
||||
|
||||
pub fn to_be_bytes(&self) -> [u8; 4] {
|
||||
self.0.to_be_bytes()
|
||||
}
|
||||
|
||||
pub fn from_be_bytes(bytes: [u8;4]) -> Result<Self, U26Error> {
|
||||
let raw_u32 = u32::from_be_bytes(bytes);
|
||||
// the last bit is expetced to be 0
|
||||
if raw_u32 & 0x1 != 0x0 {
|
||||
return Err(U26Error::InvalidCodeWord);
|
||||
}
|
||||
let value = (raw_u32 & U26_VALUE_MASK) >> 6;
|
||||
let hemming = ((raw_u32 & U26_HEMMING_MASK) >> 1) as u8;
|
||||
match check_hemming(value, hemming) {
|
||||
Ok(()) => Ok(
|
||||
Stored_U26(raw_u32)
|
||||
),
|
||||
Err(correction_data) => {
|
||||
let (dc, hc) = correction_data.calc_correction_data();
|
||||
if check_hemming(value ^ dc, hemming ^ hc).is_err() {
|
||||
// this case will not occur in our case because
|
||||
// or codeword length corresponds to 31 and thus a perfect hemming
|
||||
// code, flipping the correct bit will always produce a valid
|
||||
// codeword even though the data was not the orginal stored data,
|
||||
// to secure against this a crc is required
|
||||
Err(U26Error::IncorrectibleError)
|
||||
} else {
|
||||
Ok(Self::new(value ^ dc))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Stored_U26> for u32 {
|
||||
@@ -276,7 +312,9 @@ pub fn check_hemming(data: u32, hemming: u8) -> Result<(), HemmingCorrectionValu
|
||||
mod base_type_tests {
|
||||
use std::println;
|
||||
|
||||
use super::{calc_hemming, check_hemming, U26_MAX_VALUE};
|
||||
use crate::types::U26Error;
|
||||
|
||||
use super::{calc_hemming, check_hemming, Stored_U26, U26_MAX_VALUE};
|
||||
|
||||
#[test]
|
||||
fn hemming_code_generation() {
|
||||
@@ -345,12 +383,12 @@ mod base_type_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hemming_dual_bit_error_detection() {
|
||||
let data = 0x123456;
|
||||
let hemming = calc_hemming(data);
|
||||
let bit_error = 0x101;
|
||||
let correction = check_hemming(data ^ bit_error, hemming).unwrap_err();
|
||||
let (dc, hc) = correction.calc_correction_data();
|
||||
assert!(check_hemming(data ^ dc, hemming ^ hc).is_err())
|
||||
fn stored_u26_to_from_bytes() {
|
||||
let data: Stored_U26 = 0x123456.try_into().unwrap();
|
||||
let mut bytes = data.to_be_bytes();
|
||||
assert_eq!(Stored_U26::from_be_bytes(bytes).unwrap(), data);
|
||||
// introduce 1 bit error
|
||||
bytes[2] = bytes[2] ^ 0x01;
|
||||
assert_eq!(Stored_U26::from_be_bytes(bytes).unwrap(), data);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user