use std::result::Result;
const CAPACITY: usize = 5;
#[derive(Debug)]
struct Stack {
data: [i32; CAPACITY],
head: Option<usize>,
}
impl Stack {
fn new() -> Self {
Stack {
data: [0; CAPACITY],
head: None,
}
}
fn push(&mut self, val: i32) -> Result<(), &'static str> {
let new_head = self.head.map_or(0, |h| h + 1);
if new_head >= CAPACITY {
return Err("Stack full");
}
self.data[new_head] = val;
self.head = Some(new_head);
Ok(())
}
fn pop(&mut self) -> Result<i32, &'static str> {
match self.head {
None => Err("Stack empty"),
Some(h) => {
self.head = if h == 0 { None } else { Some(h - 1) };
Ok(self.data[h])
}
}
}
}
fn main() {
// Direct array use (potential unsafe without checks)
let mut arr = [0i32; CAPACITY];
let mut head = None::<usize>;
// push
let new_head = head.map_or(0, |h| h + 1);
arr[new_head] = 10;
head = Some(new_head);
// pop
let _val = if let Some(h) = head {
head = if h == 0 { None } else { Some(h - 1) };
arr[h]
} else { 0 };
// Unsafe example: arr[head.unwrap()] would panic on empty
// Stack safe
let mut stack = Stack::new();
let _ = stack.push(10);
let _ = stack.pop();
// stack.pop() returns Err("Stack empty")
}Full Rust code showing unsafe direct array operations (manual head management prone to errors like unwrap panic or bounds check forget) vs safe Stack abstraction with Result error handling and size limit.