@@ -80,84 +80,80 @@ impl PortWrite for u32 {
8080 }
8181}
8282
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+ }
8787}
8888
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 { }
9491
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 { }
10094
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" ;
110101}
102+ impl PortReadAccess for ReadOnlyAccess { }
111103
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" ;
123110}
111+ impl PortWriteAccess for WriteOnlyAccess { }
124112
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" ;
134119}
120+ impl PortReadAccess for ReadWriteAccess { }
121+ impl PortWriteAccess for ReadWriteAccess { }
135122
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 ) > ,
147134}
148135
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 > {
150146 /// Creates an I/O port with the given port number.
151147 #[ inline]
152- pub const fn new ( port : u16 ) -> Port < T > {
153- Port {
148+ pub const fn new ( port : u16 ) -> PortGeneric < T , A > {
149+ PortGeneric {
154150 port,
155151 phantom : PhantomData ,
156152 }
157153 }
158154}
159155
160- impl < T : PortRead > Port < T > {
156+ impl < T : PortRead , A : PortReadAccess > PortGeneric < T , A > {
161157 /// Reads from the port.
162158 ///
163159 /// ## Safety
@@ -170,7 +166,7 @@ impl<T: PortRead> Port<T> {
170166 }
171167}
172168
173- impl < T : PortWrite > Port < T > {
169+ impl < T : PortWrite , A : PortWriteAccess > PortGeneric < T , A > {
174170 /// Writes to the port.
175171 ///
176172 /// ## Safety
@@ -183,35 +179,29 @@ impl<T: PortWrite> Port<T> {
183179 }
184180}
185181
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+ }
204191
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 ,
209197 }
198+ }
199+ }
210200
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+ }
213205}
214206
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