Skip to content

Instantly share code, notes, and snippets.

@alexnask
Created April 27, 2020 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexnask/bbfba0f149c62b54134c6d04bb2bdc5c to your computer and use it in GitHub Desktop.
Save alexnask/bbfba0f149c62b54134c6d04bb2bdc5c to your computer and use it in GitHub Desktop.
const std = @import("std");
const GuildJson = struct {
id: []const u8,
name: []const u8,
icon: []const u8,
owner: bool,
permissions: u53,
features: [][]const u8,
};
const Guild = struct {
id: Snowflake,
name: []const u8,
icon: []const u8,
owner: bool,
permissions: Permissions,
features: [][]const u8,
};
const Snowflake = struct {
value: u64,
};
const Permissions = struct {
value: u53,
};
fn transmute_field(in: var, comptime Out: type) !Out {
const InType = @TypeOf(in);
return switch (InType) {
[]const u8 => switch (Out) {
Snowflake => .{ .value = try std.fmt.parseInt(u64, in, 10) },
else => @compileError("Cannot transmute field from type " ++ @typeName(InType) ++ " to type " ++ @typeName(Out)),
},
u53 => switch (Out) {
Permissions => .{ .value = in },
else => @compileError("Cannot transmute field from type " ++ @typeName(InType) ++ " to type " ++ @typeName(Out)),
},
else => @compileError("Cannot transmute field from type " ++ @typeName(InType)),
};
}
fn transmute_free(in: var, comptime Result: type, alloc: *std.mem.Allocator) !Result {
const InType = @TypeOf(in);
var result: Result = undefined;
inline for (std.meta.fields(InType)) |field| {
if (!comptime std.meta.trait.hasField(field.name)(Result)) {
@compileError("No field " ++ field.name ++ " in type " ++ @typeName(Result));
}
const OutFieldType = @TypeOf(@field(result, field.name));
const InFieldType = @TypeOf(@field(in, field.name));
if (InFieldType != OutFieldType) {
defer if (comptime std.meta.trait.isSlice(InFieldType) and std.meta.Child(InFieldType) == u8) {
alloc.free(@field(in, field.name));
};
@field(result, field.name) = try transmute_field(@field(in, field.name), OutFieldType);
} else {
@field(result, field.name) = @field(in, field.name);
}
}
return result;
}
test "" {
const alloc = std.testing.allocator;
const guild_json = GuildJson{
.id = try std.mem.dupe(alloc, u8, "012748544"),
.name = try std.mem.dupe(alloc, u8, "NAME"),
.icon = try std.mem.dupe(alloc, u8, "ICON"),
.owner = true,
.permissions = 1,
.features = &[_][]const u8{},
};
errdefer {
alloc.free(guild_json.id);
alloc.free(guild_json.name);
alloc.free(guild_json.icon);
}
const guild = try transmute_free(guild_json, Guild, alloc);
defer {
alloc.free(guild.name);
alloc.free(guild.icon);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment