update servicemodel for generated model
This increases compilation time significantly as all 260+ services need to be analyzed by zig during compilation. I plan to change the model from a single "services" constant to a function that will import only services that plan to be used. This might be in addition to the single constant to allow consumers to choose short compile times or all services support
This commit is contained in:
parent
88632df671
commit
bd5d509665
51
src/aws.zig
51
src/aws.zig
|
@ -27,15 +27,16 @@ pub const Aws = struct {
|
|||
}
|
||||
|
||||
pub fn call(self: Self, comptime request: anytype, options: Options) !FullResponse(request) {
|
||||
const action_info = actionForRequest(request);
|
||||
// This is true weirdness, but we are running into compiler bugs. Touch only if
|
||||
// prepared...
|
||||
const service = @field(services, action_info.service);
|
||||
const action = @field(service, action_info.action);
|
||||
// every codegenned request object includes a metaInfo function to get
|
||||
// pointers to service and action
|
||||
const meta_info = request.metaInfo();
|
||||
const service = meta_info.service;
|
||||
const action = meta_info.action;
|
||||
const R = Response(request);
|
||||
const FullR = FullResponse(request);
|
||||
|
||||
log.debug("service {s}", .{action_info.service});
|
||||
log.debug("service endpoint {s}", .{service.endpoint_prefix});
|
||||
log.debug("service sigv4 name {s}", .{service.sigv4_name});
|
||||
log.debug("version {s}", .{service.version});
|
||||
log.debug("action {s}", .{action.action_name});
|
||||
const response = try self.aws_http.callApi(action_info.service, service.version, action.action_name, options);
|
||||
|
@ -73,40 +74,9 @@ pub const Aws = struct {
|
|||
}
|
||||
};
|
||||
|
||||
fn actionForRequest(comptime request: anytype) struct { service: []const u8, action: []const u8, service_obj: anytype } {
|
||||
const type_name = @typeName(@TypeOf(request));
|
||||
var service_start: usize = 0;
|
||||
var service_end: usize = 0;
|
||||
var action_start: usize = 0;
|
||||
var action_end: usize = 0;
|
||||
for (type_name) |ch, i| {
|
||||
switch (ch) {
|
||||
'(' => service_start = i + 2,
|
||||
')' => action_end = i - 1,
|
||||
',' => {
|
||||
service_end = i - 1;
|
||||
action_start = i + 2;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
// const zero: usize = 0;
|
||||
// TODO: Figure out why if statement isn't working
|
||||
// if (serviceStart == zero or serviceEnd == zero or actionStart == zero or actionEnd == zero) {
|
||||
// @compileLog("Type must be a function with two parameters \"service\" and \"action\". Found: " ++ type_name);
|
||||
// // @compileError("Type must be a function with two parameters \"service\" and \"action\". Found: " ++ type_name);
|
||||
// }
|
||||
return .{
|
||||
.service = type_name[service_start..service_end],
|
||||
.action = type_name[action_start..action_end],
|
||||
.service_obj = @field(services, type_name[service_start..service_end]),
|
||||
};
|
||||
}
|
||||
fn ServerResponse(comptime request: anytype) type {
|
||||
const T = Response(request);
|
||||
const action_info = actionForRequest(request);
|
||||
const service = @field(services, action_info.service);
|
||||
const action = @field(service, action_info.action);
|
||||
const action = request.metaInfo().action;
|
||||
// NOTE: The non-standard capitalization here is used as a performance
|
||||
// enhancement and to reduce allocations in json.zig. These fields are
|
||||
// not (nor are they ever intended to be) exposed outside this codebase
|
||||
|
@ -169,8 +139,5 @@ fn FullResponse(comptime request: anytype) type {
|
|||
};
|
||||
}
|
||||
fn Response(comptime request: anytype) type {
|
||||
const action_info = actionForRequest(request);
|
||||
const service = @field(services, action_info.service);
|
||||
const action = @field(service, action_info.action);
|
||||
return action.Response;
|
||||
return request.metaInfo().action.Response;
|
||||
}
|
||||
|
|
|
@ -1,108 +1,50 @@
|
|||
const std = @import("std");
|
||||
const models = @import("models.zig");
|
||||
const json = @import("json.zig");
|
||||
const expectEqualStrings = std.testing.expectEqualStrings;
|
||||
|
||||
// TODO: Make generic
|
||||
fn Services() type {
|
||||
const types = [_]type{
|
||||
Service("sts"),
|
||||
// This service list can be imported from a master file of all services
|
||||
// provided by codegen
|
||||
const service_list = @import("codegen/service_manifest.zig").services;
|
||||
|
||||
// From here, the fields of our structure can be generated at comptime...
|
||||
var fields: [service_list.len]std.builtin.TypeInfo.StructField = undefined;
|
||||
for (fields) |*item, i| {
|
||||
const import = @field(@import("codegen/models/" ++ service_list[i].file_name), service_list[i].export_name);
|
||||
item.* = .{
|
||||
.name = service_list[i].name,
|
||||
.field_type = @TypeOf(import),
|
||||
.default_value = import,
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
};
|
||||
}
|
||||
|
||||
// finally, generate the type
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.layout = .Auto,
|
||||
.fields = &[_]std.builtin.TypeInfo.StructField{
|
||||
.{
|
||||
.name = "sts",
|
||||
.field_type = types[0],
|
||||
.default_value = new(types[0]),
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
},
|
||||
.fields = &fields,
|
||||
.decls = &[_]std.builtin.TypeInfo.Declaration{},
|
||||
.is_tuple = false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
fn ServiceActionResponse(comptime service: []const u8, comptime action: []const u8) type {
|
||||
if (std.mem.eql(u8, service, "sts") and std.mem.eql(u8, action, "get_caller_identity")) {
|
||||
return struct {
|
||||
arn: []const u8,
|
||||
user_id: []const u8,
|
||||
account: []const u8,
|
||||
};
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn ServiceAction(comptime service: []const u8, comptime action: []const u8) type {
|
||||
if (std.mem.eql(u8, service, "sts") and std.mem.eql(u8, action, "get_caller_identity")) {
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.layout = .Auto,
|
||||
.fields = &[_]std.builtin.TypeInfo.StructField{
|
||||
.{
|
||||
.name = "Request",
|
||||
.field_type = type,
|
||||
.default_value = struct {},
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
.{
|
||||
.name = "action_name",
|
||||
.field_type = @TypeOf("GetCallerIdentity"),
|
||||
.default_value = "GetCallerIdentity",
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
.{
|
||||
.name = "Response",
|
||||
.field_type = type,
|
||||
.default_value = ServiceActionResponse("sts", "get_caller_identity"),
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
},
|
||||
.decls = &[_]std.builtin.TypeInfo.Declaration{},
|
||||
.is_tuple = false,
|
||||
},
|
||||
});
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// TODO: One constant to rule them all is a bit much. We can keep this
|
||||
// in the back pocket, but let's move to a factory style getService("blah");
|
||||
pub const services = Services(){};
|
||||
|
||||
fn new(comptime T: type) T {
|
||||
return T{};
|
||||
test "services includes sts" {
|
||||
expectEqualStrings("2011-06-15", services.sts.version);
|
||||
}
|
||||
fn Service(comptime service: []const u8) type {
|
||||
if (std.mem.eql(u8, "sts", service)) {
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.layout = .Auto,
|
||||
.fields = &[_]std.builtin.TypeInfo.StructField{
|
||||
.{
|
||||
.name = "version",
|
||||
.field_type = @TypeOf("2011-06-15"),
|
||||
.default_value = "2011-06-15",
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
.{
|
||||
.name = "get_caller_identity",
|
||||
.field_type = ServiceAction("sts", "get_caller_identity"),
|
||||
.default_value = new(ServiceAction("sts", "get_caller_identity")),
|
||||
.is_comptime = false,
|
||||
.alignment = 0,
|
||||
},
|
||||
},
|
||||
.decls = &[_]std.builtin.TypeInfo.Declaration{},
|
||||
.is_tuple = false,
|
||||
},
|
||||
});
|
||||
}
|
||||
unreachable;
|
||||
test "sts includes get_caller_identity" {
|
||||
expectEqualStrings("GetCallerIdentity", services.sts.get_caller_identity.action_name);
|
||||
}
|
||||
test "can get service and action name from request" {
|
||||
// get request object. This call doesn't have parameters
|
||||
const req = services.sts.get_caller_identity.Request{};
|
||||
// const metadata = @TypeOf(req).metaInfo();
|
||||
const metadata = req.metaInfo();
|
||||
expectEqualStrings("2011-06-15", metadata.service.version);
|
||||
// expectEqualStrings("GetCallerIdentity", metadata.action.action_name);
|
||||
}
|
||||
// End code "generation" prototype
|
||||
|
|
Loading…
Reference in New Issue
Block a user