Add from_bytes() and to_bytes() to CryptoNum, and do a basic implementation of from_bytes().

This commit is contained in:
2019-07-23 21:05:20 -07:00
parent aff88eb2f0
commit 203c23e277
2 changed files with 49 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ module UnsignedBase(
where where
import Control.Monad(forM_) import Control.Monad(forM_)
import Data.List(intercalate)
import File import File
import Gen import Gen
@@ -56,6 +57,36 @@ declareBaseStructure bitsize =
wrapIndent ("if idx >= " ++ show entries) $ wrapIndent ("if idx >= " ++ show entries) $
out "return false;" out "return false;"
out "(self.value[idx] & (1u64 << offset)) != 0" out "(self.value[idx] & (1u64 << offset)) != 0"
blank
wrapIndent ("fn from_bytes(&self, bytes: &[u8]) -> Self") $
do let bytes = bitsize `div` 8;
forM_ [0..bytes-1] $ \ idx ->
out ("let byte" ++ show idx ++ " = " ++
"if " ++ show idx ++ " < bytes.len() { " ++
"bytes[" ++ show idx ++ "] as u64 } else { 0 };")
blank
let byteNames = map (\ x -> "byte" ++ show x) [0..bytes-1]
byteGroups = groupCount 8 (reverse byteNames)
forM_ (zip byteGroups [0..bytes-1]) $ \ (byteGroup, idx) ->
do let shiftAmts = [0,8..56]
shifts = zipWith (\ n s -> n ++ " << " ++ show s)
byteGroup shiftAmts
shift0 = head shifts
shiftL = last shifts
middles = reverse (drop 1 (reverse (drop 1 shifts)))
prefix = "let word" ++ show idx ++ " "
blankPrefix = map (const ' ') prefix
out (prefix ++ " = " ++ shift0)
forM_ middles $ \ s -> out (blankPrefix ++ " | " ++ s)
out (blankPrefix ++ " | " ++ shiftL ++ ";")
blank
wrapIndent name $
do out ("value: [")
let vwords = map (\ x -> "word" ++ show x) [0..top]
linewords = groupCount 4 vwords
vlines = map (intercalate ", ") linewords
forM_ vlines $ \ l -> out (" " ++ l ++ ",")
out ("]")
blank blank
implFor "PartialEq" name $ implFor "PartialEq" name $
wrapIndent "fn eq(&self, other: &Self) -> bool" $ wrapIndent "fn eq(&self, other: &Self) -> bool" $
@@ -122,3 +153,8 @@ declareBaseStructure bitsize =
out ("x.mask(usize::from(&m));") out ("x.mask(usize::from(&m));")
out ("assert_eq!(x, r);") out ("assert_eq!(x, r);")
out ("});") out ("});")
groupCount :: Int -> [a] -> [[a]]
groupCount x ls
| x >= length ls = [ls]
| otherwise = take x ls : groupCount x (drop x ls)

View File

@@ -20,5 +20,17 @@ pub trait CryptoNum {
/// Test if the given bit is zero, where bits are numbered in /// Test if the given bit is zero, where bits are numbered in
/// least-significant order (0 is the LSB, etc.). /// least-significant order (0 is the LSB, etc.).
fn testbit(&self, bit: usize) -> bool; fn testbit(&self, bit: usize) -> bool;
/// Convert a slice into a CryptoNum, assuming big-endian memory layout.
/// If you pass in a slice bigger than the bit size of the numeric type,
/// this will assume that the number is in the first `n` bits of the
/// memory layout. If you pass in a smaller buffer, it will use the bits
/// available as the low `n` bits of the number.
fn from_bytes(&self, bytes: &[u8]) -> Self;
/// Write the cryptonum into the provide slice. If the provided slice
/// is greater than or equal to `n` bits in length, `to_bytes` will
/// write to the first `n` bits. If the slice is less than `n` bits
/// in length, `to_bytes` will write the lower-order bits that fit
/// into the provided slice.
fn to_bytes(&self, bytes: &mut [u8]);
} }