Skip to content

Commit 04304ac

Browse files
bors[bot]burrbull
andauthored
Merge #140
140: non_exhaustive structures r=adamgreig a=burrbull Up MSRV to 1.40 Co-authored-by: Andrey Zgarbul <zgarbul.andrey@gmail.com>
2 parents 3ec0906 + fcd389b commit 04304ac

18 files changed

+102
-96
lines changed

.github/workflows/ci.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
continue-on-error: ${{ matrix.experimental || false }}
1313
strategy:
1414
matrix:
15-
rust: [ 1.36.0, stable ]
15+
rust: [ 1.40.0, stable ]
1616
include:
1717
# Test nightly but don't fail the build.
1818
- rust: nightly
@@ -44,3 +44,19 @@ jobs:
4444
- uses: actions-rs/cargo@v1
4545
with:
4646
command: test
47+
48+
test strict:
49+
runs-on: ubuntu-latest
50+
steps:
51+
- name: Checkout repository
52+
uses: actions/checkout@v2
53+
- name: Install Rust
54+
uses: actions-rs/toolchain@v1
55+
with:
56+
toolchain: stable
57+
profile: minimal
58+
override: true
59+
- uses: actions-rs/cargo@v1
60+
with:
61+
command: test
62+
args: --all-features

.github/workflows/clippy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: actions-rs/toolchain@v1
1313
with:
1414
profile: minimal
15-
toolchain: 1.36.0
15+
toolchain: stable
1616
override: true
1717
components: clippy
1818
- uses: actions-rs/clippy-check@v1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ This project is developed and maintained by the [Tools team][team].
1313

1414
## Minimum Supported Rust Version (MSRV)
1515

16-
This crate is guaranteed to compile on stable Rust 1.36.0 and up. It *might*
16+
This crate is guaranteed to compile on stable Rust 1.40.0 and up. It *might*
1717
compile with older versions but that may change in any new patch release.
1818

1919
## License

