[][src]Macro v9::table

macro_rules! table {
    (@first $x:tt $($_xs:tt)*) => { ... };
    (
        $vis:vis struct $name:ident {
            $(pub $cn:ident: $cty:ty,)*
        }
    ) => { ... };
    (
        #[raw_index($raw:ty)]
        $vis:vis struct $name:ident {
            $(pub $cn:ident: $cty:ty,)*
        }
    ) => { ... };
}

Defines a table. This is the most important item in the crate!

Usage

// Declare a couple tables.
v9::table! {
    #[raw_index(u64)]
    pub struct cheeses {
        pub quantity: f64,
        pub warehouse: crate::warehouses::RowId,
        pub stinky: bool,
    }
}

v9::table! {
    pub struct warehouses {
        pub coordinates: (i32, i32),
        pub on_fire: bool,
    }
}

fn main() {
    // We create a new Universe. We put everything we can in it!
    use v9::prelude::Universe;
    let mut universe = Universe::new();

    // But it doesn't know about the tables, so we must register them.
    use v9::prelude::TableMarker;
    cheeses::Marker::register(&mut universe);
    warehouses::Marker::register(&mut universe);

    // Let's print out an inventory.
    use v9::kernel::Kernel;
    let mut print_inventory = Kernel::new(|cheeses: cheeses::Read, warehouses: warehouses::Read| {
        println!("Warehouses:");
        for id in warehouses.iter() {
            println!("{:?}", warehouses.ref_row(id));
        }
        println!("Cheeses:");
        for id in cheeses.iter() {
            println!("{:?}", cheeses.ref_row(id));
        }
    });
    // The kernel holds our closure, and keeps track of all of the objects it requires.
    universe.run(&mut print_inventory);
    // It's empty... we should add some things.
    universe.kmap(|mut warehouses: warehouses::Write, mut cheeses: cheeses::Write| {
        warehouses.reserve(3);
        let w0 = warehouses.push(warehouses::Row {
            coordinates: (0, 0),
            on_fire: true,
        });
        let w1 = warehouses.push(warehouses::Row {
            coordinates: (4, 9),
            on_fire: false,
        });
        let w2 = warehouses.push(warehouses::Row {
            coordinates: (8, 4),
            on_fire: true,
        });
        for wid in &[w0, w1, w2] {
            cheeses.reserve(10);
            for _ in 0..10 {
                cheeses.push(cheeses::Row {
                    quantity: 237.0,
                    warehouse: *wid,
                    stinky: true,
                });
            }
        }
    });
    // v9 is somewhat low-level. Because a Kernel does allocation (and we HATE allocation)
    // you are expected to implement your own higher level manager.
    // We can use `universe.kmap` when we prefer to be sloppy.
    universe.run(&mut print_inventory);
    // Now we should see our data.
    // But remember how those warehouses were on fire?
    universe.kmap(|list: &mut warehouses::Ids, mut on_fire: warehouses::edit::on_fire| {
        let mut dousing = true;
        for wid in list.removing(&on_fire) {
            if on_fire[wid] {
                if dousing {
                    dousing = false;
                    on_fire[wid] = false;
                } else {
                    wid.remove();
                }
            }
        }
    });
    // v9 has ensured data consistency -- the cheese in the destroyed warehouses has been lost.
    universe.run(&mut print_inventory);
    universe.kmap(|cheeses: cheeses::Read| {
        let mut n = 0;
        for _ in cheeses.iter() {
            n += 1;
        }
        assert_eq!(n, 20);
    });
}

Details

There's several things to be aware of.

  1. Naming. The item name should be lowercase (it becomes a module), and plural. The columns should be singular. (Unless it should be, like in pub aliases: Vec<String>.)
  2. The macro syntax kind of looks like a struct… but it very much is not.
  3. Type paths should be absolute, not relative.
  4. The struct's visiblity may be anything, but the field's visiblity must be pub.