aboutsummaryrefslogtreecommitdiff
path: root/shared/fs/afs/read/location.zig
blob: ef145fc3cf881a3bc5f60a5ceaa6f7c86dd933d2 (plain)
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
//! AFS Location Operations

const constants = @import("../constants/constants.zig");
const types = @import("../types/types.zig");

const StackRecord = types.StackRecord;
const UnitRecord = types.UnitRecord;

pub const LocationError = error{
    NotFound,
    NotAStack,
    InvalidLocation,
    BTreeError,
};

/// Result of looking up a location
pub const LookupResult = union(enum) {
    unit: UnitRecord,
    stack: StackRecord,
    not_found: void,
};

/// Convert ASCII location component to UTF-16 identity
pub fn component_to_identity(component: []const u8, identity_buffer: []u16) usize {
    var len: usize = 0;
    for (component) |byte| {
        if (len >= identity_buffer.len) break;
        identity_buffer[len] = byte;
        len += 1;
    }
    return len;
}

/// Iterator for location components
pub const LocationIterator = struct {
    location: []const u8,
    position: usize,

    pub fn init(location: []const u8) LocationIterator {
        var start: usize = 0;
        // Skip leading separator
        if (location.len > 0 and (location[0] == '/' or location[0] == '\\')) {
            start = 1;
        }
        return LocationIterator{
            .location = location,
            .position = start,
        };
    }

    pub fn next(self: *LocationIterator) ?[]const u8 {
        // Skip empty components
        while (self.position < self.location.len and
            (self.location[self.position] == '/' or self.location[self.position] == '\\'))
        {
            self.position += 1;
        }

        if (self.position >= self.location.len) {
            return null;
        }

        const start = self.position;
        while (self.position < self.location.len and
            self.location[self.position] != '/' and
            self.location[self.position] != '\\')
        {
            self.position += 1;
        }

        if (self.position == start) {
            return null;
        }

        return self.location[start..self.position];
    }
};