/
ref_drone.rs
155 lines (134 loc) · 3.76 KB
/
ref_drone.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use std::marker::PhantomData;
pub trait DroneState: sealed::Sealed {}
pub struct Drone<'a, State>
where
State: DroneState,
{
inner: &'a mut InnerDrone,
state: PhantomData<State>,
}
pub struct InnerDrone {
x: f32,
y: f32,
}
impl InnerDrone {
fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
}
pub struct Idle;
impl DroneState for Idle {}
pub struct Hovering;
impl DroneState for Hovering {}
pub struct Flying;
impl DroneState for Flying {}
mod sealed {
pub trait Sealed {}
impl Sealed for super::Idle {}
impl Sealed for super::Hovering {}
impl Sealed for super::Flying {}
}
impl<'a> Drone<'a, Idle> {
pub fn new(inner : &'a mut InnerDrone) -> Self {
Self {
inner,
state: PhantomData,
}
}
pub fn take_off(self) -> Drone<'a, Hovering> {
Drone::<Hovering>::from(self)
}
}
impl<'a> Drone<'a, Hovering> {
fn land(self) -> Drone<'a, Idle> {
Drone::<Idle>::from(self)
}
// &self == self -> Self
// using self as a reference is the same as consuming self to return it
// however, if the state transitions inside the function,
// we are required to consume and return
fn move_to(self, x: f32, y: f32) -> Drone<'a, Hovering> {
let drone = Drone::<Flying>::from(self);
drone.fly(x, y)
}
}
// This implements a bidirectional conversion from Drone<Idle> to Drone<Hovering>
impl<'a> From<Drone<'a, Idle>> for Drone<'a, Hovering> {
fn from(drone: Drone<'a, Idle>) -> Self {
Self {
inner: drone.inner,
state: PhantomData,
}
}
}
impl<'a> From<Drone<'a, Hovering>> for Drone<'a, Idle> {
fn from(drone: Drone<'a, Hovering>) -> Self {
Self {
inner: drone.inner,
state: PhantomData,
}
}
}
impl<'a> From<Drone<'a, Hovering>> for Drone<'a, Flying> {
fn from(drone: Drone<'a, Hovering>) -> Self {
Self {
inner: drone.inner,
state: PhantomData,
}
}
}
impl<'a> From<Drone<'a, Flying>> for Drone<'a, Hovering> {
fn from(drone: Drone<'a, Flying>) -> Self {
Self {
inner: drone.inner,
state: PhantomData,
}
}
}
impl<'a> Drone<'a, Flying> {
fn has_arrived(&self, x: f32, y: f32) -> bool {
return self.inner.x == x && self.inner.y == y;
}
fn fly(mut self, x: f32, y: f32) -> Drone<'a, Hovering> {
self.inner.x = x;
self.inner.y = y;
Drone::<Hovering>::from(self)
}
}
#[cfg(test)]
mod drone_test {
use super::*;
#[test]
fn drone_spawns_idle() {
let mut inner = InnerDrone::new(0.0, 0.0);
let drone = Drone::<Idle>::new(&mut inner);
assert_eq!(drone.inner.x, 0.0);
assert_eq!(drone.inner.y, 0.0);
}
#[test]
fn drone_takes_off_n_lands() {
let mut inner = InnerDrone::new(0.0, 0.0);
let drone = Drone::<Idle>::new(&mut inner);
let drone = drone.take_off();
assert_eq!(drone.inner.x, 0.0);
assert_eq!(drone.inner.y, 0.0);
drone.land();
}
#[test]
fn drone_flies() {
let mut inner = InnerDrone::new(0.0, 0.0);
let drone = Drone::<Idle>::new(&mut inner).take_off().move_to(-5.0, -5.0).land();
assert_eq!(drone.inner.x, -5.0);
assert_eq!(drone.inner.y, -5.0);
}
#[test]
fn drone_does_not_fly_idle() {
let mut inner = InnerDrone::new(0.0, 0.0);
let drone = Drone::<Idle>::new(&mut inner);
// drone.move_to(10.0, 10.0); // comptime error: "move_to" is not a member of type Idle
assert_eq!(drone.inner.x, 0.0);
assert_eq!(drone.inner.y, 0.0);
}
}
// struct NotDroneState;
// impl Drone<NotDroneState> {} // NotDroneState does not satisfy trait DroneState