Skip to content

Commit af4cc76

Browse files
committed
Split ArrayProxy out into its own file.
Make the usage of ArrayProxy dependent on the const_generics config option.
1 parent 60aa7be commit af4cc76

File tree

5 files changed

+68
-69
lines changed

5 files changed

+68
-69
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111
- Re-export base's module for derived peripherals
1212
- More Cluster arrays are now emitted as an array rather than a list of
1313
elements. An `ArrayProxy` wrapper is used when a Rust built-in array does not
14-
match the cluster layout.
14+
match the cluster layout. Requires the `--const_generic` command line option.
1515

1616
## [v0.19.0] - 2021-05-26
1717

src/generate/array_proxy.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
/// Access an array of `COUNT` items of type `T` with the items `STRIDE` bytes
3+
/// apart. This is a zero-sized-type. No objects of this type are ever
4+
/// actually created, it is only a convenience for wrapping pointer arithmetic.
5+
///
6+
/// There is no safe way to produce items of this type. Unsafe code can produce
7+
/// references by pointer casting. It is up to the unsafe code doing that, to
8+
/// ensure that the memory really is backed by appropriate content.
9+
///
10+
/// Typically, this is used for accessing hardware registers.
11+
pub struct ArrayProxy<T, const COUNT: usize, const STRIDE: usize> {
12+
/// As well as providing a PhantomData, this field is non-public, and
13+
/// therefore ensures that code outside of this module can never create
14+
/// an ArrayProxy.
15+
_array: marker::PhantomData<T>
16+
}
17+
18+
impl<T, const C: usize, const S: usize> ArrayProxy<T, C, S> {
19+
/// Get a reference from an [ArrayProxy] with no bounds checking.
20+
pub unsafe fn get_ref(&self, index: usize) -> &T {
21+
let base = self as *const Self as usize;
22+
let address = base + S * index;
23+
&*(address as *const T)
24+
}
25+
/// Get a reference from an [ArrayProxy], or return `None` if the index
26+
/// is out of bounds.
27+
pub fn get(&self, index: usize) -> Option<&T> {
28+
if index < C {
29+
Some(unsafe { self.get_ref(index) })
30+
}
31+
else {
32+
None
33+
}
34+
}
35+
/// Return the number of items.
36+
pub fn len(&self) -> usize { C }
37+
}
38+
39+
impl<T, const C: usize, const S: usize> core::ops::Index<usize> for ArrayProxy<T, C, S> {
40+
type Output = T;
41+
fn index(&self, index: usize) -> &T {
42+
// Do a real array dereference for the bounds check.
43+
[(); C][index];
44+
unsafe { self.get_ref(index) }
45+
}
46+
}

src/generate/device.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
146146
std::str::from_utf8(include_bytes!("generic_msp430_atomic.rs"))?;
147147
writeln!(file, "\n{}", msp430_atomic_file)?;
148148
}
149+
if config.const_generic {
150+
let array_proxy = std::str::from_utf8(include_bytes!("array_proxy.rs"))?;
151+
writeln!(file, "{}", array_proxy)?;
152+
}
149153

150154
if !config.make_mod {
151155
out.extend(quote! {
@@ -156,32 +160,27 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
156160
});
157161
}
158162
} else {
159-
let tokens = syn::parse_file(generic_file)?.into_token_stream();
160-
163+
let mut tokens = syn::parse_file(generic_file)?.into_token_stream();
161164
if config.target == Target::Msp430 && config.nightly {
162165
let msp430_atomic_file =
163166
std::str::from_utf8(include_bytes!("generic_msp430_atomic.rs"))?;
164167
let generic_msp430_atomic = syn::parse_file(msp430_atomic_file)?.into_token_stream();
165-
out.extend(quote! {
166-
#[allow(unused_imports)]
167-
use generic::*;
168-
///Common register and bit access and modify traits
169-
pub mod generic {
170-
#tokens
171-
172-
#generic_msp430_atomic
173-
}
174-
});
175-
} else {
176-
out.extend(quote! {
177-
#[allow(unused_imports)]
178-
use generic::*;
179-
///Common register and bit access and modify traits
180-
pub mod generic {
181-
#tokens
182-
}
183-
});
168+
tokens.extend(generic_msp430_atomic);
169+
}
170+
if config.const_generic {
171+
let array_proxy = std::str::from_utf8(include_bytes!("array_proxy.rs"))?;
172+
let generic_array_proxy = syn::parse_file(array_proxy)?.into_token_stream();
173+
tokens.extend(generic_array_proxy);
184174
}
175+
176+
out.extend(quote! {
177+
#[allow(unused_imports)]
178+
use generic::*;
179+
///Common register and bit access and modify traits
180+
pub mod generic {
181+
#tokens
182+
}
183+
});
185184
}
186185

187186
out.extend(interrupt::render(config.target, &d.peripherals, device_x)?);

src/generate/generic.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -280,49 +280,3 @@ impl<FI> FieldReader<bool, FI> {
280280
self.bit()
281281
}
282282
}
283-
284-
/// Access an array of `COUNT` items of type `T` with the items `STRIDE` bytes
285-
/// apart. This is a zero-sized-type. No objects of this type are ever
286-
/// actually created, it is only a convenience for wrapping pointer arithmetic.
287-
///
288-
/// There is no safe way to produce items of this type. Unsafe code can produce
289-
/// references by pointer casting. It is up to the unsafe code doing that, to
290-
/// ensure that the memory really is backed by appropriate content.
291-
///
292-
/// Typically, this is used for accessing hardware registers.
293-
pub struct ArrayProxy<T, const COUNT: usize, const STRIDE: usize> {
294-
/// As well as providing a PhantomData, this field is non-public, and
295-
/// therefore ensures that code outside of this module can never create
296-
/// an ArrayProxy.
297-
_array: marker::PhantomData<T>
298-
}
299-
300-
impl<T, const C: usize, const S: usize> ArrayProxy<T, C, S> {
301-
/// Get a reference from an [ArrayProxy] with no bounds checking.
302-
pub unsafe fn get_ref(&self, index: usize) -> &T {
303-
let base = self as *const Self as usize;
304-
let address = base + S * index;
305-
&*(address as *const T)
306-
}
307-
/// Get a reference from an [ArrayProxy], or return `None` if the index
308-
/// is out of bounds.
309-
pub fn get(&self, index: usize) -> Option<&T> {
310-
if index < C {
311-
Some(unsafe { self.get_ref(index) })
312-
}
313-
else {
314-
None
315-
}
316-
}
317-
/// Return the number of items.
318-
pub fn len(&self) -> usize { C }
319-
}
320-
321-
impl<T, const C: usize, const S: usize> core::ops::Index<usize> for ArrayProxy<T, C, S> {
322-
type Output = T;
323-
fn index(&self, index: usize) -> &T {
324-
// Do a real array dereference for the bounds check.
325-
[(); C][index];
326-
unsafe { self.get_ref(index) }
327-
}
328-
}

src/generate/peripheral.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ fn expand_cluster(
703703
offset: info.address_offset,
704704
size: cluster_size * array_info.dim,
705705
});
706-
} else if sequential_indexes {
706+
} else if sequential_indexes && config.const_generic {
707707
// Include a ZST ArrayProxy giving indexed access to the
708708
// elements.
709709
cluster_expanded.push(array_proxy(info, array_info, name)?);

0 commit comments

Comments
 (0)