Skip to content

Commit 674fbd7

Browse files
committed
Replace manual repeated impls with macros
1 parent 4eeab35 commit 674fbd7

File tree

1 file changed

+77
-161
lines changed

1 file changed

+77
-161
lines changed

libraries/tock-register-interface/src/registers.rs

Lines changed: 77 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -79,32 +79,22 @@ pub trait IntLike:
7979
fn zero() -> Self;
8080
}
8181

82-
impl IntLike for u8 {
83-
fn zero() -> Self {
84-
0
85-
}
86-
}
87-
impl IntLike for u16 {
88-
fn zero() -> Self {
89-
0
90-
}
91-
}
92-
impl IntLike for u32 {
93-
fn zero() -> Self {
94-
0
95-
}
96-
}
97-
impl IntLike for u64 {
98-
fn zero() -> Self {
99-
0
100-
}
101-
}
102-
impl IntLike for u128 {
103-
fn zero() -> Self {
104-
0
105-
}
82+
macro_rules! IntLike_impl_for {
83+
($type:ty) => {
84+
impl IntLike for $type {
85+
fn zero() -> Self {
86+
0
87+
}
88+
}
89+
};
10690
}
10791

92+
IntLike_impl_for!(u8);
93+
IntLike_impl_for!(u16);
94+
IntLike_impl_for!(u32);
95+
IntLike_impl_for!(u64);
96+
IntLike_impl_for!(u128);
97+
10898
/// Descriptive name for each register.
10999
pub trait RegisterLongName {}
110100

@@ -408,29 +398,21 @@ impl<T: IntLike + fmt::Debug, R: RegisterLongName> fmt::Debug for LocalRegisterC
408398
}
409399
}
410400

