Skip to content

Commit 595c6dc

Browse files
committed
Safety helper
1 parent cabb504 commit 595c6dc

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
77

88
## [Unreleased]
99

10-
- Add `WriteEnum` constraint for `FieldWriter`s (fix `variant` safety)
10+
- Add `IsEnum` constraint for `FieldWriter`s (fix `variant` safety)
1111
- Make field writer `bits` always `unsafe` add `set` for safe writing
1212
- Fix bit writer type for `ModifiedWriteValues::ZeroToSet`
1313

src/generate/register.rs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -393,17 +393,22 @@ pub fn render_register_mod(
393393
// * there is a single field that covers the entire register
394394
// * that field can represent all values
395395
// * the write constraints of the register allow full range of values
396-
let can_write_safe = !unsafety(
396+
let safe_ty = if let Safety::Safe = Safety::get(
397397
register
398398
.fields
399399
.as_ref()
400400
.and_then(|fields| fields.first())
401401
.and_then(|field| field.write_constraint)
402402
.as_ref(),
403403
rsize,
404-
) || !unsafety(register.write_constraint.as_ref(), rsize);
405-
let safe_ty = if can_write_safe { "Safe" } else { "Unsafe" };
406-
let safe_ty = Ident::new(safe_ty, span);
404+
) {
405+
Safety::Safe
406+
} else if let Safety::Safe = Safety::get(register.write_constraint.as_ref(), rsize) {
407+
Safety::Safe
408+
} else {
409+
Safety::Unsafe
410+
};
411+
let safe_ty = safe_ty.ident(span);
407412

408413
let doc = format!("`write(|w| ..)` method takes [`{mod_ty}::W`](W) writer structure",);
409414

@@ -1097,7 +1102,7 @@ pub fn fields(
10971102
// the read value, or else we reuse read value.
10981103
if can_write {
10991104
let mut proxy_items = TokenStream::new();
1100-
let mut unsafety = unsafety(f.write_constraint.as_ref(), width);
1105+
let mut safety = Safety::get(f.write_constraint.as_ref(), width);
11011106

11021107
// if we writes to enumeratedValues, generate its structure if it differs from read structure.
11031108
let value_write_ty = if let Some(ev) = rwenum.write_enum() {
@@ -1136,12 +1141,12 @@ pub fn fields(
11361141
if variants.len() == 1 << width {
11371142
} else if let Some(def) = def.take() {
11381143
variants.push(def);
1139-
unsafety = false;
1144+
safety = Safety::Safe;
11401145
}
11411146

11421147
// if the write structure is finite, it can be safely written.
11431148
if variants.len() == 1 << width {
1144-
unsafety = false;
1149+
safety = Safety::Safe;
11451150
}
11461151

11471152
// generate write value structure and From conversation if we can't reuse read value structure.
@@ -1237,13 +1242,12 @@ pub fn fields(
12371242
} else {
12381243
let wproxy = Ident::new("FieldWriter", span);
12391244
let width = &unsuffixed(width);
1240-
if value_write_ty == "u8" && unsafety {
1245+
if value_write_ty == "u8" && safety != Safety::Safe {
12411246
quote! { crate::#wproxy<'a, REG, #width> }
1242-
} else if unsafety {
1247+
} else if safety != Safety::Safe {
12431248
quote! { crate::#wproxy<'a, REG, #width, #value_write_ty> }
12441249
} else {
1245-
let safe_ty =
1246-
Ident::new(if unsafety { "Unsafe" } else { "Safe" }, span);
1250+
let safe_ty = safety.ident(span);
12471251
quote! { crate::#wproxy<'a, REG, #width, #value_write_ty, crate::#safe_ty> }
12481252
}
12491253
};
@@ -1367,22 +1371,40 @@ pub fn fields(
13671371
))
13681372
}
13691373

1370-
fn unsafety(write_constraint: Option<&WriteConstraint>, width: u32) -> bool {
1371-
match &write_constraint {
1372-
Some(&WriteConstraint::Range(range))
1373-
if range.min == 0 && range.max == u64::MAX >> (64 - width) =>
1374-
{
1375-
// the SVD has acknowledged that it's safe to write
1376-
// any value that can fit in the field
1377-
false
1378-
}
1379-
None if width == 1 => {
1380-
// the field is one bit wide, so we assume it's legal to write
1381-
// either value into it or it wouldn't exist; despite that
1382-
// if a writeConstraint exists then respect it
1383-
false
1374+
#[derive(Clone, Debug, PartialEq, Eq)]
1375+
enum Safety {
1376+
Unsafe,
1377+
Safe,
1378+
}
1379+
1380+
impl Safety {
1381+
fn get(write_constraint: Option<&WriteConstraint>, width: u32) -> Self {
1382+
match &write_constraint {
1383+
Some(&WriteConstraint::Range(range))
1384+
if range.min == 0 && range.max == u64::MAX >> (64 - width) =>
1385+
{
1386+
// the SVD has acknowledged that it's safe to write
1387+
// any value that can fit in the field
1388+
Self::Safe
1389+
}
1390+
None if width == 1 => {
1391+
// the field is one bit wide, so we assume it's legal to write
1392+
// either value into it or it wouldn't exist; despite that
1393+
// if a writeConstraint exists then respect it
1394+
Self::Safe
1395+
}
1396+
_ => Self::Unsafe,
13841397
}
1385-
_ => true,
1398+
}
1399+
fn ident(&self, span: Span) -> Ident {
1400+
Ident::new(
1401+
if let Self::Safe = self {
1402+
"Safe"
1403+
} else {
1404+
"Unsafe"
1405+
},
1406+
span,
1407+
)
13861408
}
13871409
}
13881410

0 commit comments

Comments
 (0)