diff --git a/unsafe_stack/.gitignore b/unsafe_stack/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/unsafe_stack/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/unsafe_stack/Cargo.toml b/unsafe_stack/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9d6158852daf2e273cf62b04fd7602edce9000ac --- /dev/null +++ b/unsafe_stack/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "unsafe_stack" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/unsafe_stack/src/main.rs b/unsafe_stack/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..97a00b3f37966a3c255ea563cc0051fbd2300b26 --- /dev/null +++ b/unsafe_stack/src/main.rs @@ -0,0 +1,16 @@ +use unsafe_stack::{Stack, StackError}; +mod unsafe_stack; + +fn main() -> Result<(), StackError> { + let mut new_stack: Stack<f64> = Stack::new(10).unwrap(); + + for i in 0..new_stack.capacity { + unsafe { + new_stack.push(i as f64).unwrap(); + } + } + + println!("{}", new_stack); + + Ok(()) +} diff --git a/unsafe_stack/src/unsafe_stack/mod.rs b/unsafe_stack/src/unsafe_stack/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..346df6c5471355396123fcb7f8424172d189b60a --- /dev/null +++ b/unsafe_stack/src/unsafe_stack/mod.rs @@ -0,0 +1,78 @@ +#[derive(Debug)] +pub enum StackError { + AllocationFailed, + StackFull, + StackEmpty, +} + +#[derive(Debug)] +pub struct Stack<T> { + pointer: *mut T, + length: usize, + pub capacity: usize, +} + +impl<T: Copy + std::fmt::Display> std::fmt::Display for Stack<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Ok(for i in 0..self.capacity { + unsafe { + write!(f, "{} ", *self.pointer.offset(i as isize) as T)?; + } + }) + } +} + +#[allow(dead_code)] +impl<T: Copy> Stack<T> { + pub fn new(capacity: usize) -> Result<Self, StackError> { + unsafe { + let layout = std::alloc::Layout::array::<T>(capacity); + + if let Ok(val) = layout { + let ptr = std::alloc::alloc(val); + if ptr.is_null() { + return Err(StackError::AllocationFailed); + } + + Ok(Self { + pointer: ptr as *mut T, + length: 0, + capacity, + }) + } else { + Err(StackError::AllocationFailed) + } + } + } + + pub fn is_full(&self) -> bool { + self.length == self.capacity + } + + pub fn is_empty(&self) -> bool { + self.length == 0 + } + + pub unsafe fn push(&mut self, value: T) -> Result<(), StackError> { + match self.is_full() { + true => Err(StackError::StackFull), + false => unsafe { + let location = self.pointer.offset(self.length as isize); + *location = value; + self.length += 1; + Ok(()) + }, + } + } + + pub unsafe fn pop(&mut self) -> Result<T, StackError> { + match self.is_empty() { + true => Err(StackError::StackEmpty), + false => unsafe { + let location = self.pointer.offset(self.length as isize - 1); + self.length -= 1; + Ok(*location) + }, + } + } +}