aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/invocations/io/view.zig
blob: 349af7a2c148dfae9aad71f1c854b4435b76fc4e (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
//! View invocation - Read from attachment

const copy = @import("../../utils/mem/copy.zig");
const handler = @import("../handler.zig");
const int = @import("../../utils/types/int.zig");
const kata_attachment = @import("../../kata/attachment.zig");
const kata_limits = @import("../../common/limits/kata.zig");
const keyboard = @import("../../drivers/keyboard/keyboard.zig");
const random = @import("../../utils/random/xorshift.zig");
const result = @import("../../utils/types/result.zig");
const sensei = @import("../../kata/sensei/sensei.zig");
const slice = @import("../../utils/mem/slice.zig");

pub fn invoke(ctx: *handler.InvocationContext) void {
    const kata = sensei.get_current_kata() orelse return result.set_error(ctx);

    const fd = int.u32_of(ctx.rdi);
    const buffer_ptr = ctx.rsi;
    const count = ctx.rdx;

    if (fd >= kata_limits.MAX_ATTACHMENTS) return result.set_error(ctx);
    const entry = kata.attachments[fd] orelse return result.set_error(ctx);

    const bytes = view_from_attachment(entry, buffer_ptr, count) catch return result.set_error(ctx);
    result.set_value(ctx, bytes);
}

fn view_from_attachment(entry: *kata_attachment.Attachment, buffer_ptr: u64, count: u64) !u64 {
    if (entry.attachment_type == .Device) {
        const device = entry.device_type orelse return error.InvalidDevice;
        return view_from_device(device, buffer_ptr, count);
    }

    const unit_buffer = entry.buffer orelse return 0;
    const remaining = entry.unit_size - entry.position;
    const to_view = @min(count, remaining);

    if (to_view == 0) return 0;

    const src = slice.from_ptr_const(u8, int.from_ptr(unit_buffer.ptr) + entry.position, to_view);
    const dest = slice.from_ptr(u8, buffer_ptr, to_view);
    copy.bytes(dest, src);

    entry.position += to_view;
    return to_view;
}

fn view_from_device(device: kata_attachment.DeviceType, buffer_ptr: u64, count: u64) !u64 {
    const dest = slice.byte_ptr(buffer_ptr);

    switch (device) {
        .Source => {
            var i: u64 = 0;
            while (i < count) : (i += 1) {
                if (keyboard.read_char()) |char| {
                    dest[i] = char;
                } else break;
            }
            return i;
        },
        .Zero => {
            copy.zero(slice.from_ptr(u8, buffer_ptr, count));
            return count;
        },
        .Chaos => {
            var i: u64 = 0;
            while (i < count) : (i += 1) {
                dest[i] = random.byte();
            }
            return count;
        },
        else => return error.CannotView,
    }
}