11use jack_sys as j;
22use std:: marker:: PhantomData ;
3+ use std:: ptr:: NonNull ;
34use std:: { mem, slice} ;
45
56use crate :: { Error , Frames , Port , PortFlags , PortSpec , ProcessScope } ;
@@ -49,8 +50,9 @@ impl Port<MidiIn> {
4950 /// Get an iterator over midi events.
5051 pub fn iter < ' a > ( & ' a self , ps : & ' a ProcessScope ) -> MidiIter < ' a > {
5152 assert_eq ! ( self . client_ptr( ) , ps. client_ptr( ) ) ;
53+ let buffer = NonNull :: new ( unsafe { self . buffer ( ps. n_frames ( ) ) } ) ;
5254 MidiIter {
53- buffer : unsafe { self . buffer ( ps . n_frames ( ) ) } ,
55+ buffer,
5456 index : 0 ,
5557 _phantom : PhantomData ,
5658 }
@@ -60,7 +62,7 @@ impl Port<MidiIn> {
6062/// Iterate through Midi Messages within a [`Port<MidiIn>`].
6163#[ derive( Debug , Clone ) ]
6264pub struct MidiIter < ' a > {
63- buffer : * mut :: libc:: c_void ,
65+ buffer : Option < NonNull < :: libc:: c_void > > ,
6466 index : usize ,
6567 _phantom : PhantomData < & ' a ( ) > ,
6668}
@@ -86,42 +88,48 @@ impl<'a> MidiIter<'a> {
8688 }
8789
8890 fn absolute_nth ( & self , n : u32 ) -> Option < RawMidi < ' a > > {
91+ let buffer = self . buffer ?. as_ptr ( ) ;
8992 let mut ev = mem:: MaybeUninit :: < j:: jack_midi_event_t > :: uninit ( ) ;
90- let res = unsafe { j:: jack_midi_event_get ( ev. as_mut_ptr ( ) , self . buffer , n) } ;
93+ let res = unsafe { j:: jack_midi_event_get ( ev. as_mut_ptr ( ) , buffer, n) } ;
9194 if res != 0 {
9295 return None ;
9396 }
9497 let ev = unsafe { ev. assume_init ( ) } ;
9598 let time = ev. time ;
96- let bytes: & [ u8 ] = unsafe { slice:: from_raw_parts ( ev. buffer as * const u8 , ev. size ) } ;
99+ // `slice::from_raw_parts` requires a non-null pointer, even for an empty slice.
100+ let bytes: & [ u8 ] = if ev. buffer . is_null ( ) || ev. size == 0 {
101+ & [ ]
102+ } else {
103+ unsafe { slice:: from_raw_parts ( ev. buffer as * const u8 , ev. size ) }
104+ } ;
97105 Some ( RawMidi { time, bytes } )
98106 }
99107
100108 fn absolute_len ( & self ) -> usize {
101- if self . buffer . is_null ( ) {
102- 0
103- } else {
104- unsafe { j :: jack_midi_get_event_count ( self . buffer ) as usize }
105- }
109+ let Some ( buffer ) = self . buffer else {
110+ return 0 ;
111+ } ;
112+
113+ unsafe { j :: jack_midi_get_event_count ( buffer . as_ptr ( ) ) as usize }
106114 }
107115}
108116
109117impl < ' a > Iterator for MidiIter < ' a > {
110118 type Item = RawMidi < ' a > ;
111119
112120 fn next ( & mut self ) -> Option < Self :: Item > {
113- let ret = self . peek ( ) ;
121+ let ret = self . peek ( ) ? ;
114122 self . index += 1 ;
115- ret
123+ Some ( ret)
116124 }
117125
118126 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
119- let len = self . absolute_len ( ) - self . index ;
127+ let len = self . absolute_len ( ) . saturating_sub ( self . index ) ;
120128 ( len, Some ( len) )
121129 }
122130
123131 fn count ( self ) -> usize {
124- self . absolute_len ( ) - self . index
132+ self . absolute_len ( ) . saturating_sub ( self . index )
125133 }
126134
127135 fn last ( self ) -> Option < Self :: Item > {
@@ -134,7 +142,7 @@ impl<'a> Iterator for MidiIter<'a> {
134142 }
135143
136144 fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
137- self . index += n ;
145+ self . index = self . index . saturating_add ( n ) . min ( self . absolute_len ( ) ) ;
138146 self . next ( )
139147 }
140148}
@@ -212,3 +220,45 @@ impl MidiWriter<'_> {
212220 unsafe { j:: jack_midi_max_event_size ( self . buffer ) }
213221 }
214222}
223+
224+ #[ cfg( test) ]
225+ mod tests {
226+ use super :: * ;
227+
228+ fn empty_iter ( ) -> MidiIter < ' static > {
229+ MidiIter {
230+ buffer : None ,
231+ index : 0 ,
232+ _phantom : PhantomData ,
233+ }
234+ }
235+
236+ #[ test]
237+ fn empty_iter_has_no_events ( ) {
238+ let mut iter = empty_iter ( ) ;
239+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
240+ assert_eq ! ( iter. peek( ) , None ) ;
241+ assert_eq ! ( iter. next( ) , None ) ;
242+ assert_eq ! ( iter. clone( ) . count( ) , 0 ) ;
243+ assert_eq ! ( iter. last( ) , None ) ;
244+ }
245+
246+ #[ test]
247+ fn nth_past_the_end_does_not_underflow ( ) {
248+ let mut iter = empty_iter ( ) ;
249+ assert_eq ! ( iter. nth( 5 ) , None ) ;
250+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
251+ assert_eq ! ( iter. clone( ) . count( ) , 0 ) ;
252+ assert_eq ! ( iter. nth( usize :: MAX ) , None ) ;
253+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
254+ }
255+
256+ #[ test]
257+ fn next_past_the_end_does_not_underflow ( ) {
258+ let mut iter = empty_iter ( ) ;
259+ for _ in 0 ..3 {
260+ assert_eq ! ( iter. next( ) , None ) ;
261+ }
262+ assert_eq ! ( iter. size_hint( ) , ( 0 , Some ( 0 ) ) ) ;
263+ }
264+ }
0 commit comments