Skip to content

Commit 11f83aa

Browse files
committed
Fixed v1/v2 compatibility.
v1 -> v2 promotion now implicit, v2 -> v1 regression must be explicit with `.into()`
1 parent da8b3d4 commit 11f83aa

File tree

4 files changed

+131
-20
lines changed

4 files changed

+131
-20
lines changed

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ futures = "0.1.17"
2626

2727
[features]
2828
unproven = ["nb/unstable"]
29-
v1-compat = []
30-
v2-compat = []
3129

3230
[package.metadata.docs.rs]
3331
features = ["unproven"]

src/digital/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Digital I/O
22
//!
33
//!
4+
//!
45
56
// Depreciated / infallible traits
67
#[deprecated(since = "0.2.2", note = "Deprecated because the methods cannot return errors. \
@@ -12,12 +13,12 @@ pub mod v2;
1213

1314
// Compatibility shims, only one can be active at a time to avoid recursive errors
1415

15-
// v2 -> v1 compatibility shims
16-
#[cfg(feature = "v1-compat")]
16+
// v2 -> v1 compatibility wrappers
17+
// These require explicit casts from v2 -> v1
1718
pub mod v1_compat;
1819

1920
// v1 -> v2 compatibility shims
20-
#[cfg(feature = "v2-compat")]
21+
// These are implicit over v1 implementations
2122
pub mod v2_compat;
2223

2324
// Re-export old traits so this isn't a breaking change

src/digital/v1_compat.rs

Lines changed: 89 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,98 @@
1-
//! v1 compatibility shims
1+
//! v1 compatibility wrapper
22
//! this module adds reverse support for v2 digital traits
3-
//! only on of v1_compat or v2_compat may be included at a given time
3+
//! v2 traits must be explicitly cast to the v1 version using `.into()`.
44
55
#[allow(deprecated)]
66
use super::v1;
77
use super::v2;
88

9+
/// Wrapper to allow v2 fallible OutputPin traits to be converted to v1 traits
10+
pub struct OldOutputPin<T> {
11+
pin: T,
12+
}
13+
14+
impl <T, ERR> From<T> for OldOutputPin<T>
15+
where
16+
T: v2::OutputPin<Error=ERR>,
17+
ERR: core::fmt::Debug,
18+
{
19+
fn from(pin: T) -> Self {
20+
OldOutputPin{pin}
21+
}
22+
}
23+
924
/// Implementation of v1 OutputPin trait for v2 fallible output pins
1025
#[allow(deprecated)]
11-
impl <T, ERR> v1::OutputPin for T
26+
impl <T, ERR> v1::OutputPin for OldOutputPin<T>
1227
where
1328
T: v2::OutputPin<Error=ERR>,
1429
ERR: core::fmt::Debug,
1530
{
1631
fn set_low(&mut self) {
17-
self.set_low().unwrap()
32+
self.pin.set_low().unwrap()
1833
}
1934

2035
fn set_high(&mut self) {
21-
self.set_high().unwrap()
36+
self.pin.set_high().unwrap()
2237
}
2338
}
2439

2540
/// Implementation of v1 StatefulOutputPin trait for v2 fallible pins
2641
#[cfg(feature = "unproven")]
2742
#[allow(deprecated)]
28-
impl <T, ERR> v1::StatefulOutputPin for T
43+
impl <T, ERR> v1::StatefulOutputPin for OldOutputPin<T>
2944
where
3045
T: v2::StatefulOutputPin<Error=ERR>,
3146
ERR: core::fmt::Debug,
3247
{
3348
fn is_set_low(&self) -> bool {
34-
self.is_set_low().unwrap()
49+
self.pin.is_set_low().unwrap()
3550
}
3651

3752
fn is_set_high(&self) -> bool {
38-
self.is_set_high().unwrap()
53+
self.pin.is_set_high().unwrap()
54+
}
55+
}
56+
57+
/// Wrapper to allow v2 fallible InputPin traits to be converted to v1 traits
58+
#[cfg(feature = "unproven")]
59+
pub struct OldInputPin<T> {
60+
pin: T,
61+
}
62+
63+
#[cfg(feature = "unproven")]
64+
impl <T, ERR> From<T> for OldInputPin<T>
65+
where
66+
T: v2::InputPin<Error=ERR>,
67+
ERR: core::fmt::Debug,
68+
{
69+
fn from(pin: T) -> Self {
70+
OldInputPin{pin}
3971
}
4072
}
4173

