#![allow(dead_code)]
use std::cmp;
use std::fmt;
use std::num::NonZeroU32;
use std::ops;
use crate::Rect;
use crate::SoftBufferError;
pub struct BorrowStack<'a, T: 'a + ?Sized, U: 'a + ?Sized> {
container: *mut T,
member: *mut U,
_phantom: std::marker::PhantomData<&'a mut T>,
}
unsafe impl<'a, T: 'a + Send + ?Sized, U: 'a + Send + ?Sized> Send for BorrowStack<'a, T, U> {}
impl<'a, T: 'a + ?Sized, U: 'a + ?Sized> BorrowStack<'a, T, U> {
pub fn new<F>(container: &'a mut T, f: F) -> Result<Self, SoftBufferError>
where
F: for<'b> FnOnce(&'b mut T) -> Result<&'b mut U, SoftBufferError>,
{
let container = container as *mut T;
let member = f(unsafe { &mut *container })? as *mut U;
Ok(Self {
container,
member,
_phantom: std::marker::PhantomData,
})
}
pub fn member(&self) -> &U {
unsafe { &*self.member }
}
pub fn member_mut(&mut self) -> &mut U {
unsafe { &mut *self.member }
}
pub fn into_container(self) -> &'a mut T {
unsafe { &mut *self.container }
}
}
impl<'a, T: 'a + ?Sized, U: 'a + ?Sized + fmt::Debug> fmt::Debug for BorrowStack<'a, T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowStack")
.field("member", &self.member())
.finish_non_exhaustive()
}
}
pub(crate) fn union_damage(damage: &[Rect]) -> Option<Rect> {
struct Region {
left: u32,
top: u32,
bottom: u32,
right: u32,
}
let region = damage
.iter()
.map(|rect| Region {
left: rect.x,
top: rect.y,
right: rect.x + rect.width.get(),
bottom: rect.y + rect.height.get(),
})
.reduce(|mut prev, next| {
prev.left = cmp::min(prev.left, next.left);
prev.top = cmp::min(prev.top, next.top);
prev.right = cmp::max(prev.right, next.right);
prev.bottom = cmp::max(prev.bottom, next.bottom);
prev
})?;
Some(Rect {
x: region.left,
y: region.top,
width: NonZeroU32::new(region.right - region.left)
.expect("`right` must always be bigger then `left`"),
height: NonZeroU32::new(region.bottom - region.top)
.expect("`bottom` must always be bigger then `top`"),
})
}
#[derive(PartialEq, Eq, Hash, Clone)]
pub(crate) struct PixelBuffer(pub Vec<u32>);
impl fmt::Debug for PixelBuffer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PixelBuffer").finish_non_exhaustive()
}
}
impl ops::Deref for PixelBuffer {
type Target = Vec<u32>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ops::DerefMut for PixelBuffer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_borrowstack_slice_int() {
fn f(mut stack: BorrowStack<[u32], u32>) {
assert_eq!(*stack.member(), 3);
*stack.member_mut() = 42;
assert_eq!(stack.into_container(), &[1, 2, 42, 4, 5]);
}
let mut v = vec![1, 2, 3, 4, 5];
f(BorrowStack::new(v.as_mut(), |v: &mut [u32]| Ok(&mut v[2])).unwrap());
assert_eq!(&v, &[1, 2, 42, 4, 5]);
}
}