dope 0.12.0

The manifold runtime
Documentation
extern crate dope;
use o3::cell::{BrandCell, BrandToken};
use std::cell::Cell;
use std::marker::PhantomPinned;

struct Slot {
    inflight: Vec<u8>,
    close_after: bool,
}

struct Aux {
    scratch: Vec<u8>,
}

struct Timer {
    armed: u32,
}

struct Pinned {
    value: Cell<u32>,
    _pin: PhantomPinned,
}

struct Listener {
    pool: Vec<Slot>,
    app: App,
    aux: Aux,
}

struct App {
    seen: usize,
}

impl App {
    fn chunk<'id>(
        &mut self,
        slot: &mut Slot,
        chunk: &[u8],
        aux: &mut Aux,
        timer: &BrandCell<'id, Timer>,
        token: &mut BrandToken<'id>,
    ) -> bool {
        aux.scratch.clear();
        aux.scratch.extend_from_slice(chunk);
        slot.inflight.extend_from_slice(&aux.scratch);
        timer.borrow_mut(token).armed += 1;
        self.seen += 1;
        chunk.ends_with(b"\n")
    }
}

#[test]
fn dispatch_loop_shape_under_split_brands() {
    BrandToken::scope(|mut listener_token| {
        BrandToken::scope(|mut timer_token| {
            let listener = BrandCell::new(Listener {
                pool: vec![
                    Slot {
                        inflight: Vec::new(),
                        close_after: false,
                    },
                    Slot {
                        inflight: Vec::new(),
                        close_after: false,
                    },
                ],
                app: App { seen: 0 },
                aux: Aux {
                    scratch: Vec::new(),
                },
            });
            let timer = BrandCell::new(Timer { armed: 0 });
            let timer_handle = &timer;

            let events: [(usize, &[u8]); 3] = [(0, b"a"), (1, b"b\n"), (0, b"c\n")];
            for (idx, chunk) in events {
                let this = listener.borrow_mut(&mut listener_token);
                let (pool, app, aux) = (&mut this.pool, &mut this.app, &mut this.aux);
                let slot = &mut pool[idx];
                if app.chunk(slot, chunk, aux, timer_handle, &mut timer_token) {
                    slot.close_after = true;
                }
            }

            let this = listener.borrow(&listener_token);
            assert_eq!(this.app.seen, 3);
            assert_eq!(this.pool[0].inflight, b"ac\n");
            assert!(this.pool[0].close_after);
            assert!(this.pool[1].close_after);
            assert_eq!(timer.borrow(&timer_token).armed, 3);
        });
    });
}

#[test]
fn pinned_borrow_keeps_the_value_in_place() {
    BrandToken::scope(|mut token| {
        let cell = BrandCell::new(Pinned {
            value: Cell::new(0),
            _pin: PhantomPinned,
        });
        let cell = std::pin::pin!(cell);
        let first = {
            let value = cell.as_ref().borrow_pin_mut(&mut token);
            value.as_ref().get_ref().value.set(7);
            value.as_ref().get_ref() as *const Pinned
        };
        let value = cell.as_ref().borrow_pin(&token);
        assert_eq!(first, value.get_ref() as *const Pinned);
        assert_eq!(value.get_ref().value.get(), 7);
    });
}