Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Zig mount example #217

Merged
merged 1 commit into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/languages/zig.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,4 @@ The Zig kit was originally authored by Christoph Voigt ([@voigt](https://github.

| [K/V Store](../features/key-value.md) | [Environment Variables](../features/environment-variables.md) | [Dynamic Routes](../features/dynamic-routes.md) | [Folders](../features/mount-folders.md) | [HTTP Requests](../features/http-requests.md) |
| --- | --- | --- | --- | --- |
| ✅ | ❌ | ✅ | | ❌ |
| ✅ | ❌ | ✅ | | ❌ |
26 changes: 26 additions & 0 deletions examples/zig-mount/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const std = @import("std");

const examples = [1][]const u8{ "mount" };

pub fn build(b: *std.Build) !void {
const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" });
const optimize = b.standardOptimizeOption(.{});

const worker_module = b.createModule(.{
.source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" },
});

inline for (examples) |example| {
const exe = b.addExecutable(.{
.name = example,
.root_source_file = .{ .path = "src/" ++ example ++ ".zig" },
.target = target,
.optimize = optimize,
});

exe.wasi_exec_model = .reactor;
exe.addModule("worker", worker_module);

b.installArtifact(exe);
}
}
26 changes: 26 additions & 0 deletions examples/zig-mount/src/mount.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const std = @import("std");
const worker = @import("worker");

var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
const allocator = arena.allocator();

fn requestFn(resp: *worker.Response, r: *worker.Request) void {
_ = r;

const file = std.fs.Dir.openFileWasi(
std.fs.cwd(), "zig.svg", .{
.mode = std.fs.File.OpenMode.read_only,
.lock = std.fs.File.Lock.none,
}) catch unreachable;
defer file.close();

const mb = (1 << 10) << 10;
const file_contents = file.readToEndAlloc(allocator, mb) catch "";

_ = &resp.headers.append("x-generated-by", "wasm-workers-server");
_ = &resp.writeAll(file_contents);
}

pub fn main() !void {
worker.ServeFunc(requestFn);
}
33 changes: 33 additions & 0 deletions examples/zig-mount/zig-out/bin/_images/zig.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions examples/zig-mount/zig-out/bin/mount.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name = "envs"
version = "1"

[[folders]]
from = "./_images"
to = "/src/images"
33 changes: 19 additions & 14 deletions kits/zig/worker/src/worker.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@ pub const Request = struct {

pub const Response = struct {
body: []const u8,
base64: bool,
headers: http.Headers,
request: Request,

pub fn writeAll(res: *Response, data: []const u8) !u32 {
res.body = data;
return res.body.len;
}

pub fn writeAllBase64(res: *Response, data: []const u8) !u32 {
res.body = base64Encode(data);
res.base64 = true;
return res.body.len;
}
};

// Note: as Zig does not support multiple return types, we use this struct
Expand Down Expand Up @@ -60,7 +67,7 @@ pub const Output = struct {
.httpHeader = http.Headers.init(allocator),
};
}

pub fn header(self: *Self) http.Headers {
if (self.httpHeader == undefined) {
self.httpHeader = http.Headers.init(allocator);
Expand All @@ -73,12 +80,12 @@ pub const Output = struct {
self.status = statusCode;
}

pub fn write(self: *Self, data: []const u8) !u32 {
if (std.unicode.utf8ValidateSlice(data)) {
self.data = data;
pub fn write(self: *Self, response: Response) !u32 {
self.base64 = response.base64;
if (response.base64) {
self.data = base64Encode(response.body);
} else {
self.base64 = true;
self.data = base64Encode(data);
self.data = response.body;
}

if (self.status == 0) {
Expand All @@ -90,7 +97,7 @@ pub const Output = struct {
}

// prepare writer for json
var out_buf: [1024]u8 = undefined;
var out_buf: [4096]u8 = undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this merges I'm going to open an issue to need an allocator here instead of fixed sizes on the stack.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good 👍

var slice_stream = std.io.fixedBufferStream(&out_buf);
const out = slice_stream.writer();
var w = std.json.writeStream(out, .{ .whitespace = .minified });
Expand All @@ -116,8 +123,6 @@ pub const Output = struct {
try w.endObject();
const result = slice_stream.getWritten();

// std.debug.print("\noutput json: {s}\n\n", .{ result });

const stdout = std.io.getStdOut().writer();
try stdout.print("{s}", .{ result });

Expand All @@ -129,7 +134,7 @@ fn base64Encode(data: []const u8) []const u8 {
// This initializing Base64Encoder throws weird error if not wrapped in function (maybe Zig bug?)
var enc = std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, '=');
var data_len = enc.calcSize(data.len);
var buf: [128]u8 = undefined;
var buf: [16384]u8 = undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this merges I'm going to open an issue to need an allocator here instead of fixed sizes on the stack.

return enc.encode(buf[0..data_len], data);
}

Expand Down Expand Up @@ -192,7 +197,7 @@ fn getInput(s: []const u8) !Input {
while (paramsIterator.next()) |entry| {
try params.put(entry.key_ptr.*, entry.value_ptr.*.string);
}

return input;
}

Expand Down Expand Up @@ -249,13 +254,13 @@ pub fn ServeFunc(requestFn: *const fn (*Response, *Request) void) void {
var request = r.request;
var output = r.output;

var response = Response{ .body = "", .headers = http.Headers.init(allocator), .request = request, };
var response = Response{ .body = "", .base64 = false, .headers = http.Headers.init(allocator), .request = request, };

requestFn(&response, &request);

output.httpHeader = response.headers;

_ = output.write(response.body) catch |err| {
_ = output.write(response) catch |err| {
std.debug.print("error writing data: {!} \n", .{ err });
};
}