mirror of
https://github.com/kristoferssolo/des-rs.git
synced 2025-12-20 11:04:38 +00:00
feat: add error type
This commit is contained in:
parent
d362a7df3a
commit
b8b963455d
@ -2,33 +2,17 @@ use crate::grammar;
|
|||||||
use unsynn::*;
|
use unsynn::*;
|
||||||
|
|
||||||
pub struct Struct {
|
pub struct Struct {
|
||||||
pub attr: Attribute,
|
pub bit_width: u128,
|
||||||
|
pub error_type: Ident,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub body: Ident,
|
pub body: Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Struct {
|
|
||||||
pub fn bit_width(&self) -> u128 {
|
|
||||||
self.attr.bit_width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Attribute {
|
|
||||||
pub bit_width: u128,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<grammar::Attribute> for Attribute {
|
|
||||||
fn from(value: grammar::Attribute) -> Self {
|
|
||||||
Self {
|
|
||||||
bit_width: value.bit_width.content.bit_width.content.value(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<grammar::StructDef> for Struct {
|
impl From<grammar::StructDef> for Struct {
|
||||||
fn from(value: grammar::StructDef) -> Self {
|
fn from(value: grammar::StructDef) -> Self {
|
||||||
Self {
|
Self {
|
||||||
attr: value.attr.into(),
|
bit_width: value.bit_width.bit_width.content.width.content.value(),
|
||||||
|
error_type: value.error_type.error.content.error.content,
|
||||||
name: value.name,
|
name: value.name,
|
||||||
body: value.body.content,
|
body: value.body.content,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,9 @@ use crate::{codegen::generate_impl, grammar::StructDef};
|
|||||||
use unsynn::*;
|
use unsynn::*;
|
||||||
|
|
||||||
pub fn impl_bit_wrapper(input: &TokenStream) -> TokenStream {
|
pub fn impl_bit_wrapper(input: &TokenStream) -> TokenStream {
|
||||||
let parsed = input.to_token_iter().parse::<StructDef>().unwrap();
|
let parsed = input
|
||||||
|
.to_token_iter()
|
||||||
|
.parse::<StructDef>()
|
||||||
|
.expect("StructDef parsing");
|
||||||
generate_impl(&parsed.into())
|
generate_impl(&parsed.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,8 +70,9 @@ fn generate_bitwise_fmt(info: &Struct) -> TokenStream {
|
|||||||
fn generate_bitwise_ops(info: &Struct) -> TokenStream {
|
fn generate_bitwise_ops(info: &Struct) -> TokenStream {
|
||||||
let name = &info.name;
|
let name = &info.name;
|
||||||
let inner = &info.body;
|
let inner = &info.body;
|
||||||
|
let error_type = &info.error_type;
|
||||||
|
|
||||||
let bit_width = u8::try_from(info.bit_width()).expect("8-bit value");
|
let bit_width = u8::try_from(info.bit_width).expect("8-bit value");
|
||||||
|
|
||||||
let hex_width = usize::from(bit_width.div_ceil(4));
|
let hex_width = usize::from(bit_width.div_ceil(4));
|
||||||
let bin_width = usize::from(bit_width);
|
let bin_width = usize::from(bit_width);
|
||||||
@ -91,7 +92,7 @@ fn generate_bitwise_ops(info: &Struct) -> TokenStream {
|
|||||||
/// Create a new [`Self`] from a key value
|
/// Create a new [`Self`] from a key value
|
||||||
#[inline]
|
#[inline]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub fn new(key: #inner) -> Result<Self, String> {
|
pub fn new(key: #inner) -> Result<Self, #error_type> {
|
||||||
key.try_into()
|
key.try_into()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,17 +264,17 @@ fn generate_bitwise_ops(info: &Struct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create from a hex string with bit width validation
|
/// Create from a hex string with bit width validation
|
||||||
pub fn from_hex(hex: &str) -> Result<Self, String> {
|
pub fn from_hex(hex: &str) -> Result<Self, #error_type> {
|
||||||
let value = #inner::from_str_radix(hex, 16).map_err(|e| format!("Invalid hex string: {e}"))?;
|
let value = #inner::from_str_radix(hex, 16)?;
|
||||||
|
|
||||||
let masked = value & Self::MAX;
|
let masked = value & Self::MAX;
|
||||||
if value != masked {
|
if value != masked {
|
||||||
return Err(
|
return Err(#error_type::ExceedsBitLimit {
|
||||||
format!(
|
value,
|
||||||
"Hex value 0x{value:X} exceeds {}-bit limit (masked to 0x{masked:0width$X})",
|
bit_width: Self::BIT_WIDTH,
|
||||||
Self::BIT_WIDTH, width = #hex_width
|
masked,
|
||||||
)
|
width: #hex_width
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self(value))
|
Ok(Self(value))
|
||||||
|
|||||||
@ -4,12 +4,13 @@ keyword! {
|
|||||||
pub KwStruct = "struct";
|
pub KwStruct = "struct";
|
||||||
pub KwPub = "pub";
|
pub KwPub = "pub";
|
||||||
pub KwBitWidth = "bit_width";
|
pub KwBitWidth = "bit_width";
|
||||||
|
pub KwError = "bit_conversion_error";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsynn! {
|
unsynn! {
|
||||||
pub struct BitWidth{
|
pub struct BitWidth {
|
||||||
pub kw_bit_width: KwBitWidth,
|
pub kw_bit_width: KwBitWidth,
|
||||||
pub bit_width: ParenthesisGroupContaining<LiteralInteger>,
|
pub width: ParenthesisGroupContaining<LiteralInteger>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Attribute {
|
pub struct Attribute {
|
||||||
@ -17,8 +18,19 @@ unsynn! {
|
|||||||
pub bit_width: BracketGroupContaining<BitWidth>,
|
pub bit_width: BracketGroupContaining<BitWidth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ErrorType {
|
||||||
|
pub kw_bit_width: KwError,
|
||||||
|
pub error: ParenthesisGroupContaining<Ident>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AttributeError {
|
||||||
|
pub pound: Pound,
|
||||||
|
pub error: BracketGroupContaining<ErrorType>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct StructDef {
|
pub struct StructDef {
|
||||||
pub attr: Attribute,
|
pub bit_width: Attribute,
|
||||||
|
pub error_type: AttributeError,
|
||||||
pub vis: Option<KwPub>,
|
pub vis: Option<KwPub>,
|
||||||
pub kw_struct: KwStruct,
|
pub kw_struct: KwStruct,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
@ -33,6 +45,7 @@ mod tests {
|
|||||||
|
|
||||||
const SAMPLE: &str = r#"
|
const SAMPLE: &str = r#"
|
||||||
#[bit_width(48)]
|
#[bit_width(48)]
|
||||||
|
#[bit_conversion_error()]
|
||||||
pub struct Subkey(u64);
|
pub struct Subkey(u64);
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ mod grammar;
|
|||||||
use crate::bit_wrapper::impl_bit_wrapper;
|
use crate::bit_wrapper::impl_bit_wrapper;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
#[proc_macro_derive(BitWrapper, attributes(bit_width))]
|
#[proc_macro_derive(BitWrapper, attributes(bit_width, bit_conversion_error))]
|
||||||
pub fn derive_bit_wrapper(input: TokenStream) -> TokenStream {
|
pub fn derive_bit_wrapper(input: TokenStream) -> TokenStream {
|
||||||
impl_bit_wrapper(&input.into()).into()
|
impl_bit_wrapper(&input.into()).into()
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user