Skip to content

Commit 10bab4f

Browse files
committed
ReadWriteEnum
1 parent ee87aab commit 10bab4f

File tree

2 files changed

+97
-21
lines changed

2 files changed

+97
-21
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](https://semver.org/).
1111
- generic unsafe `W::bits` + safe `W::set`
1212
- Add `base-address-shift` config flag
1313
- Use `PascalCase` for type idents, fix case changing bugs, add `--ident-format` (`-f`) option flag
14-
- Add `enum_read_name` for `read-only` enums
14+
- Add `enum_read_name` for `read-only` enums, `RWEnum` helper
1515

1616
## [v0.31.5] - 2024-01-04
1717

src/generate/register.rs

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,71 @@ fn render_register_mod_debug(
510510
Ok(r_debug_impl)
511511
}
512512

513+
type EV = (EnumeratedValues, Option<EnumPath>);
514+
515+
pub enum RWEnum<'a> {
516+
ReadAndWriteEnum(&'a EV),
517+
ReadEnumWriteEnum(&'a EV, &'a EV),
518+
ReadEnumWriteRaw(&'a EV),
519+
ReadRawWriteEnum(&'a EV),
520+
ReadEnum(&'a EV),
521+
ReadRaw,
522+
WriteEnum(&'a EV),
523+
WriteRaw,
524+
ReadRawWriteRaw,
525+
}
526+
impl<'a> RWEnum<'a> {
527+
pub fn different_enums(&self) -> bool {
528+
matches!(self, Self::ReadEnumWriteEnum(_, _))
529+
}
530+
pub fn read_write(&self) -> bool {
531+
matches!(
532+
self,
533+
Self::ReadAndWriteEnum(_)
534+
| Self::ReadEnumWriteEnum(_, _)
535+
| Self::ReadEnumWriteRaw(_)
536+
| Self::ReadRawWriteEnum(_)
537+
| Self::ReadRawWriteRaw
538+
)
539+
}
540+
pub fn read_only(&self) -> bool {
541+
matches!(self, Self::ReadEnum(_) | Self::ReadRaw)
542+
}
543+
pub fn can_read(&self) -> bool {
544+
self.read_write() || self.read_only()
545+
}
546+
pub fn write_only(&self) -> bool {
547+
matches!(self, Self::WriteEnum(_) | Self::WriteRaw)
548+
}
549+
pub fn can_write(&self) -> bool {
550+
self.read_write() || self.write_only()
551+
}
552+
pub fn read_enum(&self) -> Option<&'a EV> {
553+
match *self {
554+
Self::ReadAndWriteEnum(e)
555+
| Self::ReadEnumWriteEnum(e, _)
556+
| Self::ReadEnumWriteRaw(e)
557+
| Self::ReadEnum(e) => Some(e),
558+
_ => None,
559+
}
560+
}
561+
pub fn write_enum(&self) -> Option<&'a EV> {
562+
match *self {
563+
Self::ReadAndWriteEnum(e)
564+
| Self::ReadEnumWriteEnum(_, e)
565+
| Self::ReadRawWriteEnum(e)
566+
| Self::WriteEnum(e) => Some(e),
567+
_ => None,
568+
}
569+
}
570+
pub fn gen_write_enum(&self) -> bool {
571+
matches!(
572+
self,
573+
Self::ReadEnumWriteEnum(_, _) | Self::ReadRawWriteEnum(_) | Self::WriteEnum(_)
574+
)
575+
}
576+
}
577+
513578
#[allow(clippy::too_many_arguments)]
514579
pub fn fields(
515580
mut fields: Vec<&Field>,
@@ -612,14 +677,25 @@ pub fn fields(
612677
lookup_results.push((ev, epath));
613678
}
614679

615-
let read_enum = lookup_filter(&lookup_results, Usage::Read);
616-
let write_enum = lookup_filter(&lookup_results, Usage::Write);
617-
618-
// does the read and the write value has the same name? If we have the same,
619-
// we can reuse read value type other than generating a new one.
620-
let writer_reader_different_enum = !(can_read
621-
&& can_write
622-
&& matches!((read_enum, write_enum), (Some(e1), Some(e2)) if e1.0 == e2.0));
680+
let rwenum = match (
681+
can_read,
682+
lookup_filter(&lookup_results, Usage::Read),
683+
can_write,
684+
lookup_filter(&lookup_results, Usage::Write),
685+
) {
686+
(true, Some(e1), true, Some(e2)) if e1.0 == e2.0 => RWEnum::ReadAndWriteEnum(e1),
687+
(true, Some(e1), true, Some(e2)) => RWEnum::ReadEnumWriteEnum(e1, e2),
688+
(true, Some(e), true, None) => RWEnum::ReadEnumWriteRaw(e),
689+
(true, None, true, Some(e)) => RWEnum::ReadRawWriteEnum(e),
690+
(true, Some(e), false, _) => RWEnum::ReadEnum(e),
691+
(true, None, false, _) => RWEnum::ReadRaw,
692+
(false, _, true, Some(e)) => RWEnum::WriteEnum(e),
693+
(false, _, true, None) => RWEnum::WriteRaw,
694+
(true, _, true, _) => RWEnum::ReadRawWriteRaw,
695+
(false, _, false, _) => {
696+
return Err(anyhow!("Field {fpath} is not writtable or readable"))
697+
}
698+
};
623699

624700
let brief_suffix = if let Field::Array(_, de) = &f {
625701
if let Some(range) = de.indexes_as_range() {
@@ -659,8 +735,8 @@ pub fn fields(
659735

660736
// get the type of value structure. It can be generated from either name field
661737
// in enumeratedValues if it's an enumeration, or from field name directly if it's not.
662-
let value_read_ty = if let Some((evs, _)) = read_enum {
663-
let fmt = if writer_reader_different_enum {
738+
let value_read_ty = if let Some((evs, _)) = rwenum.read_enum() {
739+
let fmt = if rwenum.different_enums() {
664740
"enum_read_name"
665741
} else {
666742
"enum_name"
@@ -680,7 +756,7 @@ pub fn fields(
680756
// information in enumeratedValues;
681757
// if it's not enumeratedValues, always derive the read proxy as we do not need to re-export
682758
// it again from BitReader or FieldReader.
683-
let should_derive_reader = matches!(read_enum, Some((_, None)) | None);
759+
let should_derive_reader = matches!(rwenum.read_enum(), Some((_, None)) | None);
684760

685761
// derive the read proxy structure if necessary.
686762
if should_derive_reader {
@@ -715,7 +791,7 @@ pub fn fields(
715791

716792
// if this is an enumeratedValues not derived from base, generate the enum structure
717793
// and implement functions for each value in enumeration.
718-
if let Some((evs, None)) = read_enum {
794+
if let Some((evs, None)) = rwenum.read_enum() {
719795
// parse enum variants from enumeratedValues svd record
720796
let mut variants = Variant::from_enumerated_values(evs, config)?;
721797

@@ -855,7 +931,7 @@ pub fn fields(
855931

856932
// if this value is derived from a base, generate `pub use` code for each read proxy and value
857933
// if necessary.
858-
if let Some((_, Some(base))) = read_enum {
934+
if let Some((_, Some(base))) = rwenum.read_enum() {
859935
// generate pub use field_1 reader as field_2 reader
860936
let base_field = util::replace_suffix(&base.field.name, "");
861937
let base_r = ident(&base_field, config, "field_reader", span);
@@ -966,8 +1042,8 @@ pub fn fields(
9661042
// gets a brief of write proxy
9671043
let field_writer_brief = format!("Field `{name}{brief_suffix}` writer - {description}");
9681044

969-
let value_write_ty = if let Some((evs, _)) = write_enum {
970-
let fmt = if writer_reader_different_enum {
1045+
let value_write_ty = if let Some((evs, _)) = rwenum.write_enum() {
1046+
let fmt = if rwenum.different_enums() {
9711047
"enum_write_name"
9721048
} else {
9731049
"enum_name"
@@ -985,7 +1061,7 @@ pub fn fields(
9851061
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);
9861062

9871063
// if we writes to enumeratedValues, generate its structure if it differs from read structure.
988-
if let Some((evs, None)) = write_enum {
1064+
if let Some((evs, None)) = rwenum.write_enum() {
9891065
// parse variants from enumeratedValues svd record
9901066
let mut variants = Variant::from_enumerated_values(evs, config)?;
9911067
let map = enums_to_map(evs);
@@ -1007,7 +1083,7 @@ pub fn fields(
10071083
}
10081084

10091085
// generate write value structure and From conversation if we can't reuse read value structure.
1010-
if writer_reader_different_enum {
1086+
if rwenum.gen_write_enum() {
10111087
if variants.is_empty() {
10121088
add_with_no_variants(
10131089
mod_items,
@@ -1047,7 +1123,7 @@ pub fn fields(
10471123

10481124
// derive writer. We derive writer if the write proxy is in current register module,
10491125
// or writer in different register have different _SPEC structures
1050-
let should_derive_writer = matches!(write_enum, Some((_, None)) | None);
1126+
let should_derive_writer = matches!(rwenum.write_enum(), Some((_, None)) | None);
10511127

10521128
// derive writer structure by type alias to generic write proxy structure.
10531129
if should_derive_writer {
@@ -1116,7 +1192,7 @@ pub fn fields(
11161192
});
11171193
}
11181194

1119-
if let Some((_, Some(base))) = write_enum {
1195+
if let Some((_, Some(base))) = rwenum.write_enum() {
11201196
// if base.register == None, derive write from the same module. This is allowed because both
11211197
// the generated and source write proxy are in the same module.
11221198
// we never reuse writer for writer in different module does not have the same _SPEC strcuture,
@@ -1135,7 +1211,7 @@ pub fn fields(
11351211
}
11361212
// if base.register == None, it emits pub use structure from same module.
11371213
if base.register() != fpath.register() {
1138-
if writer_reader_different_enum {
1214+
if rwenum.gen_write_enum() {
11391215
// use the same enum structure name
11401216
if !writer_enum_derives.contains(&value_write_ty) {
11411217
let base_path = base_syn_path(base, &fpath, &value_write_ty, config)?;

0 commit comments

Comments
 (0)