diff --git a/changelog.md b/changelog.md index 3321a8cb06..c9dafcb889 100644 --- a/changelog.md +++ b/changelog.md @@ -16,6 +16,8 @@ when upgrading from a version of rust-sdl2 to another. [PR #1332](https://github.com/Rust-SDL2/rust-sdl2/pull/1332) Fix `size_hint` implementations for `{audio,video,render}::DriverIterator` +[PR #1333](https://github.com/Rust-SDL2/rust-sdl2/pull/1333) Implement `FusedIterator`, `DoubleEndedIterator`, `and nth[_back]` for `{audio,video,render}::DriverIterator` + [PR #1337](https://github.com/Rust-SDL2/rust-sdl2/pull/1337) Fix "Cannot initialize Sdl from more than one thread" for tests / CI ### v0.35.2 diff --git a/src/sdl2/audio.rs b/src/sdl2/audio.rs index 9303b1959b..7b5c9ce304 100644 --- a/src/sdl2/audio.rs +++ b/src/sdl2/audio.rs @@ -352,6 +352,18 @@ pub struct DriverIterator { index: i32, } +// panics if SDL_GetAudioDriver returns a null pointer, +// which only happens if index is outside the range +// 0..SDL_GetNumAudioDrivers() +fn get_audio_driver(index: i32) -> &'static str { + unsafe { + let buf = sys::SDL_GetAudioDriver(index); + assert!(!buf.is_null()); + + CStr::from_ptr(buf as *const _).to_str().unwrap() + } +} + impl Iterator for DriverIterator { type Item = &'static str; @@ -360,13 +372,10 @@ impl Iterator for DriverIterator { if self.index >= self.length { None } else { - unsafe { - let buf = sys::SDL_GetAudioDriver(self.index); - assert!(!buf.is_null()); - self.index += 1; + let driver = get_audio_driver(self.index); + self.index += 1; - Some(CStr::from_ptr(buf as *const _).to_str().unwrap()) - } + Some(driver) } } @@ -375,10 +384,49 @@ impl Iterator for DriverIterator { let remaining = (self.length - self.index) as usize; (remaining, Some(remaining)) } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'static str> { + use std::convert::TryInto; + + self.index = match n.try_into().ok().and_then(|n| self.index.checked_add(n)) { + Some(index) if index < self.length => index, + _ => self.length, + }; + + self.next() + } +} + +impl DoubleEndedIterator for DriverIterator { + #[inline] + fn next_back(&mut self) -> Option<&'static str> { + if self.index >= self.length { + None + } else { + self.length -= 1; + + Some(get_audio_driver(self.length)) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<&'static str> { + use std::convert::TryInto; + + self.length = match n.try_into().ok().and_then(|n| self.length.checked_sub(n)) { + Some(length) if length > self.index => length, + _ => self.index, + }; + + self.next_back() + } } impl ExactSizeIterator for DriverIterator {} +impl std::iter::FusedIterator for DriverIterator {} + /// Gets an iterator of all audio drivers compiled into the SDL2 library. #[doc(alias = "SDL_GetAudioDriver")] #[inline] diff --git a/src/sdl2/render.rs b/src/sdl2/render.rs index 99ce07d09e..cb645752b9 100644 --- a/src/sdl2/render.rs +++ b/src/sdl2/render.rs @@ -2556,6 +2556,17 @@ pub struct DriverIterator { index: i32, } +// panics if SDL_GetRenderDriverInfo returns a nonzero value, +// which should only happen if index is outside the range +// 0..SDL_GetNumRenderDrivers() +fn get_render_driver_info(index: i32) -> RendererInfo { + let mut out = mem::MaybeUninit::uninit(); + let result = unsafe { sys::SDL_GetRenderDriverInfo(index, out.as_mut_ptr()) }; + assert_eq!(result, 0); + + unsafe { RendererInfo::from_ll(&out.assume_init()) } +} + impl Iterator for DriverIterator { type Item = RendererInfo; @@ -2565,12 +2576,10 @@ impl Iterator for DriverIterator { if self.index >= self.length { None } else { - let mut out = mem::MaybeUninit::uninit(); - let result = unsafe { sys::SDL_GetRenderDriverInfo(self.index, out.as_mut_ptr()) == 0 }; - assert!(result, "{}", 0); + let driver = get_render_driver_info(self.index); self.index += 1; - unsafe { Some(RendererInfo::from_ll(&out.assume_init())) } + Some(driver) } } @@ -2579,10 +2588,49 @@ impl Iterator for DriverIterator { let remaining = (self.length - self.index) as usize; (remaining, Some(remaining)) } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + use std::convert::TryInto; + + self.index = match n.try_into().ok().and_then(|n| self.index.checked_add(n)) { + Some(index) if index < self.length => index, + _ => self.length, + }; + + self.next() + } +} + +impl DoubleEndedIterator for DriverIterator { + #[inline] + fn next_back(&mut self) -> Option { + if self.index >= self.length { + None + } else { + self.length -= 1; + + Some(get_render_driver_info(self.length)) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + use std::convert::TryInto; + + self.length = match n.try_into().ok().and_then(|n| self.length.checked_sub(n)) { + Some(length) if length > self.index => length, + _ => self.index, + }; + + self.next_back() + } } impl ExactSizeIterator for DriverIterator {} +impl std::iter::FusedIterator for DriverIterator {} + /// Gets an iterator of all render drivers compiled into the SDL2 library. #[inline] #[doc(alias = "SDL_GetNumRenderDrivers")] diff --git a/src/sdl2/video.rs b/src/sdl2/video.rs index 872e47b4bb..fbb2c47f55 100644 --- a/src/sdl2/video.rs +++ b/src/sdl2/video.rs @@ -1990,6 +1990,20 @@ pub struct DriverIterator { index: i32, } +// panics if SDL_GetVideoDriver returns a null pointer, +// which only happens if index is outside the range +// 0..SDL_GetNumVideoDrivers() +fn get_video_driver(index: i32) -> &'static str { + use std::str; + + unsafe { + let buf = sys::SDL_GetVideoDriver(index); + assert!(!buf.is_null()); + + str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap() + } +} + impl Iterator for DriverIterator { type Item = &'static str; @@ -1998,15 +2012,10 @@ impl Iterator for DriverIterator { if self.index >= self.length { None } else { - use std::str; - - unsafe { - let buf = sys::SDL_GetVideoDriver(self.index); - assert!(!buf.is_null()); - self.index += 1; + let driver = get_video_driver(self.index); + self.index += 1; - Some(str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap()) - } + Some(driver) } } @@ -2015,10 +2024,49 @@ impl Iterator for DriverIterator { let remaining = (self.length - self.index) as usize; (remaining, Some(remaining)) } + + #[inline] + fn nth(&mut self, n: usize) -> Option<&'static str> { + use std::convert::TryInto; + + self.index = match n.try_into().ok().and_then(|n| self.index.checked_add(n)) { + Some(index) if index < self.length => index, + _ => self.length, + }; + + self.next() + } +} + +impl DoubleEndedIterator for DriverIterator { + #[inline] + fn next_back(&mut self) -> Option<&'static str> { + if self.index >= self.length { + None + } else { + self.length -= 1; + + Some(get_video_driver(self.length)) + } + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<&'static str> { + use std::convert::TryInto; + + self.length = match n.try_into().ok().and_then(|n| self.length.checked_sub(n)) { + Some(length) if length > self.index => length, + _ => self.index, + }; + + self.next_back() + } } impl ExactSizeIterator for DriverIterator {} +impl std::iter::FusedIterator for DriverIterator {} + /// Gets an iterator of all video drivers compiled into the SDL2 library. #[inline] #[doc(alias = "SDL_GetVideoDriver")]