1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use elements;
use super::invoke::{Invoke, Identity};

/// Table definition
#[derive(Debug)]
pub struct TableDefinition {
    /// Minimum length
    pub min: u32,
    /// Maximum length, if any
    pub max: Option<u32>,
    /// Element segments, if any
    pub elements: Vec<TableEntryDefinition>,
}

/// Table elements entry definition
#[derive(Debug)]
pub struct TableEntryDefinition {
    /// Offset initialization expression
    pub offset: elements::InitExpr,
    /// Values of initialization
    pub values: Vec<u32>,
}

/// Table builder
pub struct TableBuilder<F=Identity> {
    callback: F,
    table: TableDefinition,
}

impl TableBuilder {
    /// New table builder
    pub fn new() -> Self {
        TableBuilder::with_callback(Identity)
    }
}

impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
    /// New table builder with callback in chained context
    pub fn with_callback(callback: F) -> Self {
        TableBuilder {
            callback: callback,
            table: Default::default(),
        }
    }

    /// Set/override minimum length
    pub fn with_min(mut self, min: u32) -> Self {
        self.table.min = min;
        self
    }

    /// Set/override maximum length
    pub fn with_max(mut self, max: Option<u32>) -> Self {
        self.table.max = max;
        self
    }

    /// Generate initialization expression and element values on specified index
    pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
        self.table.elements.push(TableEntryDefinition {
            offset: elements::InitExpr::new(vec![
                elements::Opcode::I32Const(index as i32),
                elements::Opcode::End,
            ]),
            values: values,
        });
        self
    }

    /// Finalize current builder spawning resulting struct
    pub fn build(self) -> F::Result {
        self.callback.invoke(self.table)
    }
}

impl Default for TableDefinition {
    fn default() -> Self {
        TableDefinition {
            min: 0,
            max: None,
            elements: Vec::new(),
        }
    }
}