summaryrefslogtreecommitdiff
path: root/app/client.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-19 23:28:22 -0300
committerGabriel Schneider <[email protected]>2026-09-19 23:28:22 -0300
commitba996acfcad1698adbf4a1834fe50e73b1c6cab9 (patch)
tree282ba00ce5b10d7416aecb9f2f0f0a439340a57d /app/client.zig
parentb05abcba3ea09ea106ad28364c6e40a3ec31b890 (diff)
downloadcloud9-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.zig176
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;
-}