add metadata function
This blows up the number of parameters on generateComplexTypeFor at least this is a private function, but still kinda messay
This commit is contained in:
parent
03ef89a362
commit
4a10450e0e
|
@ -126,7 +126,7 @@ fn generateServices(allocator: *std.mem.Allocator, comptime terminator: []const
|
||||||
|
|
||||||
// Operations
|
// Operations
|
||||||
for (service.shape.service.operations) |op|
|
for (service.shape.service.operations) |op|
|
||||||
try generateOperation(allocator, shapes.get(op).?, shapes, writer);
|
try generateOperation(allocator, shapes.get(op).?, shapes, writer, constant_name);
|
||||||
|
|
||||||
// End service
|
// End service
|
||||||
_ = try writer.write("} = .{}" ++ terminator ++ " // end of service: ");
|
_ = try writer.write("} = .{}" ++ terminator ++ " // end of service: ");
|
||||||
|
@ -134,24 +134,31 @@ fn generateServices(allocator: *std.mem.Allocator, comptime terminator: []const
|
||||||
}
|
}
|
||||||
return constant_names.toOwnedSlice();
|
return constant_names.toOwnedSlice();
|
||||||
}
|
}
|
||||||
fn generateOperation(allocator: *std.mem.Allocator, operation: smithy.ShapeInfo, shapes: anytype, writer: anytype) !void {
|
fn generateOperation(allocator: *std.mem.Allocator, operation: smithy.ShapeInfo, shapes: anytype, writer: anytype, service: []const u8) !void {
|
||||||
const snake_case_name = try snake.fromPascalCase(allocator, operation.name);
|
const snake_case_name = try snake.fromPascalCase(allocator, operation.name);
|
||||||
defer allocator.free(snake_case_name);
|
defer allocator.free(snake_case_name);
|
||||||
|
|
||||||
|
comptime const prefix = " ";
|
||||||
var type_stack = std.ArrayList(*const smithy.ShapeInfo).init(allocator);
|
var type_stack = std.ArrayList(*const smithy.ShapeInfo).init(allocator);
|
||||||
defer type_stack.deinit();
|
defer type_stack.deinit();
|
||||||
// indent should start at 4 spaces here
|
// indent should start at 4 spaces here
|
||||||
try writer.print(" {s}: struct ", .{snake_case_name});
|
const operation_name = avoidReserved(snake_case_name);
|
||||||
|
try writer.print(" {s}: struct ", .{operation_name});
|
||||||
_ = try writer.write("{\n");
|
_ = try writer.write("{\n");
|
||||||
try writer.print(" action_name: []const u8 = \"{s}\",\n", .{operation.name});
|
try writer.print(" action_name: []const u8 = \"{s}\",\n", .{operation.name});
|
||||||
_ = try writer.write(" Request: type = ");
|
_ = try writer.write(" Request: type = ");
|
||||||
if (operation.shape.operation.input) |member| {
|
if (operation.shape.operation.input) |member| {
|
||||||
try generateTypeFor(allocator, member, shapes, writer, " ", false, &type_stack);
|
try generateTypeFor(allocator, member, shapes, writer, prefix, false, &type_stack, false);
|
||||||
} else _ = try writer.write("struct {}"); // we want to maintain consistency with other ops
|
_ = try writer.write("\n");
|
||||||
|
try generateMetadataFunction(service, operation_name, prefix, writer);
|
||||||
|
} else {
|
||||||
|
_ = try writer.write("struct {\n");
|
||||||
|
try generateMetadataFunction(service, operation_name, prefix, writer);
|
||||||
|
}
|
||||||
_ = try writer.write(",\n");
|
_ = try writer.write(",\n");
|
||||||
_ = try writer.write(" Response: type = ");
|
_ = try writer.write(" Response: type = ");
|
||||||
if (operation.shape.operation.output) |member| {
|
if (operation.shape.operation.output) |member| {
|
||||||
try generateTypeFor(allocator, member, shapes, writer, " ", true, &type_stack);
|
try generateTypeFor(allocator, member, shapes, writer, " ", true, &type_stack, true);
|
||||||
} else _ = try writer.write("struct {}"); // we want to maintain consistency with other ops
|
} else _ = try writer.write("struct {}"); // we want to maintain consistency with other ops
|
||||||
_ = try writer.write(",\n");
|
_ = try writer.write(",\n");
|
||||||
|
|
||||||
|
@ -166,6 +173,19 @@ fn generateOperation(allocator: *std.mem.Allocator, operation: smithy.ShapeInfo,
|
||||||
_ = try writer.write(" } = .{},\n");
|
_ = try writer.write(" } = .{},\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generateMetadataFunction(service: []const u8, operation_name: []const u8, comptime prefix: []const u8, writer: anytype) !void {
|
||||||
|
// TODO: Shove these lines in here, and also the else portion
|
||||||
|
// pub fn metaInfo(self: @This()) struct { service: @TypeOf(sts), action: @TypeOf(sts.get_caller_identity) } {
|
||||||
|
// return .{ .service = sts, .action = sts.get_caller_identity };
|
||||||
|
// }
|
||||||
|
// We want to add a short "get my parents" function into the response
|
||||||
|
try writer.print("{s} ", .{prefix});
|
||||||
|
_ = try writer.write("pub fn metaInfo(self: @This()) struct { ");
|
||||||
|
try writer.print("service: @TypeOf({s}), action: @TypeOf({s}.{s})", .{ service, service, operation_name });
|
||||||
|
_ = try writer.write(" } {\n" ++ prefix ++ " return .{ ");
|
||||||
|
try writer.print(".service = {s}, .action = {s}.{s}", .{ service, service, operation_name });
|
||||||
|
_ = try writer.write(" };\n" ++ prefix ++ " }\n" ++ prefix ++ "}");
|
||||||
|
}
|
||||||
fn getErrorName(err_name: []const u8) []const u8 {
|
fn getErrorName(err_name: []const u8) []const u8 {
|
||||||
if (endsWith("Exception", err_name))
|
if (endsWith("Exception", err_name))
|
||||||
return err_name[0 .. err_name.len - "Exception".len];
|
return err_name[0 .. err_name.len - "Exception".len];
|
||||||
|
@ -180,7 +200,7 @@ fn endsWith(item: []const u8, str: []const u8) bool {
|
||||||
return std.mem.eql(u8, item, str[str.len - item.len ..]);
|
return std.mem.eql(u8, item, str[str.len - item.len ..]);
|
||||||
}
|
}
|
||||||
/// return type is anyerror!void as this is a recursive function, so the compiler cannot properly infer error types
|
/// return type is anyerror!void as this is a recursive function, so the compiler cannot properly infer error types
|
||||||
fn generateTypeFor(allocator: *std.mem.Allocator, shape_id: []const u8, shapes: anytype, writer: anytype, prefix: []const u8, all_required: bool, type_stack: anytype) anyerror!void {
|
fn generateTypeFor(allocator: *std.mem.Allocator, shape_id: []const u8, shapes: anytype, writer: anytype, prefix: []const u8, all_required: bool, type_stack: anytype, end_structure: bool) anyerror!void {
|
||||||
if (shapes.get(shape_id) == null) {
|
if (shapes.get(shape_id) == null) {
|
||||||
std.debug.print("Shape ID not found. This is most likely a bug. Shape ID: {s}\n", .{shape_id});
|
std.debug.print("Shape ID not found. This is most likely a bug. Shape ID: {s}\n", .{shape_id});
|
||||||
return error.InvalidType;
|
return error.InvalidType;
|
||||||
|
@ -213,6 +233,7 @@ fn generateTypeFor(allocator: *std.mem.Allocator, shape_id: []const u8, shapes:
|
||||||
// type to properly reference. Realistically, AWS or the service
|
// type to properly reference. Realistically, AWS or the service
|
||||||
// must be blocking deep recursion somewhere or this would be a great
|
// must be blocking deep recursion somewhere or this would be a great
|
||||||
// DOS attack
|
// DOS attack
|
||||||
|
try generateSimpleTypeFor("nothing", "[]const u8", writer, all_required);
|
||||||
std.log.warn("Type cycle detected, limiting depth. Type: {s}", .{shape_id});
|
std.log.warn("Type cycle detected, limiting depth. Type: {s}", .{shape_id});
|
||||||
// std.log.info(" Type stack:\n", .{});
|
// std.log.info(" Type stack:\n", .{});
|
||||||
// for (type_stack.items) |i|
|
// for (type_stack.items) |i|
|
||||||
|
@ -221,17 +242,29 @@ fn generateTypeFor(allocator: *std.mem.Allocator, shape_id: []const u8, shapes:
|
||||||
}
|
}
|
||||||
try type_stack.append(&shape_info);
|
try type_stack.append(&shape_info);
|
||||||
switch (shape) {
|
switch (shape) {
|
||||||
.structure => |s| try generateComplexTypeFor(allocator, shape.structure.members, "struct", shapes, writer, prefix, all_required, type_stack),
|
.structure => |s| {
|
||||||
.uniontype => |s| try generateComplexTypeFor(allocator, shape.uniontype.members, "union", shapes, writer, prefix, all_required, type_stack),
|
try generateComplexTypeFor(allocator, shape.structure.members, "struct", shapes, writer, prefix, all_required, type_stack);
|
||||||
|
if (end_structure) {
|
||||||
|
// epilog
|
||||||
|
try writer.print("{s}", .{prefix});
|
||||||
|
_ = try writer.write("}");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.uniontype => |s| {
|
||||||
|
try generateComplexTypeFor(allocator, shape.uniontype.members, "union", shapes, writer, prefix, all_required, type_stack);
|
||||||
|
// epilog
|
||||||
|
try writer.print("{s}", .{prefix});
|
||||||
|
_ = try writer.write("}");
|
||||||
|
},
|
||||||
.string => |s| try generateSimpleTypeFor(s, "[]const u8", writer, all_required),
|
.string => |s| try generateSimpleTypeFor(s, "[]const u8", writer, all_required),
|
||||||
.integer => |s| try generateSimpleTypeFor(s, "i64", writer, all_required),
|
.integer => |s| try generateSimpleTypeFor(s, "i64", writer, all_required),
|
||||||
.list => |s| {
|
.list => |s| {
|
||||||
_ = try writer.write("[]");
|
_ = try writer.write("[]");
|
||||||
try generateTypeFor(allocator, shape.list.member_target, shapes, writer, prefix, all_required, type_stack);
|
try generateTypeFor(allocator, shape.list.member_target, shapes, writer, prefix, all_required, type_stack, true);
|
||||||
},
|
},
|
||||||
.set => |s| {
|
.set => |s| {
|
||||||
_ = try writer.write("[]");
|
_ = try writer.write("[]");
|
||||||
try generateTypeFor(allocator, shape.set.member_target, shapes, writer, prefix, all_required, type_stack);
|
try generateTypeFor(allocator, shape.set.member_target, shapes, writer, prefix, all_required, type_stack, true);
|
||||||
},
|
},
|
||||||
.timestamp => |s| try generateSimpleTypeFor(s, "i64", writer, all_required),
|
.timestamp => |s| try generateSimpleTypeFor(s, "i64", writer, all_required),
|
||||||
.blob => |s| try generateSimpleTypeFor(s, "[]const u8", writer, all_required),
|
.blob => |s| try generateSimpleTypeFor(s, "[]const u8", writer, all_required),
|
||||||
|
@ -245,12 +278,12 @@ fn generateTypeFor(allocator: *std.mem.Allocator, shape_id: []const u8, shapes:
|
||||||
defer allocator.free(new_prefix);
|
defer allocator.free(new_prefix);
|
||||||
try writer.print("{s} key: ", .{prefix});
|
try writer.print("{s} key: ", .{prefix});
|
||||||
if (!all_required) try writeOptional(shape.map.traits, writer, null);
|
if (!all_required) try writeOptional(shape.map.traits, writer, null);
|
||||||
try generateTypeFor(allocator, shape.map.key, shapes, writer, prefix, all_required, type_stack);
|
try generateTypeFor(allocator, shape.map.key, shapes, writer, prefix, all_required, type_stack, true);
|
||||||
if (!all_required) try writeOptional(shape.map.traits, writer, " = null");
|
if (!all_required) try writeOptional(shape.map.traits, writer, " = null");
|
||||||
_ = try writer.write(",\n");
|
_ = try writer.write(",\n");
|
||||||
try writer.print("{s} value: ", .{prefix});
|
try writer.print("{s} value: ", .{prefix});
|
||||||
if (!all_required) try writeOptional(shape.map.traits, writer, null);
|
if (!all_required) try writeOptional(shape.map.traits, writer, null);
|
||||||
try generateTypeFor(allocator, shape.map.key, shapes, writer, prefix, all_required, type_stack);
|
try generateTypeFor(allocator, shape.map.key, shapes, writer, prefix, all_required, type_stack, true);
|
||||||
if (!all_required) try writeOptional(shape.map.traits, writer, " = null");
|
if (!all_required) try writeOptional(shape.map.traits, writer, " = null");
|
||||||
_ = try writer.write(",\n");
|
_ = try writer.write(",\n");
|
||||||
_ = try writer.write(prefix);
|
_ = try writer.write(prefix);
|
||||||
|
@ -278,16 +311,13 @@ fn generateComplexTypeFor(allocator: *std.mem.Allocator, members: []smithy.TypeM
|
||||||
defer allocator.free(new_prefix);
|
defer allocator.free(new_prefix);
|
||||||
const snake_case_member = try snake.fromPascalCase(allocator, member.name);
|
const snake_case_member = try snake.fromPascalCase(allocator, member.name);
|
||||||
defer allocator.free(snake_case_member);
|
defer allocator.free(snake_case_member);
|
||||||
try writer.print("{s} {s}: ", .{ prefix, snake_case_member });
|
try writer.print("{s} {s}: ", .{ prefix, avoidReserved(snake_case_member) });
|
||||||
if (!all_required) try writeOptional(member.traits, writer, null);
|
if (!all_required) try writeOptional(member.traits, writer, null);
|
||||||
try generateTypeFor(allocator, member.target, shapes, writer, new_prefix, all_required, type_stack);
|
try generateTypeFor(allocator, member.target, shapes, writer, new_prefix, all_required, type_stack, true);
|
||||||
if (!all_required) try writeOptional(member.traits, writer, " = null");
|
if (!all_required and !std.mem.eql(u8, "union", type_type_name))
|
||||||
|
try writeOptional(member.traits, writer, " = null");
|
||||||
_ = try writer.write(",\n");
|
_ = try writer.write(",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// epilog
|
|
||||||
try writer.print("{s}", .{prefix});
|
|
||||||
_ = try writer.write("}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeOptional(traits: ?[]smithy.Trait, writer: anytype, value: ?[]const u8) !void {
|
fn writeOptional(traits: ?[]smithy.Trait, writer: anytype, value: ?[]const u8) !void {
|
||||||
|
@ -299,11 +329,19 @@ fn writeOptional(traits: ?[]smithy.Trait, writer: anytype, value: ?[]const u8) !
|
||||||
// not required
|
// not required
|
||||||
if (value) |v| {
|
if (value) |v| {
|
||||||
_ = try writer.write(v);
|
_ = try writer.write(v);
|
||||||
} else
|
} else _ = try writer.write("?");
|
||||||
_ = try writer.write("?");
|
|
||||||
}
|
}
|
||||||
fn camelCase(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 {
|
fn camelCase(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 {
|
||||||
const first_letter = name[0] + ('a' - 'A');
|
const first_letter = name[0] + ('a' - 'A');
|
||||||
return try std.fmt.allocPrint(allocator, "{c}{s}", .{ first_letter, name[1..] });
|
return try std.fmt.allocPrint(allocator, "{c}{s}", .{ first_letter, name[1..] });
|
||||||
}
|
}
|
||||||
|
fn avoidReserved(snake_name: []const u8) []const u8 {
|
||||||
|
if (std.mem.eql(u8, snake_name, "error")) return "@\"error\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "return")) return "@\"return\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "not")) return "@\"not\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "and")) return "@\"and\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "or")) return "@\"or\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "test")) return "@\"test\"";
|
||||||
|
if (std.mem.eql(u8, snake_name, "null")) return "@\"null\"";
|
||||||
|
return snake_name;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user