lib/std/vec.rad 3.2 KiB raw
1
//! Raw vector backed by caller-managed storage.
2
//!
3
//! Users provide their own storage and the vector manages
4
//! element count within that arena. The arena should be aligned according
5
//! to the element type's requirements.
6
7
/// Raw vector metadata structure.
8
///
9
/// Does not own storage, points to user-provided arena.
10
export record RawVec: Copy {
11
    /// Pointer to user-provided byte arena.
12
    data: *unsafe mut [u8],
13
    /// Current number of elements stored.
14
    len: u32,
15
    /// Size of each element in bytes (stride between elements).
16
    stride: u32,
17
    /// Alignment in bytes required by element type (>= 1).
18
    alignment: u32,
19
}
20
21
/// Create a new raw vector with external arena.
22
///
23
/// * `arena` must outlive the vector and all returned element pointers.
24
/// * `stride` is the size of each element.
25
/// * `alignment` is the required alignment for elements.
26
export unsafe fn new(arena: &mut [u8], stride: u32, alignment: u32) -> RawVec {
27
    assert stride > 0;
28
    assert alignment > 0;
29
    assert (arena.ptr as u32) % alignment == 0;
30
    assert (arena.len % stride) == 0;
31
32
    return RawVec { data: arena as *unsafe mut [u8], len: 0, stride, alignment };
33
}
34
35
/// Get the current number of elements in the vector.
36
export fn len(vec: &RawVec) -> u32 {
37
    return vec.len;
38
}
39
40
/// Get the maximum capacity of the vector.
41
export unsafe fn capacity(vec: &RawVec) -> u32 {
42
    return vec.data.len / vec.stride;
43
}
44
45
/// Reset the vector to empty (does not clear memory).
46
export fn reset(vec: &mut RawVec) {
47
    set vec.len = 0;
48
}
49
50
/// Get a pointer to the element at the given index.
51
///
52
/// Returns nil if index is out of bounds.
53
export unsafe fn get(vec: &RawVec, index: u32) -> ?*unsafe opaque {
54
    if index >= vec.len {
55
        return nil;
56
    }
57
    let offset: u32 = index * vec.stride;
58
    let ptr: *unsafe u8 = &vec.data[offset];
59
60
    return ptr as *unsafe opaque;
61
}
62
63
/// Push an element onto the end of the vector.
64
///
65
/// Returns false if the vector is at capacity.
66
export unsafe fn push(vec: &mut RawVec, elem: &opaque) -> bool {
67
    if vec.len >= capacity(vec) {
68
        return false;
69
    }
70
    let off: u32 = vec.len * vec.stride;
71
    copyBytes(&mut vec.data[off..off + vec.stride], @sliceOf(elem as &u8, vec.stride));
72
    set vec.len += 1;
73
74
    return true;
75
}
76
77
/// Pop an element from the end of the vector.
78
///
79
/// Copies the element into the provided output pointer.
80
/// Returns false if the vector is empty.
81
export unsafe fn pop(vec: &mut RawVec, out: &mut opaque) -> bool {
82
    if vec.len == 0 {
83
        return false;
84
    }
85
    set vec.len -= 1;
86
87
    let off: u32 = vec.len * vec.stride;
88
    copyBytes(@sliceOf(out as &mut u8, vec.stride), &vec.data[off..off + vec.stride]);
89
90
    return true;
91
}
92
93
/// Set the element at the given index.
94
///
95
/// Returns false if index is out of bounds.
96
export unsafe fn put(vec: &mut RawVec, index: u32, elem: &opaque) -> bool {
97
    if index >= vec.len {
98
        return false;
99
    }
100
    let off: u32 = index * vec.stride;
101
    copyBytes(&mut vec.data[off..off + vec.stride], @sliceOf(elem as &u8, vec.stride));
102
103
    return true;
104
}
105
106
/// Copy bytes from source to destination.
107
fn copyBytes(dst: &mut [u8], src: &[u8]) {
108
    assert dst.len == src.len;
109
    for i in 0..src.len {
110
        set dst[i] = src[i];
111
    }
112
}