@@ -80,84 +80,80 @@ impl PortWrite for u32 {
80
80
}
81
81
}
82
82
83
- /// A read only I/O port.
84
- pub struct PortReadOnly < T > {
85
- port : u16 ,
86
- phantom : PhantomData < T > ,
83
+ mod sealed {
84
+ pub trait Access {
85
+ const DEBUG_NAME : & ' static str ;
86
+ }
87
87
}
88
88
89
- /// A write only I/O port.
90
- pub struct PortWriteOnly < T > {
91
- port : u16 ,
92
- phantom : PhantomData < T > ,
93
- }
89
+ /// A marker trait for access types which allow reading port values.
90
+ pub trait PortReadAccess : sealed:: Access { }
94
91
95
- /// An I/O port.
96
- pub struct Port < T > {
97
- port : u16 ,
98
- phantom : PhantomData < T > ,
99
- }
92
+ /// A marker trait for access types which allow writing port values.
93
+ pub trait PortWriteAccess : sealed:: Access { }
100
94
101
- impl < T > PortReadOnly < T > {
102
- /// Creates a read only I/O port with the given port number.
103
- #[ inline]
104
- pub const fn new ( port : u16 ) -> PortReadOnly < T > {
105
- PortReadOnly {
106
- port,
107
- phantom : PhantomData ,
108
- }
109
- }
95
+ /// An access marker type indicating that a port is only allowed to read values.
96
+ #[ derive( Debug ) ]
97
+ pub struct ReadOnlyAccess ( ( ) ) ;
98
+
99
+ impl sealed:: Access for ReadOnlyAccess {
100
+ const DEBUG_NAME : & ' static str = "ReadOnly" ;
110
101
}
102
+ impl PortReadAccess for ReadOnlyAccess { }
111
103
112
- impl < T : PortRead > PortReadOnly < T > {
113
- /// Reads from the port.
114
- ///
115
- /// ## Safety
116
- ///
117
- /// This function is unsafe because the I/O port could have side effects that violate memory
118
- /// safety.
119
- #[ inline]
120
- pub unsafe fn read ( & mut self ) -> T {
121
- T :: read_from_port ( self . port )
122
- }
104
+ /// An access marker type indicating that a port is only allowed to write values.
105
+ #[ derive( Debug ) ]
106
+ pub struct WriteOnlyAccess ( ( ) ) ;
107
+
108
+ impl sealed:: Access for WriteOnlyAccess {
109
+ const DEBUG_NAME : & ' static str = "WriteOnly" ;
123
110
}
111
+ impl PortWriteAccess for WriteOnlyAccess { }
124
112
125
- impl < T > PortWriteOnly < T > {
126
- /// Creates a write only I/O port with the given port number.
127
- #[ inline]
128
- pub const fn new ( port : u16 ) -> PortWriteOnly < T > {
129
- PortWriteOnly {
130
- port,
131
- phantom : PhantomData ,
132
- }
133
- }
113
+ /// An access marker type indicating that a port is allowed to read or write values.
114
+ #[ derive( Debug ) ]
115
+ pub struct ReadWriteAccess ( ( ) ) ;
116
+
117
+ impl sealed:: Access for ReadWriteAccess {
118
+ const DEBUG_NAME : & ' static str = "ReadWrite" ;
134
119
}
120
+ impl PortReadAccess for ReadWriteAccess { }
121
+ impl PortWriteAccess for ReadWriteAccess { }
135
122
136
- impl < T : PortWrite > PortWriteOnly < T > {
137
- /// Writes to the port.
138
- ///
139
- /// ## Safety
140
- ///
141
- /// This function is unsafe because the I/O port could have side effects that violate memory
142
- /// safety.
143
- # [ inline ]
144
- pub unsafe fn write ( & mut self , value : T ) {
145
- T :: write_to_port ( self . port , value )
146
- }
123
+ /// An I/O port.
124
+ ///
125
+ /// The port reads or writes values of type `T` and has read/write access specified by `A`.
126
+ ///
127
+ /// Use the provided marker types or aliases to get a port type with the access you need:
128
+ /// * `PortGeneric<T, ReadWriteAccess>` -> `Port<T>`
129
+ /// * `PortGeneric<T, ReadOnlyAccess>` -> `PortReadOnly<T>`
130
+ /// * `PortGeneric<T, WriteOnlyAccess>` -> `PortWriteOnly<T>`
131
+ pub struct PortGeneric < T , A > {
132
+ port : u16 ,
133
+ phantom : PhantomData < ( T , A ) > ,
147
134
}
148
135
149
- impl < T > Port < T > {
136
+ /// A read-write I/O port.
137
+ pub type Port < T > = PortGeneric < T , ReadWriteAccess > ;
138
+
139
+ /// A read-only I/O port.
140
+ pub type PortReadOnly < T > = PortGeneric < T , ReadOnlyAccess > ;
141
+
142
+ /// A write-only I/O port.
143
+ pub type PortWriteOnly < T > = PortGeneric < T , WriteOnlyAccess > ;
144
+
145
+ impl < T , A > PortGeneric < T , A > {
150
146
/// Creates an I/O port with the given port number.
151
147
#[ inline]
152
- pub const fn new ( port : u16 ) -> Port < T > {
153
- Port {
148
+ pub const fn new ( port : u16 ) -> PortGeneric < T , A > {
149
+ PortGeneric {
154
150
port,
155
151
phantom : PhantomData ,
156
152
}
157
153
}
158
154
}
159
155
160
- impl < T : PortRead > Port < T > {
156
+ impl < T : PortRead , A : PortReadAccess > PortGeneric < T , A > {
161
157
/// Reads from the port.
162
158
///
163
159
/// ## Safety
@@ -170,7 +166,7 @@ impl<T: PortRead> Port<T> {
170
166
}
171
167
}
172
168
173
- impl < T : PortWrite > Port < T > {
169
+ impl < T : PortWrite , A : PortWriteAccess > PortGeneric < T , A > {
174
170
/// Writes to the port.
175
171
///
176
172
/// ## Safety
@@ -183,35 +179,29 @@ impl<T: PortWrite> Port<T> {
183
179
}
184
180
}
185
181
186
- macro_rules! impl_port_util_traits {
187
- ( $struct_name: ident) => {
188
- impl <T > fmt:: Debug for $struct_name<T > {
189
- fn fmt( & self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
190
- f. debug_struct( stringify!( $struct_name) )
191
- . field( "port" , & self . port)
192
- . finish( )
193
- }
194
- }
195
-
196
- impl <T > Clone for $struct_name<T > {
197
- fn clone( & self ) -> Self {
198
- Self {
199
- port: self . port,
200
- phantom: PhantomData ,
201
- }
202
- }
203
- }
182
+ impl < T , A : sealed:: Access > fmt:: Debug for PortGeneric < T , A > {
183
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
184
+ f. debug_struct ( "PortGeneric" )
185
+ . field ( "port" , & self . port )
186
+ . field ( "size" , & core:: mem:: size_of :: < T > ( ) )
187
+ . field ( "access" , & format_args ! ( "{}" , A :: DEBUG_NAME ) )
188
+ . finish ( )
189
+ }
190
+ }
204
191
205
- impl <T > PartialEq for $struct_name<T > {
206
- fn eq( & self , other: & Self ) -> bool {
207
- self . port == other. port
208
- }
192
+ impl < T , A > Clone for PortGeneric < T , A > {
193
+ fn clone ( & self ) -> Self {
194
+ Self {
195
+ port : self . port ,
196
+ phantom : PhantomData ,
209
197
}
198
+ }
199
+ }
210
200
211
- impl <T > Eq for $struct_name<T > { }
212
- } ;
201
+ impl < T , A > PartialEq for PortGeneric < T , A > {
202
+ fn eq ( & self , other : & Self ) -> bool {
203
+ self . port == other. port
204
+ }
213
205
}
214
206
215
- impl_port_util_traits ! ( Port ) ;
216
- impl_port_util_traits ! ( PortReadOnly ) ;
217
- impl_port_util_traits ! ( PortWriteOnly ) ;
207
+ impl < T , A > Eq for PortGeneric < T , A > { }
0 commit comments