src/elementext.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ impl ElementExt for Element {
4040
Err(e) => match e.downcast_ref() {
4141
// if tag is empty just ignore it
4242
Some(SVDError::EmptyTag(_, _)) => Ok(None),
43-
_ => return Err(e),
43+
_ => Err(e),
4444
},
45-
Ok(s) => Ok(Some(s.to_owned())),
45+
Ok(s) => Ok(Some(s)),
4646
}
4747
} else {
4848
Ok(None)

src/error.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
44
pub use anyhow::{Context, Result};
55
use core::u64;
6+
#[cfg(feature = "strict")]
67
use once_cell::sync::Lazy;
8+
#[cfg(feature = "strict")]
79
use regex::Regex;
810
use xmltree::Element;
911

10-
#[allow(clippy::large_enum_variant)]
12+
#[allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
1113
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
1214
pub enum SVDError {
1315
#[error("Unknown endianness `{0}`")]
@@ -87,6 +89,7 @@ pub enum ResetValueError {
8789
MaskTooLarge(u64, u32),
8890
}
8991

92+
#[cfg(feature = "strict")]
9093
pub(crate) fn check_name(name: &str, tag: &str) -> Result<()> {
9194
static PATTERN: Lazy<Regex> = Lazy::new(|| Regex::new("^[_A-Za-z0-9]*$").unwrap());
9295
if PATTERN.is_match(name) {
@@ -98,6 +101,7 @@ pub(crate) fn check_name(name: &str, tag: &str) -> Result<()> {
98101
}
99102
}
100103

104+
#[cfg(feature = "strict")]
101105
pub(crate) fn check_dimable_name(name: &str, tag: &str) -> Result<()> {
102106
static PATTERN: Lazy<Regex> = Lazy::new(|| {
103107
Regex::new("^(((%s)|(%s)[_A-Za-z]{1}[_A-Za-z0-9]*)|([_A-Za-z]{1}[_A-Za-z0-9]*(\\[%s\\])?)|([_A-Za-z]{1}[_A-Za-z0-9]*(%s)?[_A-Za-z0-9]*))$").unwrap()
@@ -117,6 +121,7 @@ pub(crate) fn check_has_placeholder(name: &str, tag: &str) -> Result<()> {
117121
}
118122
}
119123

124+
#[cfg(feature = "strict")]
120125
pub(crate) fn check_derived_name(name: &str, tag: &str) -> Result<()> {
121126
for x in name.split('.') {
122127
check_dimable_name(x, tag)?
@@ -127,7 +132,7 @@ pub(crate) fn check_derived_name(name: &str, tag: &str) -> Result<()> {
127132
pub(crate) fn check_reset_value(
128133
size: Option<u32>,
129134
value: Option<u64>,
130-
mask: Option<u64>,
135+
_mask: Option<u64>,
131136
) -> Result<()> {
132137
const MAX_BITS: u32 = u64::MAX.count_ones();
133138

@@ -136,14 +141,17 @@ pub(crate) fn check_reset_value(
136141
return Err(ResetValueError::ValueTooLarge(value, size).into());
137142
}
138143
}
139-
if let (Some(size), Some(mask)) = (size, mask) {
140-
if MAX_BITS - mask.leading_zeros() > size {
141-
return Err(ResetValueError::MaskTooLarge(mask, size).into());
144+
#[cfg(feature = "strict")]
145+
{
146+
if let (Some(size), Some(mask)) = (size, _mask) {
147+
if MAX_BITS - mask.leading_zeros() > size {
148+
return Err(ResetValueError::MaskTooLarge(mask, size).into());
149+
}
142150
}
143-
}
144-
if let (Some(value), Some(mask)) = (value, mask) {
145-
if value & mask != value {
146-
return Err(ResetValueError::MaskConflict(value, mask).into());
151+
if let (Some(value), Some(mask)) = (value, _mask) {
152+
if value & mask != value {
153+
return Err(ResetValueError::MaskConflict(value, mask).into());
154+
}
147155
}
148156
}
149157

src/lib.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@
88
//! use std::fs::File;
99
//! use std::io::Read;
1010
//!
11-
//! fn main() {
12-
//! let xml = &mut String::new();
13-
//! File::open("STM32F30x.svd").unwrap().read_to_string(xml);
11+
//! let xml = &mut String::new();
12+
//! File::open("STM32F30x.svd").unwrap().read_to_string(xml);
1413
//!
15-
//! println!("{:?}", svd::parse(xml));
16-
//! }
14+
//! println!("{:?}", svd::parse(xml));
1715
//! ```
1816
//!
1917
//! # References

src/parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub trait Parse {
1616
/// Parses an optional child element with the provided name and Parse function
1717
/// Returns an none if the child doesn't exist, Ok(Some(e)) if parsing succeeds,
1818
/// and Err() if parsing fails.
19-
pub fn optional<'a, T>(n: &str, e: &'a Element) -> anyhow::Result<Option<T::Object>>
19+
pub fn optional<T>(n: &str, e: &Element) -> anyhow::Result<Option<T::Object>>
2020
where
2121
T: Parse<Error = anyhow::Error>,
2222
{

src/svd/clusterinfo.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::svd::{registercluster::RegisterCluster, registerproperties::RegisterP
1111

1212
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1313
#[derive(Clone, Debug, PartialEq)]
14+
#[non_exhaustive]
1415
pub struct ClusterInfo {
1516
/// String to identify the cluster.
1617
/// Cluster names are required to be unique within the scope of a peripheral
@@ -38,10 +39,6 @@ pub struct ClusterInfo {
3839
pub default_register_properties: RegisterProperties,
3940

4041
pub children: Vec<RegisterCluster>,
41-
42-
// Reserve the right to add more fields to this struct
43-
#[cfg_attr(feature = "serde", serde(skip))]
44-
_extensible: (),
4542
}
4643

4744
#[derive(Clone, Debug, Default, PartialEq)]
@@ -99,17 +96,19 @@ impl ClusterInfoBuilder {
9996
children: self
10097
.children
10198
.ok_or_else(|| BuildError::Uninitialized("children".to_string()))?,
102-
_extensible: (),
10399
})
104100
.validate()
105101
}
106102
}
107103

108104
impl ClusterInfo {
105+
#[allow(clippy::unnecessary_wraps)]
109106
fn validate(self) -> Result<Self> {
107+
#[cfg(feature = "strict")]
110108
check_dimable_name(&self.name, "name")?;
111-
if let Some(name) = self.derived_from.as_ref() {
112-
check_derived_name(name, "derivedFrom")?;
109+
if let Some(_name) = self.derived_from.as_ref() {
110+
#[cfg(feature = "strict")]
111+
check_derived_name(_name, "derivedFrom")?;
113112
} else if self.children.is_empty() {
114113
#[cfg(feature = "strict")]
115114
return Err(SVDError::EmptyCluster)?;

src/svd/cpu.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::types::Parse;
1212

1313
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1414
#[derive(Clone, Debug, PartialEq)]
15+
#[non_exhaustive]
1516
pub struct Cpu {
1617
pub name: String,
1718

@@ -32,10 +33,6 @@ pub struct Cpu {
3233

3334
/// Indicate whether the processor implements a vendor-specific System Tick Timer
3435
pub has_vendor_systick: bool,
35-
36-
// Reserve the right to add more fields to this struct
37-
#[cfg_attr(feature = "serde", serde(skip))]
38-
_extensible: (),
3936
}
4037

4138
#[derive(Clone, Debug, Default, PartialEq)]
@@ -101,13 +98,13 @@ impl CpuBuilder {
10198
has_vendor_systick: self
10299
.has_vendor_systick
103100
.ok_or_else(|| BuildError::Uninitialized("has_vendor_systick".to_string()))?,
104-
_extensible: (),
105101
})
106102
.validate()
107103
}
108104
}
109105

110106
impl Cpu {
107+
#[allow(clippy::unnecessary_wraps)]
111108
fn validate(self) -> Result<Self> {
112109
// TODO
113110
Ok(self)

src/svd/device.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::svd::{cpu::Cpu, peripheral::Peripheral, registerproperties::RegisterP
1515

1616
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1717
#[derive(Clone, Debug, PartialEq)]
18+
#[non_exhaustive]
1819
pub struct Device {
1920
/// The string identifies the device or device series. Device names are required to be unique
2021
pub name: String,
@@ -53,10 +54,6 @@ pub struct Device {
5354
pub peripherals: Vec<Peripheral>,
5455

5556
pub default_register_properties: RegisterProperties,
56-
57-
// Reserve the right to add more fields to this struct
58-
#[cfg_attr(feature = "serde", serde(skip))]
59-
_extensible: (),
6057
}
6158

6259
#[derive(Clone, Debug, Default)]
@@ -124,7 +121,6 @@ impl DeviceBuilder {
124121
.peripherals
125122
.ok_or_else(|| BuildError::Uninitialized("peripherals".to_string()))?,
126123
default_register_properties: self.default_register_properties,
127-
_extensible: (),
128124
})
129125
.validate()
130126
}
@@ -134,7 +130,7 @@ impl Device {
134130
fn validate(self) -> Result<Self> {
135131
// TODO
136132
if self.peripherals.is_empty() {
137-
return Err(SVDError::EmptyDevice)?;
133+
return Err(SVDError::EmptyDevice.into());
138134
}
139135
Ok(self)
140136
}

src/svd/dimelement.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::error::*;
1010

1111
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1212
#[derive(Clone, Debug, PartialEq)]
13+
#[non_exhaustive]
1314
pub struct DimElement {
1415
/// Defines the number of elements in an array or list
1516
pub dim: u32,
@@ -22,10 +23,6 @@ pub struct DimElement {
2223
#[cfg_attr(feature = "serde", serde(default))]
2324
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2425
pub dim_index: Option<Vec<String>>,
25-
26-
// Reserve the right to add more fields to this struct
27-
#[cfg_attr(feature = "serde", serde(skip))]
28-
_extensible: (),
2926
}
3027

3128
#[derive(Clone, Debug, Default, PartialEq)]
@@ -57,7 +54,6 @@ impl DimElementBuilder {
5754
.dim_increment
5855
.ok_or_else(|| BuildError::Uninitialized("dim_increment".to_string()))?,
5956
dim_index: self.dim_index,
60-
_extensible: (),
6157
})
6258
}
6359
}

src/svd/enumeratedvalue.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::types::Parse;
1111

1212
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1313
#[derive(Clone, Debug, PartialEq)]
14+
#[non_exhaustive]
1415
pub struct EnumeratedValue {
1516
/// String describing the semantics of the value. Can be displayed instead of the value
1617
pub name: String,
@@ -29,10 +30,6 @@ pub struct EnumeratedValue {
2930
#[cfg_attr(feature = "serde", serde(default))]
3031
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
3132
pub is_default: Option<bool>,
32-
33-
// Reserve the right to add more fields to this struct
34-
#[cfg_attr(feature = "serde", serde(skip))]
35-
_extensible: (),
3633
}
3734

3835
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
@@ -77,14 +74,14 @@ impl EnumeratedValueBuilder {
7774
description: self.description,
7875
value: self.value,
7976
is_default: self.is_default,
80-
_extensible: (),
8177
})
8278
.validate()
8379
}
8480
}
8581

8682
impl EnumeratedValue {
8783
fn validate(self) -> Result<Self> {
84+
#[cfg(feature = "strict")]
8885
check_name(&self.name, "name")?;
8986
match (&self.value, &self.is_default) {
9087
(Some(_), None) | (None, Some(_)) => Ok(self),

src/svd/enumeratedvalues.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::types::Parse;
1313

1414
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1515
#[derive(Clone, Debug, PartialEq)]
16+
#[non_exhaustive]
1617
pub struct EnumeratedValues {
1718
/// Identifier for the whole enumeration section
1819
#[cfg_attr(feature = "serde", serde(default))]
@@ -30,10 +31,6 @@ pub struct EnumeratedValues {
3031
pub derived_from: Option<String>,
3132

3233
pub values: Vec<EnumeratedValue>,
33-
34-
// Reserve the right to add more fields to this struct
35-
#[cfg_attr(feature = "serde", serde(skip))]
36-
_extensible: (),
3734
}
3835

3936
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
@@ -73,19 +70,22 @@ impl EnumeratedValuesBuilder {
7370
usage: self.usage,
7471
derived_from: self.derived_from,
7572
values: self.values.unwrap_or_default(),
76-
_extensible: (),
7773
})
7874
.validate()
7975
}
8076
}
8177

8278
impl EnumeratedValues {
8379
fn validate(self) -> Result<Self> {
84-
if let Some(name) = self.name.as_ref() {
85-
check_name(name, "name")?;
80+
#[cfg(feature = "strict")]
81+
{
82+
if let Some(name) = self.name.as_ref() {
83+
check_name(name, "name")?;
84+
}
8685
}
87-
if let Some(dname) = self.derived_from.as_ref() {
88-
check_derived_name(dname, "derivedFrom")?;
86+
if let Some(_dname) = self.derived_from.as_ref() {
87+
#[cfg(feature = "strict")]
88+
check_derived_name(_dname, "derivedFrom")?;
8989
Ok(self)
9090
} else if self.values.is_empty() {
9191
Err(EnumeratedValuesError::Empty.into())

0 commit comments

Comments
 (0)