411-
impl<R: RegisterLongName> From<LocalRegisterCopy<u8, R>> for u8 {
412-
fn from(r: LocalRegisterCopy<u8, R>) -> u8 {
413-
r.value
414-
}
415-
}
416-
417-
impl<R: RegisterLongName> From<LocalRegisterCopy<u16, R>> for u16 {
418-
fn from(r: LocalRegisterCopy<u16, R>) -> u16 {
419-
r.value
420-
}
421-
}
422-
423-
impl<R: RegisterLongName> From<LocalRegisterCopy<u32, R>> for u32 {
424-
fn from(r: LocalRegisterCopy<u32, R>) -> u32 {
425-
r.value
426-
}
401+
macro_rules! From_impl_for {
402+
($type:ty) => {
403+
impl<R: RegisterLongName> From<LocalRegisterCopy<$type, R>> for $type {
404+
fn from(r: LocalRegisterCopy<$type, R>) -> $type {
405+
r.value
406+
}
407+
}
408+
};
427409
}
428410

429-
impl<R: RegisterLongName> From<LocalRegisterCopy<u64, R>> for u64 {
430-
fn from(r: LocalRegisterCopy<u64, R>) -> u64 {
431-
r.value
432-
}
433-
}
411+
From_impl_for!(u8);
412+
From_impl_for!(u16);
413+
From_impl_for!(u32);
414+
From_impl_for!(u64);
415+
From_impl_for!(u128);
434416

435417
/// In memory volatile register.
436418
// To successfully alias this structure onto hardware registers in memory, this
@@ -506,6 +488,8 @@ impl<T: IntLike, R: RegisterLongName> InMemoryRegister<T, R> {
506488
}
507489

508490
/// Specific section of a register.
491+
///
492+
/// For the Field, the mask is unshifted, ie. the LSB should always be set.
509493
#[derive(Copy, Clone)]
510494
pub struct Field<T: IntLike, R: RegisterLongName> {
511495
mask: T,
@@ -514,6 +498,14 @@ pub struct Field<T: IntLike, R: RegisterLongName> {
514498
}
515499

516500
impl<T: IntLike, R: RegisterLongName> Field<T, R> {
501+
pub const fn new(mask: T, shift: usize) -> Field<T, R> {
502+
Field {
503+
mask: mask,
504+
shift: shift,
505+
associated_register: PhantomData,
506+
}
507+
}
508+
517509
#[inline]
518510
pub fn read(self, val: T) -> T {
519511
(val & (self.mask << self.shift)) >> self.shift
@@ -532,139 +524,63 @@ impl<T: IntLike, R: RegisterLongName> Field<T, R> {
532524
}
533525
}
534526

535-
// For the Field, the mask is unshifted, ie. the LSB should always be set
536-
impl<R: RegisterLongName> Field<u8, R> {
537-
pub const fn new(mask: u8, shift: usize) -> Field<u8, R> {
538-
Field {
539-
mask: mask,
540-
shift: shift,
541-
associated_register: PhantomData,
542-
}
543-
}
544-
545-
pub fn val(&self, value: u8) -> FieldValue<u8, R> {
546-
FieldValue::<u8, R>::new(self.mask, self.shift, value)
547-
}
548-
}
549-
550-
impl<R: RegisterLongName> Field<u16, R> {
551-
pub const fn new(mask: u16, shift: usize) -> Field<u16, R> {
552-
Field {
553-
mask: mask,
554-
shift: shift,
555-
associated_register: PhantomData,
556-
}
557-
}
558-
559-
pub fn val(&self, value: u16) -> FieldValue<u16, R> {
560-
FieldValue::<u16, R>::new(self.mask, self.shift, value)
561-
}
562-
}
563-
564-
impl<R: RegisterLongName> Field<u32, R> {
565-
pub const fn new(mask: u32, shift: usize) -> Field<u32, R> {
566-
Field {
567-
mask: mask,
568-
shift: shift,
569-
associated_register: PhantomData,
527+
macro_rules! Field_impl_for {
528+
($type:ty) => {
529+
impl<R: RegisterLongName> Field<$type, R> {
530+
pub fn val(&self, value: $type) -> FieldValue<$type, R> {
531+
FieldValue::<$type, R>::new(self.mask, self.shift, value)
532+
}
570533
}
571-
}
572-
573-
pub fn val(&self, value: u32) -> FieldValue<u32, R> {
574-
FieldValue::<u32, R>::new(self.mask, self.shift, value)
575-
}
534+
};
576535
}
577536

578-
impl<R: RegisterLongName> Field<u64, R> {
579-
pub const fn new(mask: u64, shift: usize) -> Field<u64, R> {
580-
Field {
581-
mask: mask,
582-
shift: shift,
583-
associated_register: PhantomData,
584-
}
585-
}
586-
587-
pub fn val(&self, value: u64) -> FieldValue<u64, R> {
588-
FieldValue::<u64, R>::new(self.mask, self.shift, value)
589-
}
590-
}
537+
Field_impl_for!(u8);
538+
Field_impl_for!(u16);
539+
Field_impl_for!(u32);
540+
Field_impl_for!(u64);
541+
Field_impl_for!(u128);
591542

592543
/// Values for the specific register fields.
593-
// For the FieldValue, the masks and values are shifted into their actual
594-
// location in the register.
544+
///
545+
/// For the FieldValue, the masks and values are shifted into their actual
546+
/// location in the register.
595547
#[derive(Copy, Clone)]
596548
pub struct FieldValue<T: IntLike, R: RegisterLongName> {
597549
mask: T,
598550
pub value: T,
599551
associated_register: PhantomData<R>,
600552
}
601553

602-
// Necessary to split the implementation of new() out because the bitwise
603-
// math isn't treated as const when the type is generic.
604-
// Tracking issue: https://github.com/rust-lang/rfcs/pull/2632
605-
impl<R: RegisterLongName> FieldValue<u8, R> {
606-
pub const fn new(mask: u8, shift: usize, value: u8) -> Self {
607-
FieldValue {
608-
mask: mask << shift,
609-
value: (value & mask) << shift,
610-
associated_register: PhantomData,
611-
}
612-
}
613-
}
614-
615-
impl<R: RegisterLongName> From<FieldValue<u8, R>> for u8 {
616-
fn from(val: FieldValue<u8, R>) -> u8 {
617-
val.value
618-
}
619-
}
620-
621-
impl<R: RegisterLongName> FieldValue<u16, R> {
622-
pub const fn new(mask: u16, shift: usize, value: u16) -> Self {
623-
FieldValue {
624-
mask: mask << shift,
625-
value: (value & mask) << shift,
626-
associated_register: PhantomData,
627-
}
628-
}
629-
}
630-
631-
impl<R: RegisterLongName> From<FieldValue<u16, R>> for u16 {
632-
fn from(val: FieldValue<u16, R>) -> u16 {
633-
val.value
634-
}
635-
}
636-
637-
impl<R: RegisterLongName> FieldValue<u32, R> {
638-
pub const fn new(mask: u32, shift: usize, value: u32) -> Self {
639-
FieldValue {
640-
mask: mask << shift,
641-
value: (value & mask) << shift,
642-
associated_register: PhantomData,
554+
macro_rules! FieldValue_impl_for {
555+
($type:ty) => {
556+
// Necessary to split the implementation of new() out because the bitwise
557+
// math isn't treated as const when the type is generic.
558+
// Tracking issue: https://github.com/rust-lang/rfcs/pull/2632
559+
impl<R: RegisterLongName> FieldValue<$type, R> {
560+
pub const fn new(mask: $type, shift: usize, value: $type) -> Self {
561+
FieldValue {
562+
mask: mask << shift,
563+
value: (value & mask) << shift,
564+
associated_register: PhantomData,
565+
}
566+
}
643567
}
644-
}
645-
}
646-
647-
impl<R: RegisterLongName> From<FieldValue<u32, R>> for u32 {
648-
fn from(val: FieldValue<u32, R>) -> u32 {
649-
val.value
650-
}
651-
}
652568

653-
impl<R: RegisterLongName> FieldValue<u64, R> {
654-
pub const fn new(mask: u64, shift: usize, value: u64) -> Self {
655-
FieldValue {
656-
mask: mask << shift,
657-
value: (value & mask) << shift,
658-
associated_register: PhantomData,
569+
// Necessary to split the implementation of From<> out because of the orphan rule
570+
// for foreign trait implementation (see [E0210](https://doc.rust-lang.org/error-index.html#E0210)).
571+
impl<R: RegisterLongName> From<FieldValue<$type, R>> for $type {
572+
fn from(val: FieldValue<$type, R>) -> $type {
573+
val.value
574+
}
659575
}
660-
}
576+
};
661577
}
662578

663-
impl<R: RegisterLongName> From<FieldValue<u64, R>> for u64 {
664-
fn from(val: FieldValue<u64, R>) -> u64 {
665-
val.value
666-
}
667-
}
579+
FieldValue_impl_for!(u8);
580+
FieldValue_impl_for!(u16);
581+
FieldValue_impl_for!(u32);
582+
FieldValue_impl_for!(u64);
583+
FieldValue_impl_for!(u128);
668584

669585
impl<T: IntLike, R: RegisterLongName> FieldValue<T, R> {
670586
/// Get the raw bitmask represented by this FieldValue.

0 commit comments

Comments
 (0)