use std::ptr;
#[cfg(nightly)]
use alloc::raw_vec::RawVec;
#[cfg(not(nightly))]
use alloc::RawVec;
#[cfg(windows)]
const MIN_STACK_SIZE: usize = 0x4b0;
#[cfg(unix)]
const MIN_STACK_SIZE: usize = 0x100;
pub struct Stack {
buf: RawVec<usize>,
}
impl Stack {
pub fn empty() -> Stack {
Stack {
buf: RawVec::with_capacity(0),
}
}
pub fn new(size: usize) -> Stack {
assert_ne!(size, 0);
let mut size = size;
if size < MIN_STACK_SIZE {
size = MIN_STACK_SIZE;
}
let stk = Stack {
buf: RawVec::with_capacity(size),
};
if (size & 1) == 0 && (size > 8) {
size = 8;
}
unsafe {
let buf = stk.buf.ptr();
ptr::write_bytes(buf, 0xEE, size);
}
stk
}
pub fn get_used_size(&self) -> usize {
let mut offset: usize = 0;
unsafe {
let mut magic: usize = 0xEE;
ptr::write_bytes(&mut magic, 0xEE, 1);
let mut ptr = self.buf.ptr();
while *ptr == magic {
offset += 1;
ptr = ptr.offset(1);
}
}
let cap = self.buf.cap();
if cap & 1 != 0 {
error!("stack size={}, used={}", cap, cap - offset);
}
cap - offset
}
#[inline]
pub fn size(&self) -> usize {
self.buf.cap()
}
pub fn end(&self) -> *mut usize {
unsafe { self.buf.ptr().offset(self.buf.cap() as isize) as *mut usize }
}
#[allow(dead_code)]
pub fn begin(&self) -> *mut usize {
self.buf.ptr()
}
}