upgrade to zig 0.11

This commit is contained in:
Emil Lerch 2023-08-04 16:07:27 -07:00
parent 9a2ce42bbf
commit a31b4e8c3e
Signed by: lobo
GPG Key ID: A7B62D657EF764F8
4 changed files with 1356 additions and 89 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
zig-cache
zig-out
core

View File

@ -1,17 +1,47 @@
const std = @import("std"); const std = @import("std");
pub fn build(b: *std.build.Builder) void { // Although this function looks imperative, note that its job is to
// Standard release options allow the person running `zig build` to select // declaratively construct a build graph that will be executed by an external
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. // runner.
const mode = b.standardReleaseOptions(); pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
const lib = b.addStaticLibrary("smithy", "src/smithy.zig"); // Standard optimization options allow the person running `zig build` to select
lib.setBuildMode(mode); // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
lib.install(); // set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
var main_tests = b.addTest("src/smithy.zig"); const lib = b.addStaticLibrary(.{
main_tests.setBuildMode(mode); .name = "smithy",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = .{ .path = "src/smithy.zig" },
.target = target,
.optimize = optimize,
});
// This declares intent for the library to be installed into the standard
// location when the user invokes the "install" step (the default step when
// running `zig build`).
b.installArtifact(lib);
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const main_tests = b.addTest(.{
.root_source_file = .{ .path = "src/smithy.zig" },
.target = target,
.optimize = optimize,
});
const run_main_tests = b.addRunArtifact(main_tests);
// This creates a build step. It will be visible in the `zig build --help` menu,
// and can be selected like this: `zig build test`
// This will evaluate the `test` step rather than the default, which is "install".
const test_step = b.step("test", "Run library tests"); const test_step = b.step("test", "Run library tests");
test_step.dependOn(&main_tests.step); test_step.dependOn(&run_main_tests.step);
} }

View File

