diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-19 23:28:22 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-19 23:28:22 -0300 |
| commit | ba996acfcad1698adbf4a1834fe50e73b1c6cab9 (patch) | |
| tree | 282ba00ce5b10d7416aecb9f2f0f0a439340a57d /app/client.zig | |
| parent | b05abcba3ea09ea106ad28364c6e40a3ec31b890 (diff) | |
| download | cloud9-ba996acfcad1698adbf4a1834fe50e73b1c6cab9.tar.gz cloud9-ba996acfcad1698adbf4a1834fe50e73b1c6cab9.zip | |
Rename programs: 9player -> 9ns, introspect -> 9proc, app -> web (9web)
Directories, binaries, build options (-D9ns, -D9proc), step names, module
name (9proc), thread and fs names, env var NINEPLAYER_MOUNT -> NINE_MOUNT,
docs and test scripts. Browser assets move to web/static.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'app/client.zig')
| -rw-r--r-- | app/client.zig | 176 |
1 files changed, 0 insertions, 176 deletions
diff --git a/app/client.zig b/app/client.zig deleted file mode 100644 index 2ec9163..0000000 --- a/app/client.zig +++ /dev/null @@ -1,176 +0,0 @@ -//! Browser ABI. Protocol state, encoding, reply validation, and directory decoding -//! all use the same cloud9 sources as native clients. No allocator or host imports. -const std = @import("std"); -const c9 = @import("cloud9"); -const capacity = 65536; -var input: [capacity]u8 = undefined; -var output: [capacity]u8 = undefined; -var staging: [capacity]u8 = undefined; -var json: [capacity * 2]u8 = undefined; -var client: c9.Client = undefined; -var data: []const u8 = ""; -var number: u32 = 0; -var directory: bool = false; - -export fn init() void { - client = .init(.{ .in = &input, .out = &output }); - data = ""; - number = 0; - directory = false; -} -export fn input_ptr() [*]u8 { - return &staging; -} -export fn input_capacity() u32 { - return capacity; -} -export fn output_ptr() [*]const u8 { - return client.output().ptr; -} -export fn output_len() u32 { - return @intCast(client.output().len); -} -export fn sent() void { - client.wrote(client.output().len); -} -export fn data_ptr() [*]const u8 { - return data.ptr; -} -export fn data_len() u32 { - return @intCast(data.len); -} -export fn result_number() u32 { - return number; -} -export fn result_directory() bool { - return directory; -} -export fn is_dead() bool { - return client.dead; -} -export fn max_read() u32 { - return client.maxRead(); -} -export fn max_write() u32 { - return client.maxWrite(); -} - -fn fail(message: []const u8) i32 { - data = message; - return -1; -} -fn submit(request: c9.Client.Request) i32 { - _ = client.submit(request) catch |err| return fail(@errorName(err)); - return 0; -} -export fn version() i32 { - return submit(.{ .version = .{} }); -} -export fn attach(user_len: u32, tree_len: u32) i32 { - if (user_len > capacity or tree_len > capacity - user_len) return fail("InputTooLarge"); - return submit(.{ .attach = .{ .fid = 0, .uname = staging[0..user_len], .aname = staging[user_len..][0..tree_len] } }); -} -export fn walk(fid: u32, newfid: u32, len: u32) i32 { - if (len > capacity) return fail("InputTooLarge"); - var names: [c9.max_welem][]const u8 = undefined; - var count: usize = 0; - var it = std.mem.splitScalar(u8, staging[0..len], '/'); - while (it.next()) |name| { - if (name.len == 0) continue; - if (count == names.len) return fail("TooManyNames"); - names[count] = name; - count += 1; - } - return submit(.{ .walk = .{ .fid = fid, .newfid = newfid, .names = names[0..count] } }); -} -export fn open(fid: u32, mode: u8) i32 { - return submit(.{ .open = .{ .fid = fid, .mode = mode } }); -} -export fn read(fid: u32, offset: u64, count: u32) i32 { - return submit(.{ .read = .{ .fid = fid, .offset = offset, .count = count } }); -} -export fn write(fid: u32, offset: u64, len: u32) i32 { - if (len > capacity) return fail("InputTooLarge"); - return submit(.{ .write = .{ .fid = fid, .offset = offset, .data = staging[0..len] } }); -} -export fn clunk(fid: u32) i32 { - return submit(.{ .clunk = .{ .fid = fid } }); -} -export fn stat(fid: u32) i32 { - return submit(.{ .stat = .{ .fid = fid } }); -} - -fn writeStat(s: c9.Stat, writer: *std.Io.Writer) !void { - try std.json.Stringify.value(.{ .name = s.name, .directory = s.qid.type & c9.qtdir != 0, .length = s.length, .mode = s.mode }, .{}, writer); -} - -/// Result codes: 0 incomplete, -1 error, 1 version, 2 attach, 3 walk, -/// 4 open, 5 read, 6 write, 7 clunk, 8 stat. Data is borrowed until next call. -export fn receive(len: u32) i32 { - if (len > capacity) return fail("InputTooLarge"); - if (client.push(staging[0..len]) != len) return fail("InputFull"); - const done = client.take() orelse return if (client.dead) fail("ProtocolError") else 0; - data = ""; - number = 0; - directory = false; - return switch (done.result) { - .fail => |message| fail(message), - .version => |v| blk: { - data = v.version; - number = v.msize; - break :blk 1; - }, - .attach => |qid| blk: { - directory = qid.type & c9.qtdir != 0; - break :blk 2; - }, - .walk => |w| blk: { - number = w.nwqid; - if (w.nwqid != 0) directory = w.wqid[w.nwqid - 1].type & c9.qtdir != 0; - break :blk 3; - }, - .open => |o| blk: { - number = o.iounit; - directory = o.qid.type & c9.qtdir != 0; - break :blk 4; - }, - .read => |bytes| blk: { - data = bytes; - break :blk 5; - }, - .write => |count| blk: { - number = count; - break :blk 6; - }, - .clunk => 7, - .stat => |s| blk: { - var writer: std.Io.Writer = .fixed(&json); - writeStat(s, &writer) catch return fail("OutputTooLarge"); - data = writer.buffered(); - break :blk 8; - }, - else => fail("UnexpectedReply"), - }; -} - -/// Parse complete directory stat records from one Rread, using cloud9.Stat. -export fn decode_directory(len: u32) i32 { - if (len > capacity) return fail("InputTooLarge"); - var remaining: []const u8 = staging[0..len]; - var writer: std.Io.Writer = .fixed(&json); - writer.writeByte('[') catch unreachable; - var first = true; - while (remaining.len != 0) { - if (remaining.len < 2) return fail("TruncatedDirectory"); - const size: usize = @as(usize, std.mem.readInt(u16, remaining[0..2], .little)) + 2; - if (size > remaining.len) return fail("TruncatedDirectory"); - const s = c9.Stat.decode(remaining[0..size]) catch return fail("InvalidDirectory"); - if (!first) writer.writeByte(',') catch return fail("OutputTooLarge"); - writeStat(s, &writer) catch return fail("OutputTooLarge"); - first = false; - remaining = remaining[size..]; - } - writer.writeByte(']') catch return fail("OutputTooLarge"); - data = writer.buffered(); - return 0; -} |