4274
/// Implementation of v0.2 InputPin trait for v0.3 fallible pins
4375
#[cfg(feature = "unproven")]
4476
#[allow(deprecated)]
45-
impl <T, ERR> v1::InputPin for T
77+
impl <T, ERR> v1::InputPin for OldInputPin<T>
4678
where
4779
T: v2::InputPin<Error=ERR>,
4880
ERR: core::fmt::Debug,
4981
{
5082
fn is_low(&self) -> bool {
51-
self.is_low().unwrap()
83+
self.pin.is_low().unwrap()
5284
}
5385

5486
fn is_high(&self) -> bool {
55-
self.is_high().unwrap()
87+
self.pin.is_high().unwrap()
5688
}
5789
}
5890

5991
#[cfg(test)]
6092
#[allow(deprecated)]
6193
mod tests {
94+
use super::*;
95+
6296
#[allow(deprecated)]
6397
use crate::digital::v1;
6498
use crate::digital::v2;
@@ -87,16 +121,57 @@ mod tests {
87121

88122
#[allow(deprecated)]
89123
impl <T>OldOutputPinConsumer<T>
90-
where T: v1::OutputPin {
124+
where T: v1::OutputPin
125+
{
91126
pub fn new(pin: T) -> OldOutputPinConsumer<T> {
92127
OldOutputPinConsumer{ _pin: pin }
93128
}
94129
}
95130

96131
#[test]
97-
fn new_old() {
132+
fn v1_v2_output_explicit() {
98133
let i = NewOutputPinImpl{state: false};
99-
let _c = OldOutputPinConsumer::new(i);
134+
let _c: OldOutputPinConsumer<OldOutputPin<_>> = OldOutputPinConsumer::new(i.into());
135+
}
136+
137+
#[cfg(feature = "unproven")]
138+
struct NewInputPinImpl {
139+
state: bool,
140+
}
141+
142+
#[cfg(feature = "unproven")]
143+
impl v2::InputPin for NewInputPinImpl {
144+
type Error = ();
145+
146+
fn is_low(&self) -> Result<bool, Self::Error> {
147+
Ok(!self.state)
148+
}
149+
fn is_high(&self) -> Result<bool, Self::Error>{
150+
Ok(self.state)
151+
}
152+
}
153+
154+
#[cfg(feature = "unproven")]
155+
#[allow(deprecated)]
156+
struct OldInputPinConsumer<T: v1::InputPin> {
157+
_pin: T,
158+
}
159+
160+
#[cfg(feature = "unproven")]
161+
#[allow(deprecated)]
162+
impl <T>OldInputPinConsumer<T>
163+
where T: v1::InputPin
164+
{
165+
pub fn new(pin: T) -> OldInputPinConsumer<T> {
166+
OldInputPinConsumer{ _pin: pin }
167+
}
168+
}
169+
170+
#[cfg(feature = "unproven")]
171+
#[test]
172+
fn v1_v2_input_explicit() {
173+
let i = NewInputPinImpl{state: false};
174+
let _c: OldInputPinConsumer<OldInputPin<_>> = OldInputPinConsumer::new(i.into());
100175
}
101176

102177
}

src/digital/v2_compat.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,44 @@ mod tests {
9393
}
9494

9595
#[test]
96-
fn old_new() {
96+
fn v2_v1_output_implicit() {
97+
let i = OldOutputPinImpl{state: false};
98+
let _c = NewOutputPinConsumer::new(i);
99+
}
100+
101+
#[cfg(feature = "unproven")]
102+
#[allow(deprecated)]
103+
struct OldInputPinImpl {
104+
state: bool
105+
}
106+
107+
#[cfg(feature = "unproven")]
108+
#[allow(deprecated)]
109+
impl v1::InputPin for OldInputPinImpl {
110+
fn is_low(&self) -> bool {
111+
!self.state
112+
}
113+
fn is_high(&self) -> bool {
114+
self.state
115+
}
116+
}
117+
118+
#[cfg(feature = "unproven")]
119+
struct NewInputPinConsumer<T: v2::InputPin> {
120+
_pin: T,
121+
}
122+
123+
#[cfg(feature = "unproven")]
124+
impl <T>NewInputPinConsumer<T>
125+
where T: v2::InputPin {
126+
pub fn new(pin: T) -> NewInputPinConsumer<T> {
127+
NewInputPinConsumer{ _pin: pin }
128+
}
129+
}
130+
131+
#[cfg(feature = "unproven")]
132+
#[test]
133+
fn v2_v1_input_implicit() {
97134
let i = OldOutputPinImpl{state: false};
98135
let _c = NewOutputPinConsumer::new(i);
99136
}

0 commit comments

Comments
 (0)