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) {
|
pub fn call(self: Self, comptime request: anytype, options: Options) !FullResponse(request) {
|
||||||
const action_info = actionForRequest(request);
|
// every codegenned request object includes a metaInfo function to get
|
||||||
// This is true weirdness, but we are running into compiler bugs. Touch only if
|
// pointers to service and action
|
||||||
// prepared...
|
const meta_info = request.metaInfo();
|
||||||
const service = @field(services, action_info.service);
|
const service = meta_info.service;
|
||||||
const action = @field(service, action_info.action);
|
const action = meta_info.action;
|
||||||
const R = Response(request);
|
const R = Response(request);
|
||||||
const FullR = FullResponse(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("version {s}", .{service.version});
|
||||||
log.debug("action {s}", .{action.action_name});
|
log.debug("action {s}", .{action.action_name});
|
||||||
const response = try self.aws_http.callApi(action_info.service, service.version, action.action_name, options);
|
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 {
|
fn ServerResponse(comptime request: anytype) type {
|
||||||
const T = Response(request);
|
const T = Response(request);
|
||||||
const action_info = actionForRequest(request);
|
const action = request.metaInfo().action;
|
||||||
const service = @field(services, action_info.service);
|
|
||||||
const action = @field(service, action_info.action);
|
|
||||||
// NOTE: The non-standard capitalization here is used as a performance
|
// NOTE: The non-standard capitalization here is used as a performance
|
||||||
// enhancement and to reduce allocations in json.zig. These fields are
|
// enhancement and to reduce allocations in json.zig. These fields are
|
||||||
// not (nor are they ever intended to be) exposed outside this codebase
|
// 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 {
|
fn Response(comptime request: anytype) type {
|
||||||
const action_info = actionForRequest(request);
|
return request.metaInfo().action.Response;
|
||||||
const service = @field(services, action_info.service);
|
|
||||||
const action = @field(service, action_info.action);
|
|
||||||
return action.Response;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,108 +1,50 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const models = @import("models.zig");
|
const expectEqualStrings = std.testing.expectEqualStrings;
|
||||||
const json = @import("json.zig");
|
|
||||||
|
|
||||||
// TODO: Make generic
|
// TODO: Make generic
|
||||||
fn Services() type {
|
fn Services() type {
|
||||||
const types = [_]type{
|
// This service list can be imported from a master file of all services
|
||||||
Service("sts"),
|
// 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(.{
|
return @Type(.{
|
||||||
.Struct = .{
|
.Struct = .{
|
||||||
.layout = .Auto,
|
.layout = .Auto,
|
||||||
.fields = &[_]std.builtin.TypeInfo.StructField{
|
.fields = &fields,
|
||||||
.{
|
|
||||||
.name = "sts",
|
|
||||||
.field_type = types[0],
|
|
||||||
.default_value = new(types[0]),
|
|
||||||
.is_comptime = false,
|
|
||||||
.alignment = 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
.decls = &[_]std.builtin.TypeInfo.Declaration{},
|
.decls = &[_]std.builtin.TypeInfo.Declaration{},
|
||||||
.is_tuple = false,
|
.is_tuple = false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// TODO: One constant to rule them all is a bit much. We can keep this
|
||||||
fn ServiceActionResponse(comptime service: []const u8, comptime action: []const u8) type {
|
// in the back pocket, but let's move to a factory style getService("blah");
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const services = Services(){};
|
pub const services = Services(){};
|
||||||
|
|
||||||
fn new(comptime T: type) T {
|
test "services includes sts" {
|
||||||
return T{};
|
expectEqualStrings("2011-06-15", services.sts.version);
|
||||||
}
|
}
|
||||||
fn Service(comptime service: []const u8) type {
|
test "sts includes get_caller_identity" {
|
||||||
if (std.mem.eql(u8, "sts", service)) {
|
expectEqualStrings("GetCallerIdentity", services.sts.get_caller_identity.action_name);
|
||||||
return @Type(.{
|
}
|
||||||
.Struct = .{
|
test "can get service and action name from request" {
|
||||||
.layout = .Auto,
|
// get request object. This call doesn't have parameters
|
||||||
.fields = &[_]std.builtin.TypeInfo.StructField{
|
const req = services.sts.get_caller_identity.Request{};
|
||||||
.{
|
// const metadata = @TypeOf(req).metaInfo();
|
||||||
.name = "version",
|
const metadata = req.metaInfo();
|
||||||
.field_type = @TypeOf("2011-06-15"),
|
expectEqualStrings("2011-06-15", metadata.service.version);
|
||||||
.default_value = "2011-06-15",
|
// expectEqualStrings("GetCallerIdentity", metadata.action.action_name);
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
// End code "generation" prototype
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user