lib/std/vec.rad 3.1 KiB raw
1
//! Raw vector: type-unsafe dynamic array backed by static storage.
2
//!
3
//! Users provide their own arena (static array) 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
pub record RawVec {
11
    /// Pointer to user-provided byte arena.
12
    data: *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` is a pointer to static array backing storage.
24
/// * `stride` is the size of each element.
25
/// * `alignment` is the required alignment for elements.
26
pub 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, len: 0, stride, alignment };
33
}
34
35
/// Get the current number of elements in the vector.
36
pub fn len(vec: *RawVec) -> u32 {
37
    return vec.len;
38
}
39
40
/// Get the maximum capacity of the vector.
41
pub 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
pub fn reset(vec: *mut RawVec) {
47
    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
pub fn get(vec: *RawVec, index: u32) -> ?*opaque {
54
    if index >= vec.len {
55
        return nil;
56
    }
57
    let offset: u32 = index * vec.stride;
58
    let ptr: *u8 = &vec.data[offset];
59
60
    return ptr as *opaque;
61
}
62
63
/// Push an element onto the end of the vector.
64
///
65
/// Returns false if the vector is at capacity.
66
pub 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
    let dst: *mut u8 = &mut vec.data[off];
72
    let src: *u8 = elem as *u8;
73
74
    copyBytes(dst, src, vec.stride);
75
    vec.len += 1;
76
77
    return true;
78
}
79
80
/// Pop an element from the end of the vector.
81
///
82
/// Copies the element into the provided output pointer.
83
/// Returns false if the vector is empty.
84
pub fn pop(vec: *mut RawVec, out: *mut opaque) -> bool {
85
    if vec.len == 0 {
86
        return false;
87
    }
88
    vec.len -= 1;
89
90
    let off: u32 = vec.len * vec.stride;
91
    let src: *u8 = &vec.data[off];
92
    let dst: *mut u8 = out as *mut u8;
93
94
    copyBytes(dst, src, vec.stride);
95
96
    return true;
97
}
98
99
/// Set the element at the given index.
100
///
101
/// Returns false if index is out of bounds.
102
pub fn set(vec: *mut RawVec, index: u32, elem: *opaque) -> bool {
103
    if index >= vec.len {
104
        return false;
105
    }
106
    let off: u32 = index * vec.stride;
107
    let dst: *mut u8 = &mut vec.data[off];
108
    let src: *u8 = elem as *u8;
109
110
    copyBytes(dst, src, vec.stride);
111
112
    return true;
113
}
114
115
/// Copy bytes from source to destination.
116
fn copyBytes(dst: *mut u8, src: *u8, count: u32) {
117
    for i in 0..count {
118
        *(dst + i) = *(src + i);
119
    }
120
}