my_box 0.2.2

An educational, zero-dependency Rust implementation of a heap-allocated smart pointer (MyBox<T>), mirroring std::boxed::Box<T> for learning purposes.
Documentation
use my_box::MyBox;

#[derive(Debug, Clone)]
struct Player {
    name: String,
    level: u32,
}

#[derive(Debug)]
struct TaskManager {
    tasks: Vec<i32>,
    completed: Vec<i32>,
}

impl TaskManager {
    fn sort_out(&mut self) {
        self.tasks.sort();
    }
    fn complete_task(&mut self, idx: usize) {
        if idx < self.tasks.len() {
            let task = self.tasks.remove(idx);
            self.completed.push(task);
        }
    }
}

fn example_basic() {
    println!("=== Example 1: Basic Heap Allocation ===");
    let mut heap_num = MyBox::new(10);
    *heap_num += 5;
    println!("  Heap value: {}", *heap_num);
    println!("  Raw pointer: {:p}", heap_num.as_ptr());
}

fn example_struct() {
    println!("\n=== Example 2: Struct on the Heap ===");
    let player = MyBox::new(Player {
        name: String::from("MrBread"),
        level: 99,
    });
    println!("  Player: {} (level {})", player.name, player.level);
}

fn example_mutability() {
    println!("\n=== Example 3: Mutable Access via DerefMut ===");
    let mut manager = MyBox::new(TaskManager {
        tasks: vec![50, 10, 30, 20],
        completed: vec![],
    });
    manager.sort_out();
    println!("  Sorted tasks: {:?}", manager.tasks);
    manager.complete_task(3);
    println!("  Completed: {:?}", manager.completed);
    println!("  Remaining: {:?}", manager.tasks);
}

fn example_clone() {
    println!("\n=== Example 4: Deep Clone ===");
    let original = MyBox::new(String::from("Rust Systems"));
    let cloned = original.clone();
    assert_eq!(*original, *cloned);
    assert_eq!(original.as_str(), cloned.as_str());
    assert!(original.as_ptr() != cloned.as_ptr());
    println!("  Original ptr: {:p}", original.as_ptr());
    println!("  Cloned ptr:   {:p}", cloned.as_ptr());
    println!("  Same content: {}", *original == *cloned);
    println!("  Different addresses: {}", original.as_ptr() != cloned.as_ptr());
}

fn example_scoped_drop() {
    println!("\n=== Example 5: Scoped Automatic Drop ===");
    {
        let temp = MyBox::new(vec![1, 2, 3]);
        println!("  Inside scope: {:?}", *temp);
    }
    println!("  (temp has been dropped here)");
}

#[derive(Debug, Clone, PartialEq)]
enum LinkedList<T> {
    Node { value: T, next: Box<LinkedList<T>> },
    Tail,
}

impl<T> LinkedList<T> {
    fn push_front(self, value: T) -> Self {
        LinkedList::Node {
            value,
            next: Box::new(self),
        }
    }
    fn len(&self) -> usize {
        match self {
            LinkedList::Node { next, .. } => 1 + next.len(),
            LinkedList::Tail => 0,
        }
    }
}

fn example_recursive() {
    println!("\n=== Example 6: Recursive Data Structure (Linked List) ===");
    let list = LinkedList::Tail
        .push_front(3)
        .push_front(2)
        .push_front(1);
    println!("  List: {:?}", list);
    println!("  Length: {}", list.len());
    println!(
        "  Compile-time size of List<i32>: {}",
        std::mem::size_of::<LinkedList<i32>>()
    );
}

#[derive(Debug, Clone, PartialEq)]
enum JsonValue {
    Null,
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<JsonValue>),
    Object(Box<[(String, JsonValue)]>),
}

impl Default for JsonValue {
    fn default() -> Self {
        Self::Null
    }
}

fn example_json() {
    println!("\n=== Example 7: Recursive Enum (JSON) ===");
    let json = JsonValue::Object(Box::new([
        (String::from("name"), JsonValue::String(String::from("Alice"))),
        (
            String::from("scores"),
            JsonValue::Array(vec![
                JsonValue::Number(95.0),
                JsonValue::Number(87.5),
                JsonValue::Number(92.0),
            ]),
        ),
        (String::from("active"), JsonValue::Bool(true)),
    ]));
    println!("  {:?}", json);
}

trait Drawable {
    fn draw(&self);
    fn area(&self) -> f64;
}

struct Circle {
    radius: f64,
}

struct Rectangle {
    width: f64,
    height: f64,
}

impl Drawable for Circle {
    fn draw(&self) {
        println!("    Drawing Circle(r={})", self.radius);
    }
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius * self.radius
    }
}

impl Drawable for Rectangle {
    fn draw(&self) {
        println!("    Drawing Rectangle({} x {})", self.width, self.height);
    }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn example_trait_object() {
    println!("\n=== Example 8: Trait Objects (dyn Drawable) ===");
    let shapes: Vec<Box<dyn Drawable>> = vec![
        Box::new(Circle { radius: 3.0 }),
        Box::new(Rectangle {
            width: 4.0,
            height: 5.0,
        }),
        Box::new(Circle { radius: 1.5 }),
    ];
    println!("  Shape | Area");
    println!("  ------|-------");
    for (_i, shape) in shapes.iter().enumerate() {
        shape.draw();
        println!("    => Area: {:.2}", shape.area());
        assert_eq!(std::mem::size_of_val(shape), std::mem::size_of::<usize>() * 2);
    }
}

#[derive(Debug, Clone)]
struct LargeData {
    buffer: [u8; 4096],
    index: usize,
}

impl std::ops::Deref for LargeData {
    type Target = [u8; 4096];

