Created
September 29, 2018 22:06
-
-
Save rust-play/0b004a719a5de6fa5c3717c67759d792 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains hidden or 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