From 5d4515b6cd43ce6db612d7c209a2a10615403ba2 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Wed, 22 Apr 2026 14:52:49 +0200 Subject: [PATCH 1/6] Add _iter and _len methods to block and fieldset arrays --- src/generate/block.rs | 26 ++++++++++++++++++++++++++ src/generate/fieldset.rs | 19 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/generate/block.rs b/src/generate/block.rs index e223ec3d..0268d900 100644 --- a/src/generate/block.rs +++ b/src/generate/block.rs @@ -16,6 +16,8 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result Result impl Iterator { + (0..#len).map(move |i| self.#name(i)) + } + + #doc + #[inline(always)] + pub const fn #name_len(self) -> usize { + #len + } )); } else { items.extend(quote!( @@ -83,6 +97,18 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result impl Iterator { + (0..#len).map(move |i| self.#name(i)) + } + + #doc + #[inline(always)] + pub const fn #name_len(self) -> usize { + #len + } )); } else { items.extend(quote!( diff --git a/src/generate/fieldset.rs b/src/generate/fieldset.rs index d64f7c47..7fe5b41f 100644 --- a/src/generate/fieldset.rs +++ b/src/generate/fieldset.rs @@ -26,6 +26,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu for f in sorted(&fs.fields, |f| (f.bit_offset.clone(), f.name.clone())) { let name = Ident::new(&f.name, span); let name_set = Ident::new(&format!("set_{}", f.name), span); + let name_len = Ident::new(&format!("{}_len", f.name), span); let off_in_reg = f.bit_offset.clone(); let _bit_size = f.bit_size as usize; let mask = util::hex(1u64.wrapping_shl(f.bit_size).wrapping_sub(1)); @@ -88,12 +89,20 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu #doc #[must_use] #[inline(always)] - pub const fn #name(&self, n: usize) -> #field_ty{ + pub const fn #name(&self, n: usize) -> #field_ty { assert!(n < #len); let offs = #off_in_reg + #offs_expr; let val = (self.0 >> offs) & #mask; #from_bits } + + #doc + #[must_use] + #[inline(always)] + pub const fn #name_len(&self) -> usize { + #len + } + #doc #[inline(always)] pub const fn #name_set(&mut self, n: usize, val: #field_ty) { @@ -154,6 +163,14 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu val += (((self.0 >> offs) & #mask) << #off_in_val); )*; #from_bits } + + #doc + #[must_use] + #[inline(always)] + pub const fn #name_len(&self) -> usize { + #len + } + #doc #[inline(always)] pub const fn #name_set(&mut self, n: usize, val: #field_ty) { From c50c746751f3b51eb3bec79c5d8bfcf9f31b6569 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Thu, 30 Apr 2026 14:14:24 +0200 Subject: [PATCH 2/6] Revert "Add _iter and _len methods to block and fieldset arrays" This reverts commit 5d4515b6cd43ce6db612d7c209a2a10615403ba2. --- src/generate/block.rs | 26 -------------------------- src/generate/fieldset.rs | 19 +------------------ 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/src/generate/block.rs b/src/generate/block.rs index 0268d900..e223ec3d 100644 --- a/src/generate/block.rs +++ b/src/generate/block.rs @@ -16,8 +16,6 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result Result impl Iterator { - (0..#len).map(move |i| self.#name(i)) - } - - #doc - #[inline(always)] - pub const fn #name_len(self) -> usize { - #len - } )); } else { items.extend(quote!( @@ -97,18 +83,6 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result impl Iterator { - (0..#len).map(move |i| self.#name(i)) - } - - #doc - #[inline(always)] - pub const fn #name_len(self) -> usize { - #len - } )); } else { items.extend(quote!( diff --git a/src/generate/fieldset.rs b/src/generate/fieldset.rs index 7fe5b41f..d64f7c47 100644 --- a/src/generate/fieldset.rs +++ b/src/generate/fieldset.rs @@ -26,7 +26,6 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu for f in sorted(&fs.fields, |f| (f.bit_offset.clone(), f.name.clone())) { let name = Ident::new(&f.name, span); let name_set = Ident::new(&format!("set_{}", f.name), span); - let name_len = Ident::new(&format!("{}_len", f.name), span); let off_in_reg = f.bit_offset.clone(); let _bit_size = f.bit_size as usize; let mask = util::hex(1u64.wrapping_shl(f.bit_size).wrapping_sub(1)); @@ -89,20 +88,12 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu #doc #[must_use] #[inline(always)] - pub const fn #name(&self, n: usize) -> #field_ty { + pub const fn #name(&self, n: usize) -> #field_ty{ assert!(n < #len); let offs = #off_in_reg + #offs_expr; let val = (self.0 >> offs) & #mask; #from_bits } - - #doc - #[must_use] - #[inline(always)] - pub const fn #name_len(&self) -> usize { - #len - } - #doc #[inline(always)] pub const fn #name_set(&mut self, n: usize, val: #field_ty) { @@ -163,14 +154,6 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu val += (((self.0 >> offs) & #mask) << #off_in_val); )*; #from_bits } - - #doc - #[must_use] - #[inline(always)] - pub const fn #name_len(&self) -> usize { - #len - } - #doc #[inline(always)] pub const fn #name_set(&mut self, n: usize, val: #field_ty) { From 658a14c3a33576c05453828ccc6b6042b766b0fb Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Thu, 30 Apr 2026 16:45:46 +0200 Subject: [PATCH 3/6] Implemented array proxy for ptrs --- src/generate/block.rs | 36 +++++++++--- src/generate/common.rs | 123 +++++++++++++++++++++++++++++++++++++++++ src/generate/mod.rs | 34 ++++++++++++ 3 files changed, 185 insertions(+), 8 deletions(-) diff --git a/src/generate/block.rs b/src/generate/block.rs index e223ec3d..68c2e9ed 100644 --- a/src/generate/block.rs +++ b/src/generate/block.rs @@ -46,13 +46,20 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result); if let Some(array) = &i.array { - let (len, offs_expr) = super::process_array(array); + let super::ArrayDescription { + array_ty, + constructor, + } = super::process_ptr_array( + array, + "e!(self.ptr.wrapping_add(#offset)), + &ty, + &common_path, + ); items.extend(quote!( #doc #[inline(always)] - pub const fn #name(self, n: usize) -> #ty { - assert!(n < #len); - unsafe { #common_path::Reg::from_ptr(self.ptr.wrapping_add(#offset + #offs_expr) as _) } + pub const fn #name(self) -> #array_ty { + #constructor } )); } else { @@ -74,14 +81,21 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result #ty { - assert!(n < #len); - unsafe { #ty::from_ptr(self.ptr.wrapping_add(#offset + #offs_expr) as _) } + pub const fn #name(self) -> #array_ty { + #constructor } )); } else { @@ -123,6 +137,12 @@ pub fn render(opts: &super::Options, ir: &IR, b: &Block, path: &str) -> Result Self { + unsafe { #name::from_ptr(ptr as *mut ()) } + } + } }; Ok(out) diff --git a/src/generate/common.rs b/src/generate/common.rs index a380a64e..d24678ea 100644 --- a/src/generate/common.rs +++ b/src/generate/common.rs @@ -83,3 +83,126 @@ impl Reg { self.write_value(val); } } + +pub trait FromPtr: Copy { + unsafe fn from_ptr(ptr: *mut u8) -> Self; +} + +impl FromPtr for Reg { + unsafe fn from_ptr(ptr: *mut u8) -> Self { + unsafe { Reg::::from_ptr(ptr as *mut T) } + } +} + +pub struct Array { + ptr: *mut u8, + stride: usize, + len: usize, + _type: PhantomData, +} + +impl Clone for Array { + fn clone(&self) -> Self { + Self { + ptr: self.ptr, + stride: self.stride, + len: self.len, + _type: self._type, + } + } +} +impl Copy for Array {} + +impl Array { + #[inline(always)] + pub const fn len(&self) -> usize { + self.len + } +} + +impl Array { + #[inline(always)] + pub const unsafe fn from_ptr(ptr: *mut u8, stride: usize, len: usize) -> Self { + Self { + ptr, + stride, + len, + _type: PhantomData, + } + } + + #[inline(always)] + pub fn get(&self, n: usize) -> T { + assert!(n < self.len()); + unsafe { T::from_ptr(self.ptr.wrapping_add(n * self.stride)) } + } +} + +impl Iterator for Array { + type Item = T; + + fn next(&mut self) -> Option { + if self.len == 0 { + return None; + } + + self.ptr = self.ptr.wrapping_add(self.stride); + self.len -= 1; + + Some(self.get(0)) + } +} + +pub struct CursedArray { + ptr: *mut u8, + offsets: &'static [usize], + _type: PhantomData, +} + +impl Clone for CursedArray { + fn clone(&self) -> Self { + Self { + ptr: self.ptr, + offsets: self.offsets, + _type: self._type, + } + } +} +impl Copy for CursedArray {} + +impl CursedArray { + #[inline(always)] + pub const fn len(&self) -> usize { + self.offsets.len() + } +} + +impl CursedArray { + #[inline(always)] + pub const unsafe fn from_ptr(ptr: *mut u8, offsets: &'static [usize]) -> Self { + Self { + ptr, + offsets, + _type: PhantomData, + } + } + + #[inline(always)] + pub fn get(&self, n: usize) -> T { + assert!(n < self.len()); + unsafe { T::from_ptr(self.ptr.wrapping_add(self.offsets[n])) } + } +} + +impl Iterator for CursedArray { + type Item = T; + + fn next(&mut self) -> Option { + if self.len() == 0 { + return None; + } + + self.offsets = &self.offsets[1..]; + Some(self.get(0)) + } +} diff --git a/src/generate/mod.rs b/src/generate/mod.rs index 54ce3d0e..f9f8963a 100644 --- a/src/generate/mod.rs +++ b/src/generate/mod.rs @@ -227,6 +227,40 @@ fn split_path(s: &str) -> (Vec<&str>, &str) { (v, n) } +struct ArrayDescription { + array_ty: TokenStream, + constructor: TokenStream, +} + +fn process_ptr_array( + array: &Array, + ptr: &TokenStream, + ty: &TokenStream, + common_path: &TokenStream, +) -> ArrayDescription { + match array { + Array::Regular(array) => { + let len = array.len as usize; + let stride = array.stride as usize; + ArrayDescription { + array_ty: quote!(#common_path::Array<#ty>), + constructor: quote!(unsafe { #common_path::Array::from_ptr(#ptr, #stride, #len) }), + } + } + Array::Cursed(array) => { + let offsets = array + .offsets + .iter() + .map(|&x| x as usize) + .collect::>(); + ArrayDescription { + array_ty: quote!(#common_path::CursedArray<#ty>), + constructor: quote!(unsafe { #common_path::CursedArray::from_ptr(#ptr, &[#(#offsets),*]) }), + } + } + } +} + fn process_array(array: &Array) -> (usize, TokenStream) { match array { Array::Regular(array) => { From db147022c983feb97372fddd7823c65c02c88795 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Fri, 1 May 2026 10:16:48 +0200 Subject: [PATCH 4/6] Fix stupid inductive Iterator mistake --- src/generate/common.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/generate/common.rs b/src/generate/common.rs index d24678ea..49fbf434 100644 --- a/src/generate/common.rs +++ b/src/generate/common.rs @@ -146,10 +146,12 @@ impl Iterator for Array { return None; } + let el = self.get(0); + self.ptr = self.ptr.wrapping_add(self.stride); self.len -= 1; - Some(self.get(0)) + Some(el) } } @@ -202,7 +204,8 @@ impl Iterator for CursedArray { return None; } + let el = self.get(0); self.offsets = &self.offsets[1..]; - Some(self.get(0)) + Some(el) } } From e254fce844eb16c71b8fcaedb9191a9f937983ef Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Mon, 4 May 2026 10:09:07 +0200 Subject: [PATCH 5/6] Added ArrayIter --- src/generate/common.rs | 42 +++++++++++++++++++++++++++++++----------- src/generate/mod.rs | 1 + 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/generate/common.rs b/src/generate/common.rs index 49fbf434..876924dd 100644 --- a/src/generate/common.rs +++ b/src/generate/common.rs @@ -101,6 +101,10 @@ pub struct Array { _type: PhantomData, } +pub struct ArrayIter { + parent: T, +} + impl Clone for Array { fn clone(&self) -> Self { Self { @@ -138,19 +142,26 @@ impl Array { } } -impl Iterator for Array { +impl IntoIterator for Array { + type Item = T; + type IntoIter = ArrayIter>; + + fn into_iter(self) -> Self::IntoIter { + ArrayIter { parent: self } + } +} + +impl Iterator for ArrayIter> { type Item = T; fn next(&mut self) -> Option { - if self.len == 0 { + if self.parent.len == 0 { return None; } - let el = self.get(0); - - self.ptr = self.ptr.wrapping_add(self.stride); - self.len -= 1; - + let el = self.parent.get(0); + self.parent.ptr = self.parent.ptr.wrapping_add(self.parent.stride); + self.parent.len -= 1; Some(el) } } @@ -196,16 +207,25 @@ impl CursedArray { } } -impl Iterator for CursedArray { +impl IntoIterator for CursedArray { + type Item = T; + type IntoIter = ArrayIter>; + + fn into_iter(self) -> Self::IntoIter { + ArrayIter { parent: self } + } +} + +impl Iterator for ArrayIter> { type Item = T; fn next(&mut self) -> Option { - if self.len() == 0 { + if self.parent.len() == 0 { return None; } - let el = self.get(0); - self.offsets = &self.offsets[1..]; + let el = self.parent.get(0); + self.parent.offsets = &self.parent.offsets[1..]; Some(el) } } diff --git a/src/generate/mod.rs b/src/generate/mod.rs index f9f8963a..1541c9c0 100644 --- a/src/generate/mod.rs +++ b/src/generate/mod.rs @@ -1,4 +1,5 @@ mod block; +mod common; mod device; mod enumm; mod fieldset; From 144f7a2d7aa571e97b3893bef3aa9c08e8ec0e44 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Mon, 4 May 2026 15:17:55 +0200 Subject: [PATCH 6/6] Added _len to fieldsets --- src/generate/fieldset.rs | 15 +++++++++++++-- src/generate/mod.rs | 3 +-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/generate/fieldset.rs b/src/generate/fieldset.rs index d64f7c47..c6f81fad 100644 --- a/src/generate/fieldset.rs +++ b/src/generate/fieldset.rs @@ -26,6 +26,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu for f in sorted(&fs.fields, |f| (f.bit_offset.clone(), f.name.clone())) { let name = Ident::new(&f.name, span); let name_set = Ident::new(&format!("set_{}", f.name), span); + let name_len = Ident::new(&format!("{}_len", f.name), span); let off_in_reg = f.bit_offset.clone(); let _bit_size = f.bit_size as usize; let mask = util::hex(1u64.wrapping_shl(f.bit_size).wrapping_sub(1)); @@ -83,7 +84,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu BitOffset::Regular(off_in_reg) => { let off_in_reg = off_in_reg as usize; if let Some(array) = &f.array { - let (len, offs_expr) = super::process_array(array); + let (len, offs_expr) = super::process_field_array(array); items.extend(quote!( #doc #[must_use] @@ -101,6 +102,11 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu let offs = #off_in_reg + #offs_expr; self.0 = (self.0 & !(#mask << offs)) | (((#to_bits) & #mask) << offs); } + #doc + #[inline(always)] + pub const fn #name_len(&self) -> usize { + #len + } )); } else { items.extend(quote!( @@ -142,7 +148,7 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu } if let Some(array) = &f.array { - let (len, offs_expr) = super::process_array(array); + let (len, offs_expr) = super::process_field_array(array); items.extend(quote!( #doc #[must_use] @@ -161,6 +167,11 @@ pub fn render(opts: &super::Options, ir: &IR, fs: &FieldSet, path: &str) -> Resu #( let offs = #off_in_reg + #offs_expr; self.0 = (self.0 & !(#mask << offs)) | (((#to_bits >> #off_in_val) & #mask) << offs); )*; } + #doc + #[inline(always)] + pub const fn #name_len(&self) -> usize { + #len + } )); } else { items.extend(quote!( diff --git a/src/generate/mod.rs b/src/generate/mod.rs index 1541c9c0..28ed7e4a 100644 --- a/src/generate/mod.rs +++ b/src/generate/mod.rs @@ -1,5 +1,4 @@ mod block; -mod common; mod device; mod enumm; mod fieldset; @@ -262,7 +261,7 @@ fn process_ptr_array( } } -fn process_array(array: &Array) -> (usize, TokenStream) { +fn process_field_array(array: &Array) -> (usize, TokenStream) { match array { Array::Regular(array) => { let len = array.len as usize;