contain 0.5.1

A crate for defining/extending lifetimes
Documentation
use std::sync::{Arc, Barrier};

use contain::{AnyContainer, SimpleContainer};

#[test]
fn simple_test() {
    let container = SimpleContainer::new();
    let mut holder = &String::from("initial");
    println!("holder: {}", holder);
    {
        holder = container.put(String::from("next"));
    }
    println!("holder: {}", holder);
}

#[test]
fn multiple_strings() {
    let container = SimpleContainer::new();
    let mut holder_1 = &String::from("initial 1");
    let mut holder_2 = &String::from("initial 2");
    assert_eq!("initial 1", holder_1);
    assert_eq!("initial 2", holder_2);
    {
        holder_1 = container.put(String::from("next 1"));
        holder_2 = container.put(String::from("next 2"));
    }

    assert_eq!("next 1", holder_1);
    assert_eq!("next 2", holder_2);
}

#[test]
fn with_resize() {
    let container = SimpleContainer::with_capacity(2);
    let mut holder_1 = &String::from("initial 1");
    let mut holder_2 = &String::from("initial 2");
    let mut holder_3 = &String::from("initial 3");
    let mut holder_4 = &String::from("initial 4");
    let mut holder_5 = &String::from("initial 5");
    assert_eq!("initial 1", holder_1);
    assert_eq!("initial 2", holder_2);
    assert_eq!("initial 3", holder_3);
    assert_eq!("initial 4", holder_4);
    assert_eq!("initial 5", holder_5);
    {
        holder_1 = container.put(String::from("next 1"));
        holder_2 = container.put(String::from("next 2"));
        holder_3 = container.put(String::from("next 3"));
        holder_4 = container.put(String::from("next 4"));
        holder_5 = container.put(String::from("next 5"));
    }
    assert_eq!("next 1", holder_1);
    assert_eq!("next 2", holder_2);
    assert_eq!("next 3", holder_3);
    assert_eq!("next 4", holder_4);
    assert_eq!("next 5", holder_5);
}

#[test]
fn size_check() {
    let container = SimpleContainer::new();
    let mut holder_1 = &String::from("initial 1");
    let mut holder_2 = &String::from("initial 2");
    let mut holder_3 = &String::from("initial 3");
    assert_eq!("initial 1", holder_1);
    assert_eq!("initial 2", holder_2);
    assert_eq!("initial 3", holder_3);
    {
        holder_1 = container.put(String::from("next 1"));
        holder_2 = container.put(String::from("next 2"));
        holder_3 = container.put(String::from("next 1"));
    }

    assert_eq!(container.count(), 3);
    assert_eq!("next 1", holder_1);
    assert_eq!("next 2", holder_2);
    assert_eq!("next 1", holder_3);
}

#[test]
fn mutable_test() {
    let container = SimpleContainer::new();
    let mut holder_1 = &mut String::from("initial 1");
    let mut holder_2 = &mut String::from("initial 2");
    let mut holder_3 = &mut String::from("initial 3");
    assert_eq!("initial 1", holder_1);
    assert_eq!("initial 2", holder_2);
    assert_eq!("initial 3", holder_3);
    {
        holder_1 = container.put(String::from("next 1"));
        holder_2 = container.put(String::from("next 2"));
        holder_3 = container.put(String::from("next 3"));
    }

    assert_eq!("next 1", holder_1);
    assert_eq!("next 2", holder_2);
    assert_eq!("next 3", holder_3);

    *holder_1 = String::from("final 1");

    assert_eq!("final 1", holder_1);
    assert_eq!("next 2", holder_2);
    assert_eq!("next 3", holder_3);

    *holder_2 = String::from("final 2");

    assert_eq!("final 1", holder_1);
    assert_eq!("final 2", holder_2);
    assert_eq!("next 3", holder_3);

    *holder_3 = String::from("final 3");

    assert_eq!("final 1", holder_1);
    assert_eq!("final 2", holder_2);
    assert_eq!("final 3", holder_3);
}

#[test]
fn threaded_test() {
    let container = Arc::new(SimpleContainer::<String>::new());
    let container_1 = Arc::clone(&container);
    let container_2 = Arc::clone(&container);
    let barrier = Arc::new(Barrier::new(2));
    let barrier_1 = Arc::clone(&barrier);
    let barrier_2 = Arc::clone(&barrier);

    let thread_1 = std::thread::spawn(|| {
        let container = container_1;
        let barrier = barrier_1;
        barrier.wait();
        let test_from_thread_1 = container.put(String::from("test from thread 1"));
        barrier.wait();
        assert_eq!(container.count(), 2);
        assert_eq!(test_from_thread_1, "test from thread 1");
        barrier.wait();
    });

    let thread_2 = std::thread::spawn(|| {
        let container = container_2;
        let barrier = barrier_2;
        barrier.wait();
        let test_from_thread_2 = container.put(String::from("test from thread 2"));
        barrier.wait();
        assert_eq!(container.count(), 2);
        assert_eq!(test_from_thread_2, "test from thread 2");
        barrier.wait();
    });

    thread_1.join().unwrap();
    thread_2.join().unwrap();

    assert_eq!(container.count(), 2);
}

#[test]
fn any_container_put_any() {
    let container = AnyContainer::new();
    let numbers: &[i32];
    let message: &str;

    {
        let arr = [1, 2, 3];
        numbers = container.put_any(arr);

        let s = String::from("hello");
        message = container.put_any(s);
    }

    assert_eq!(numbers, &[1, 2, 3]);
    assert_eq!(message, "hello");
}

#[test]
fn put_boxed() {
    let container: SimpleContainer<str> = Default::default();
    assert_eq!(container.count(), 0);

    let boxed = container.put_boxed(String::from("boxed").into_boxed_str());

    assert_eq!(boxed, "boxed");
    assert_eq!(container.count(), 1);
}