@ -240,18 +240,16 @@ pub const AwsProtocol = enum {
pub fn parse(allocator: std.mem.Allocator, json_model: []const u8) !Smithy { pub fn parse(allocator: std.mem.Allocator, json_model: []const u8) !Smithy {
// construct a parser. We're not copying strings here, but that may // construct a parser. We're not copying strings here, but that may
// be a poor decision // be a poor decision
var parser = std.json.Parser.init(allocator, false); var vt = try std.json.parseFromSlice(std.json.Value, allocator, json_model, .{});
defer parser.deinit();
var vt = try parser.parse(json_model);
defer vt.deinit(); defer vt.deinit();
return Smithy.init( return Smithy.init(
allocator, allocator,
vt.root.Object.get("smithy").?.String, vt.value.object.get("smithy").?.string,
ModelMetadata{ ModelMetadata{
// TODO: implement // TODO: implement
.suppressions = &.{}, .suppressions = &.{},
}, },
try shapes(allocator, vt.root.Object.get("shapes").?.Object), try shapes(allocator, vt.value.object.get("shapes").?.object),
); );
} }
@ -334,68 +332,68 @@ fn shapes(allocator: std.mem.Allocator, map: anytype) ![]ShapeInfo {
} }
fn getShape(allocator: std.mem.Allocator, shape: std.json.Value) SmithyParseError!Shape { fn getShape(allocator: std.mem.Allocator, shape: std.json.Value) SmithyParseError!Shape {
const shape_type = shape.Object.get("type").?.String; const shape_type = shape.object.get("type").?.string;
if (std.mem.eql(u8, shape_type, "service")) if (std.mem.eql(u8, shape_type, "service"))
return Shape{ return Shape{
.service = .{ .service = .{
.version = shape.Object.get("version").?.String, .version = shape.object.get("version").?.string,
.operations = if (shape.Object.get("operations")) |ops| .operations = if (shape.object.get("operations")) |ops|
try parseTargetList(allocator, ops.Array) try parseTargetList(allocator, ops.array)
else else
&.{}, // this doesn't make much sense, but it's happening &.{}, // this doesn't make much sense, but it's happening
// TODO: implement. We need some sample data tho // TODO: implement. We need some sample data tho
.resources = &.{}, .resources = &.{},
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "structure")) if (std.mem.eql(u8, shape_type, "structure"))
return Shape{ return Shape{
.structure = .{ .structure = .{
.members = try parseMembers(allocator, shape.Object.get("members")), .members = try parseMembers(allocator, shape.object.get("members")),
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "union")) if (std.mem.eql(u8, shape_type, "union"))
return Shape{ return Shape{
.uniontype = .{ .uniontype = .{
.members = try parseMembers(allocator, shape.Object.get("members")), .members = try parseMembers(allocator, shape.object.get("members")),
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "operation")) if (std.mem.eql(u8, shape_type, "operation"))
return Shape{ return Shape{
.operation = .{ .operation = .{
.input = if (shape.Object.get("input")) |member| member.Object.get("target").?.String else null, .input = if (shape.object.get("input")) |member| member.object.get("target").?.string else null,
.output = if (shape.Object.get("output")) |member| member.Object.get("target").?.String else null, .output = if (shape.object.get("output")) |member| member.object.get("target").?.string else null,
.errors = blk: { .errors = blk: {
if (shape.Object.get("errors")) |e| { if (shape.object.get("errors")) |e| {
break :blk try parseTargetList(allocator, e.Array); break :blk try parseTargetList(allocator, e.array);
} }
break :blk null; break :blk null;
}, },
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "list")) if (std.mem.eql(u8, shape_type, "list"))
return Shape{ return Shape{
.list = .{ .list = .{
.member_target = shape.Object.get("member").?.Object.get("target").?.String, .member_target = shape.object.get("member").?.object.get("target").?.string,
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "set")) if (std.mem.eql(u8, shape_type, "set"))
return Shape{ return Shape{
.set = .{ .set = .{
.member_target = shape.Object.get("member").?.Object.get("target").?.String, .member_target = shape.object.get("member").?.object.get("target").?.string,
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "map")) if (std.mem.eql(u8, shape_type, "map"))
return Shape{ return Shape{
.map = .{ .map = .{
.key = shape.Object.get("key").?.Object.get("target").?.String, .key = shape.object.get("key").?.object.get("target").?.string,
.value = shape.Object.get("value").?.Object.get("target").?.String, .value = shape.object.get("value").?.object.get("target").?.string,
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}, },
}; };
if (std.mem.eql(u8, shape_type, "string")) if (std.mem.eql(u8, shape_type, "string"))
@ -438,15 +436,15 @@ fn parseMembers(allocator: std.mem.Allocator, shape: ?std.json.Value) SmithyPars
if (shape == null) if (shape == null)
return rc; return rc;
const map = shape.?.Object; const map = shape.?.object;
var list = std.ArrayList(TypeMember).initCapacity(allocator, map.count()) catch return SmithyParseError.OutOfMemory; var list = std.ArrayList(TypeMember).initCapacity(allocator, map.count()) catch return SmithyParseError.OutOfMemory;
defer list.deinit(); defer list.deinit();
var iterator = map.iterator(); var iterator = map.iterator();
while (iterator.next()) |kv| { while (iterator.next()) |kv| {
try list.append(TypeMember{ try list.append(TypeMember{
.name = kv.key_ptr.*, .name = kv.key_ptr.*,
.target = kv.value_ptr.*.Object.get("target").?.String, .target = kv.value_ptr.*.object.get("target").?.string,
.traits = try parseTraits(allocator, kv.value_ptr.*.Object.get("traits")), .traits = try parseTraits(allocator, kv.value_ptr.*.object.get("traits")),
}); });
} }
return list.toOwnedSlice(); return list.toOwnedSlice();
@ -457,13 +455,13 @@ fn parseTargetList(allocator: std.mem.Allocator, list: anytype) SmithyParseError
var array_list = std.ArrayList([]const u8).initCapacity(allocator, list.items.len) catch return SmithyParseError.OutOfMemory; var array_list = std.ArrayList([]const u8).initCapacity(allocator, list.items.len) catch return SmithyParseError.OutOfMemory;
defer array_list.deinit(); defer array_list.deinit();
for (list.items) |i| { for (list.items) |i| {
try array_list.append(i.Object.get("target").?.String); try array_list.append(i.object.get("target").?.string);
} }
return array_list.toOwnedSlice(); return array_list.toOwnedSlice();
} }
fn parseTraitsOnly(allocator: std.mem.Allocator, shape: std.json.Value) SmithyParseError!TraitsOnly { fn parseTraitsOnly(allocator: std.mem.Allocator, shape: std.json.Value) SmithyParseError!TraitsOnly {
return TraitsOnly{ return TraitsOnly{
.traits = try parseTraits(allocator, shape.Object.get("traits")), .traits = try parseTraits(allocator, shape.object.get("traits")),
}; };
} }
@ -472,7 +470,7 @@ fn parseTraits(allocator: std.mem.Allocator, shape: ?std.json.Value) SmithyParse
if (shape == null) if (shape == null)
return rc; return rc;
const map = shape.?.Object; const map = shape.?.object;
var list = std.ArrayList(Trait).initCapacity(allocator, map.count()) catch return SmithyParseError.OutOfMemory; var list = std.ArrayList(Trait).initCapacity(allocator, map.count()) catch return SmithyParseError.OutOfMemory;
defer list.deinit(); defer list.deinit();
var iterator = map.iterator(); var iterator = map.iterator();
@ -487,18 +485,18 @@ fn getTrait(trait_type: []const u8, value: std.json.Value) SmithyParseError!?Tra
if (std.mem.eql(u8, trait_type, "aws.api#service")) if (std.mem.eql(u8, trait_type, "aws.api#service"))
return Trait{ return Trait{
.aws_api_service = .{ .aws_api_service = .{
.sdk_id = value.Object.get("sdkId").?.String, .sdk_id = value.object.get("sdkId").?.string,
.arn_namespace = value.Object.get("arnNamespace").?.String, .arn_namespace = value.object.get("arnNamespace").?.string,
.cloudformation_name = value.Object.get("cloudFormationName").?.String, .cloudformation_name = value.object.get("cloudFormationName").?.string,
.cloudtrail_event_source = value.Object.get("cloudTrailEventSource").?.String, .cloudtrail_event_source = value.object.get("cloudTrailEventSource").?.string,
// what good is a service without an endpoint? I don't know - ask amp // what good is a service without an endpoint? I don't know - ask amp
.endpoint_prefix = if (value.Object.get("endpointPrefix")) |endpoint| endpoint.String else "", .endpoint_prefix = if (value.object.get("endpointPrefix")) |endpoint| endpoint.string else "",
}, },
}; };
if (std.mem.eql(u8, trait_type, "aws.auth#sigv4")) if (std.mem.eql(u8, trait_type, "aws.auth#sigv4"))
return Trait{ return Trait{
.aws_auth_sigv4 = .{ .aws_auth_sigv4 = .{
.name = value.Object.get("name").?.String, .name = value.object.get("name").?.string,
}, },
}; };
if (std.mem.eql(u8, trait_type, "smithy.api#required")) if (std.mem.eql(u8, trait_type, "smithy.api#required"))
@ -548,33 +546,33 @@ fn getTrait(trait_type: []const u8, value: std.json.Value) SmithyParseError!?Tra
}; };
if (std.mem.eql(u8, trait_type, "smithy.api#documentation")) if (std.mem.eql(u8, trait_type, "smithy.api#documentation"))
return Trait{ .documentation = value.String }; return Trait{ .documentation = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#pattern")) if (std.mem.eql(u8, trait_type, "smithy.api#pattern"))
return Trait{ .pattern = value.String }; return Trait{ .pattern = value.string };
if (std.mem.eql(u8, trait_type, "aws.protocols#ec2QueryName")) if (std.mem.eql(u8, trait_type, "aws.protocols#ec2QueryName"))
return Trait{ .ec2_query_name = value.String }; return Trait{ .ec2_query_name = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#http")) { if (std.mem.eql(u8, trait_type, "smithy.api#http")) {
var code: i64 = 200; var code: i64 = 200;
if (value.Object.get("code")) |v| { if (value.object.get("code")) |v| {
if (v == .Integer) if (v == .integer)
code = v.Integer; code = v.integer;
} }
return Trait{ .http = .{ return Trait{ .http = .{
.method = value.Object.get("method").?.String, .method = value.object.get("method").?.string,
.uri = value.Object.get("uri").?.String, .uri = value.object.get("uri").?.string,
.code = code, .code = code,
} }; } };
} }
if (std.mem.eql(u8, trait_type, "smithy.api#jsonName")) if (std.mem.eql(u8, trait_type, "smithy.api#jsonName"))
return Trait{ .json_name = value.String }; return Trait{ .json_name = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#xmlName")) if (std.mem.eql(u8, trait_type, "smithy.api#xmlName"))
return Trait{ .xml_name = value.String }; return Trait{ .xml_name = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#httpQuery")) if (std.mem.eql(u8, trait_type, "smithy.api#httpQuery"))
return Trait{ .http_query = value.String }; return Trait{ .http_query = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#httpHeader")) if (std.mem.eql(u8, trait_type, "smithy.api#httpHeader"))
return Trait{ .http_header = value.String }; return Trait{ .http_header = value.string };
if (std.mem.eql(u8, trait_type, "smithy.api#httpPayload")) if (std.mem.eql(u8, trait_type, "smithy.api#httpPayload"))
return Trait{ .http_payload = .{} }; return Trait{ .http_payload = .{} };
@ -637,11 +635,11 @@ fn getTrait(trait_type: []const u8, value: std.json.Value) SmithyParseError!?Tra
return null; return null;
} }
fn getOptionalNumber(value: std.json.Value, key: []const u8) ?f64 { fn getOptionalNumber(value: std.json.Value, key: []const u8) ?f64 {
if (value.Object.get(key)) |v| if (value.object.get(key)) |v|
return switch (v) { return switch (v) {
.Integer => @intToFloat(f64, v.Integer), .integer => @as(f64, @floatFromInt(v.integer)),
.Float => v.Float, .float => v.float,
.Null, .Bool, .NumberString, .String, .Array, .Object => null, .null, .bool, .number_string, .string, .array, .object => null,
}; };
return null; return null;
} }
@ -687,22 +685,9 @@ fn read_file_to_string(allocator: std.mem.Allocator, file_name: []const u8, max_
defer file.close(); defer file.close();
return file.readToEndAlloc(allocator, max_bytes); return file.readToEndAlloc(allocator, max_bytes);
} }
var test_data: ?[]const u8 = null; const test_data: []const u8 = @embedFile("test.json");
const intrinsic_type_count: usize = 5; // 5 intrinsic types are added to every model const intrinsic_type_count: usize = 5; // 5 intrinsic types are added to every model
fn getTestData(_: *std.mem.Allocator) []const u8 {
if (test_data) |d| return d;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
test_data = read_file_to_string(gpa.allocator, "test.json", 150000) catch @panic("could not read test.json");
return test_data.?;
}
test "read file" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer if (gpa.deinit()) @panic("leak");
const allocator = gpa.allocator;
_ = getTestData(allocator);
// test stuff
}
test "parse string" { test "parse string" {
const test_string = const test_string =
\\ { \\ {
@ -723,9 +708,7 @@ test "parse string" {
\\ \\
; ;
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = std.testing.allocator;
defer if (gpa.deinit()) @panic("leak");
const allocator = gpa.allocator;
const model = try parse(allocator, test_string); const model = try parse(allocator, test_string);
defer model.deinit(); defer model.deinit();
try expect(std.mem.eql(u8, model.version, "1.0")); try expect(std.mem.eql(u8, model.version, "1.0"));
@ -757,9 +740,7 @@ test "parse shape with member" {
\\ \\
; ;
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = std.testing.allocator;
defer if (gpa.deinit()) @panic("leak");
const allocator = gpa.allocator;
const model = try parse(allocator, test_string); const model = try parse(allocator, test_string);
defer model.deinit(); defer model.deinit();
try expect(std.mem.eql(u8, model.version, "1.0")); try expect(std.mem.eql(u8, model.version, "1.0"));
@ -771,11 +752,8 @@ test "parse shape with member" {
try std.testing.expectEqualStrings("member", model.shapes[0].member.?); try std.testing.expectEqualStrings("member", model.shapes[0].member.?);
} }
test "parse file" { test "parse file" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = std.testing.allocator;
defer if (gpa.deinit()) @panic("leak"); const model = try parse(allocator, test_data);
const allocator = gpa.allocator;
const test_string = getTestData(allocator);
const model = try parse(allocator, test_string);
defer model.deinit(); defer model.deinit();
try std.testing.expectEqualStrings(model.version, "1.0"); try std.testing.expectEqualStrings(model.version, "1.0");
// metadata expectations // metadata expectations

1256
src/test.json Normal file

File diff suppressed because one or more lines are too long