-
-
Save lu-zero/8349e47b04b5af26a1d61d2455db541e to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(ptr_offset_from)] | |
use std::marker::PhantomData; | |
#[derive(Debug, Clone, Copy)] | |
struct PlaneInfo { | |
stride: usize, | |
w: usize, | |
h: usize, | |
} | |
#[derive(Debug, Clone)] | |
struct Plane { | |
data: Vec<u8>, | |
info: PlaneInfo, | |
} | |
use std::fmt; | |
impl fmt::Display for Plane { | |
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
let data = self | |
.data | |
.chunks(self.info.stride) | |
.take(self.info.h) | |
.map(|c| &c[..self.info.w]); | |
f.debug_list().entries(data).finish() | |
} | |
} | |
#[derive(Debug, Clone, Copy)] | |
struct TileInfo { | |
w: usize, | |
h: usize, | |
} | |
impl Plane { | |
fn new(info: PlaneInfo) -> Self { | |
Plane { | |
data: vec![128u8; (info.h + 1) * info.stride], | |
info, | |
} | |
} | |
fn tile_iter_mut<'a>(&'a mut self, tile_info: TileInfo) -> TileIterMut<'a> { | |
TileIterMut { | |
start: self.data.as_mut_ptr(), | |
end: unsafe { self.data.as_ptr().offset(self.data.len() as isize) }, | |
plane_info: self.info, | |
tile_info, | |
w_off: 0, | |
h_off: 0, | |
f: PhantomData, | |
} | |
} | |
} | |
#[derive(Debug, Clone, Copy)] | |
struct TileIterMut<'a> { | |
start: *mut u8, | |
end: *const u8, | |
plane_info: PlaneInfo, | |
tile_info: TileInfo, | |
w_off: usize, | |
h_off: usize, | |
f: PhantomData<&'a mut Plane>, | |
} | |
impl<'a> Iterator for TileIterMut<'a> { | |
type Item = TileMut<'a>; | |
fn next(&mut self) -> Option<TileMut<'a>> { | |
let y = self.h_off; | |
let x = self.w_off; | |
let stride = self.plane_info.stride; | |
let base = (y * stride + x) as isize; | |
let start = unsafe { self.start.offset(base) }; | |
let tile_size = (self.tile_info.h * stride + self.tile_info.w) as isize; | |
let end = unsafe { start.offset(tile_size) } as *const u8; | |
if end > self.end { | |
println!("exit at {}x{} {}", self.h_off, self.w_off, unsafe { | |
end.offset_from(self.end) | |
}); | |
None | |
} else { | |
let next_w_off = self.w_off + self.tile_info.w; | |
if next_w_off >= self.plane_info.w { | |
self.h_off += self.tile_info.h; | |
self.w_off = 0; | |
} else { | |
self.w_off = next_w_off; | |
} | |
println!("off {}x{} {}", self.h_off, self.w_off, unsafe { | |
end.offset_from(start as *const u8) | |
}); | |
Some(TileMut { | |
start, | |
end, | |
tile_info: self.tile_info, | |
stride: self.plane_info.stride, | |
f: PhantomData, | |
}) | |
} | |
} | |
} | |
#[derive(Debug, Clone, Copy)] | |
struct TileMut<'a> { | |
start: *mut u8, | |
end: *const u8, | |
tile_info: TileInfo, | |
stride: usize, | |
f: PhantomData<&'a mut TileIterMut<'a>>, | |
} | |
use std::ops::Index; | |
use std::ops::IndexMut; | |
impl<'a> Index<usize> for TileMut<'a> { | |
type Output = u8; | |
fn index<'b>(&'b self, index: usize) -> &'b u8 { | |
let h = index / self.tile_info.w; | |
let w = index % self.tile_info.w; | |
let pos = unsafe { self.start.offset((h * self.stride + w) as isize) }; | |
if pos >= self.end as *mut u8 { | |
panic!("Index out of range"); | |
} else { | |
unsafe { pos.as_ref().unwrap() } | |
} | |
} | |
} | |
impl<'a> IndexMut<usize> for TileMut<'a> { | |
fn index_mut<'b>(&'b mut self, index: usize) -> &'b mut u8 { | |
let h = index / self.tile_info.w; | |
let w = index % self.tile_info.w; | |
let pos = unsafe { self.start.offset((h * self.stride + w) as isize) }; | |
if pos >= self.end as *mut u8 { | |
panic!("Index out of range"); | |
} else { | |
unsafe { pos.as_mut().unwrap() } | |
} | |
} | |
} | |
#[derive(Debug, Clone, Copy)] | |
struct LineIterMut { | |
ptr: *mut u8, | |
tile_info: TileInfo, | |
h_off: usize, | |
} | |
fn main() { | |
let mut plane = Plane::new(PlaneInfo { | |
stride: 128, | |
w: 64, | |
h: 64, | |
}); | |
let tile_info = TileInfo { w: 16, h: 16 }; | |
plane | |
.tile_iter_mut(tile_info) | |
.enumerate() | |
.for_each(|(i, mut t)| { | |
println!("{} {:?}", i, t); | |
t[0] = i as u8; | |
}); | |
println!("{:#}", plane); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment