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 stride = vec.stride;
71
    let off: u32 = vec.len * stride;
72
    copyBytes(&mut vec.data[off..off + stride], @sliceOf(elem as &u8, stride));
73
    set vec.len += 1;
74
75
    return true;
76
}
77
78
/// Pop an element from the end of the vector.
79
///
80
/// Copies the element into the provided output pointer.
81
/// Returns false if the vector is empty.
82
export unsafe fn pop(vec: &mut RawVec, out: &mut opaque) -> bool {
83
    if vec.len == 0 {
84
        return false;
85
    }
86
    set vec.len -= 1;
87
88
    let off: u32 = vec.len * vec.stride;
89
    copyBytes(@sliceOf(out as &mut u8, vec.stride), &vec.data[off..off + vec.stride]);
90
91
    return true;
92
}
93
94
/// Set the element at the given index.
95
///
96
/// Returns false if index is out of bounds.
97
export unsafe fn put(vec: &mut RawVec, index: u32, elem: &opaque) -> bool {
98
    if index >= vec.len {
99
        return false;
100
    }
101
    let stride = vec.stride;
102
    let off: u32 = index * stride;
103
    copyBytes(&mut vec.data[off..off + stride], @sliceOf(elem as &u8, stride));
104
105
    return true;
106
}
107
108
/// Copy bytes from source to destination.
109
fn copyBytes(dst: &mut [u8], src: &[u8]) {
110
    assert dst.len == src.len;
111
    for i in 0..src.len {
112
        set dst[i] = src[i];
113
    }
114
}