    fn deref(&self) -> &Self::Target {
        &self.buffer
    }
}

impl Default for LargeData {
    fn default() -> Self {
        Self {
            buffer: [0u8; 4096],
            index: 0,
        }
    }
}

fn example_stack_vs_heap() {
    println!("\n=== Example 9: Stack vs Heap Allocation ===");
    let stack_instance = LargeData {
        buffer: [42; 4096],
        index: 99,
    };
    println!(
        "  Stack LargeData size: {} bytes",
        std::mem::size_of_val(&stack_instance)
    );
    let heap_instance = MyBox::new(LargeData {
        buffer: [42; 4096],
        index: 99,
    });
    println!(
        "  MyBox<LargeData> size: {} bytes (vs {} on stack)",
        std::mem::size_of_val(&heap_instance),
        std::mem::size_of_val(&stack_instance)
    );
    let start = std::time::Instant::now();
    for _ in 0..1_000_000 {
        let moved_heap = heap_instance.clone();
        let _ = moved_heap.as_ptr();
    }
    let heap_time = start.elapsed();
    println!("  1M heap clone+move: {:?}", heap_time);
    let start = std::time::Instant::now();
    let stack_copy = stack_instance;
    for _ in 0..1_000_000 {
        let moved_stack = stack_copy.clone();
        let _ = moved_stack.index;
    }
    let stack_time = start.elapsed();
    println!(
        "  1M stack clone+move: {:?} ({}x slower)",
        stack_time,
        stack_time.as_nanos() / heap_time.as_nanos().max(1)
    );
}

fn example_raw_pointer_interop() {
    println!("\n=== Example 10: Raw Pointer Interop (into_raw / from_raw) ===");
    let boxed = MyBox::new(String::from("unsafe boundary"));
    let ptr = boxed.into_raw();
    println!("  Leaked pointer: {:p}", ptr);
    assert!(!ptr.is_null());
    let recovered = unsafe { MyBox::from_raw(ptr) };
    assert_eq!(recovered.as_str(), "unsafe boundary");
    println!("  Recovered: {}", *recovered);
    println!("  (Drop runs after this scope ends)");
}

#[derive(Debug, PartialEq)]
struct Book {
    title: String,
    author: String,
}

fn example_collections() {
    println!("\n=== Example 11: MyBox in Collections ===");
    let mut library: Vec<MyBox<Book>> = vec![
        MyBox::new(Book {
            title: String::from("The Rust Programming Language"),
            author: String::from("Klabnik & Nichols"),
        }),
        MyBox::new(Book {
            title: String::from("Programming Rust"),
            author: String::from("Jim Blandy"),
        }),
        MyBox::new(Book {
            title: String::from("Rust for Rustaceans"),
            author: String::from("Jon Gjengset"),
        }),
    ];
    println!("  Library has {} books:", library.len());
    for (i, book) in library.iter().enumerate() {
        println!(
            "    {}. \"{}\" by {}",
            i + 1,
            book.title,
            book.author
        );
    }
    library.sort_by(|a, b| a.title.cmp(&b.title));
    println!("\n  After sorting by title:");
    for (i, book) in library.iter().enumerate() {
        println!("    {}. \"{}\"", i + 1, book.title);
    }
}

#[derive(Debug, Clone, PartialEq)]
enum BinaryTree<T> {
    Leaf,
    Node {
        value: T,
        left: Box<BinaryTree<T>>,
        right: Box<BinaryTree<T>>,
    },
}

impl<T> BinaryTree<T> {
    fn count_nodes(&self) -> usize {
        match self {
            BinaryTree::Leaf => 0,
            BinaryTree::Node { left, right, .. } => {
                1 + left.count_nodes() + right.count_nodes()
            }
        }
    }
}

fn example_binary_tree() {
    println!("\n=== Example 12: Binary Tree with Box ===");
    let tree: BinaryTree<i32> = BinaryTree::Node {
        value: 10,
        left: Box::new(BinaryTree::Node {
            value: 5,
            left: Box::new(BinaryTree::Leaf),
            right: Box::new(BinaryTree::Leaf),
        }),
        right: Box::new(BinaryTree::Node {
            value: 15,
            left: Box::new(BinaryTree::Leaf),
            right: Box::new(BinaryTree::Leaf),
        }),
    };
    println!("  Tree: {:?}", tree);
    println!("  Nodes: {}", tree.count_nodes());
}

fn main() {
    example_basic();
    example_struct();
    example_mutability();
    example_clone();
    example_scoped_drop();
    example_recursive();
    example_json();
    example_trait_object();
    example_stack_vs_heap();
    example_raw_pointer_interop();
    example_collections();
    example_binary_tree();
}