lib-q-cb-kem 0.0.4

Classical McEliece KEM implementation for lib-Q post-quantum cryptography library
Documentation
#![cfg(test)]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
pub(crate) struct TestData {
    data: &'static [u8],
}

#[cfg(feature = "alloc")]
impl TestData {
    pub(crate) fn new() -> TestData {
        let bytes = include_bytes!("../data/testdata.txt");
        TestData { data: bytes }
    }
}

#[cfg(feature = "alloc")]
mod alloc_parsers {
    use super::TestData;

    macro_rules! impl_parser_per_type {
        ($name:ident, $bitsize:expr, $t:ty) => {
            /// Parses a testdata file and returns a vector of $ty stored for the given `search_key`.
            /// The value is parsed in big-endian order.
            ///
            /// I started to write a zero-allocation parser, but it takes many lines of code.
            /// This design allocates, but can be comprehended much easier.
            pub(crate) fn $name(&self, search_key: &str) -> alloc::vec::Vec<$t> {
                use core::convert::TryInto;
                use core::str;

                let content = match str::from_utf8(self.data) {
                    Ok(v) => v,
                    Err(e) => panic!("testdata.txt contains invalid UTF-8 data: {}", e),
                };

                for (lineno, line) in content.lines().enumerate() {
                    let inner_line = line.trim();
                    if inner_line.starts_with('#') {
                        continue;
                    }
                    let mut key = "";
                    let mut value = "";
                    for (f, field) in inner_line.split('=').enumerate() {
                        match f {
                            0 => key = field.trim(),
                            1 => value = field.trim(),
                            _ => {}
                        }
                    }
                    if key != search_key {
                        continue;
                    }
                    if value == "" {
                        panic!("empty value for key '{}' at line {}", search_key, lineno);
                    }
                    let bytes = hex::decode(value).expect("invalid hex data in value");
                    let bytes_per_element = $bitsize / 8;
                    let elements_count = bytes.len() / bytes_per_element;
                    let mut elements = alloc::vec::Vec::<$t>::with_capacity(elements_count);
                    for idx in 0..elements_count {
                        let element =
                            &bytes[bytes_per_element * idx..bytes_per_element * (idx + 1)];
                        elements.push(<$t>::from_be_bytes(
                            element.try_into().expect("invalid slice length"),
                        ));
                    }
                    return elements;
                }

                panic!("search_key '{}' not found in testdata.txt", search_key);
            }
        };
    }

    impl TestData {
        impl_parser_per_type!(u8vec, 8, u8);
        impl_parser_per_type!(u16vec, 16, u16);
        #[cfg(feature = "cbkem8192128f")]
        impl_parser_per_type!(u32vec, 32, u32);
        impl_parser_per_type!(u64vec, 64, u64);
        #[cfg(any(
            feature = "cbkem348864",
            feature = "cbkem6960119",
            feature = "cbkem8192128f"
        ))]
        impl_parser_per_type!(i16vec, 16, i16);
    }
}