mirror of
https://github.com/ziglang/zig.git
synced 2025-12-31 18:43:18 +00:00
199 lines
5.9 KiB
Zig
199 lines
5.9 KiB
Zig
const std = @import("std");
|
|
const fs = std.fs;
|
|
const mem = std.mem;
|
|
const log = std.log.scoped(.tapi);
|
|
const yaml = @import("tapi/yaml.zig");
|
|
|
|
const Allocator = mem.Allocator;
|
|
const Yaml = yaml.Yaml;
|
|
|
|
const VersionField = union(enum) {
|
|
string: []const u8,
|
|
float: f64,
|
|
int: u64,
|
|
};
|
|
|
|
pub const TbdV3 = struct {
|
|
archs: []const []const u8,
|
|
uuids: []const []const u8,
|
|
platform: []const u8,
|
|
install_name: []const u8,
|
|
current_version: ?VersionField,
|
|
compatibility_version: ?VersionField,
|
|
objc_constraint: ?[]const u8,
|
|
parent_umbrella: ?[]const u8,
|
|
exports: ?[]const struct {
|
|
archs: []const []const u8,
|
|
allowable_clients: ?[]const []const u8,
|
|
re_exports: ?[]const []const u8,
|
|
symbols: ?[]const []const u8,
|
|
weak_symbols: ?[]const []const u8,
|
|
objc_classes: ?[]const []const u8,
|
|
objc_ivars: ?[]const []const u8,
|
|
objc_eh_types: ?[]const []const u8,
|
|
},
|
|
};
|
|
|
|
pub const TbdV4 = struct {
|
|
tbd_version: u3,
|
|
targets: []const []const u8,
|
|
uuids: ?[]const struct {
|
|
target: []const u8,
|
|
value: []const u8,
|
|
},
|
|
install_name: []const u8,
|
|
current_version: ?VersionField,
|
|
compatibility_version: ?VersionField,
|
|
reexported_libraries: ?[]const struct {
|
|
targets: []const []const u8,
|
|
libraries: []const []const u8,
|
|
},
|
|
parent_umbrella: ?[]const struct {
|
|
targets: []const []const u8,
|
|
umbrella: []const u8,
|
|
},
|
|
exports: ?[]const struct {
|
|
targets: []const []const u8,
|
|
symbols: ?[]const []const u8,
|
|
weak_symbols: ?[]const []const u8,
|
|
objc_classes: ?[]const []const u8,
|
|
objc_ivars: ?[]const []const u8,
|
|
objc_eh_types: ?[]const []const u8,
|
|
},
|
|
reexports: ?[]const struct {
|
|
targets: []const []const u8,
|
|
symbols: ?[]const []const u8,
|
|
weak_symbols: ?[]const []const u8,
|
|
objc_classes: ?[]const []const u8,
|
|
objc_ivars: ?[]const []const u8,
|
|
objc_eh_types: ?[]const []const u8,
|
|
},
|
|
allowable_clients: ?[]const struct {
|
|
targets: []const []const u8,
|
|
clients: []const []const u8,
|
|
},
|
|
objc_classes: ?[]const []const u8,
|
|
objc_ivars: ?[]const []const u8,
|
|
objc_eh_types: ?[]const []const u8,
|
|
};
|
|
|
|
pub const Tbd = union(enum) {
|
|
v3: TbdV3,
|
|
v4: TbdV4,
|
|
|
|
/// Caller owns memory.
|
|
pub fn targets(self: Tbd, gpa: Allocator) error{OutOfMemory}![]const []const u8 {
|
|
var out = std.ArrayList([]const u8).init(gpa);
|
|
defer out.deinit();
|
|
|
|
switch (self) {
|
|
.v3 => |v3| {
|
|
try out.ensureTotalCapacityPrecise(v3.archs.len);
|
|
for (v3.archs) |arch| {
|
|
const target = try std.fmt.allocPrint(gpa, "{s}-{s}", .{ arch, v3.platform });
|
|
out.appendAssumeCapacity(target);
|
|
}
|
|
},
|
|
.v4 => |v4| {
|
|
try out.ensureTotalCapacityPrecise(v4.targets.len);
|
|
for (v4.targets) |t| {
|
|
out.appendAssumeCapacity(try gpa.dupe(u8, t));
|
|
}
|
|
},
|
|
}
|
|
|
|
return out.toOwnedSlice();
|
|
}
|
|
|
|
pub fn currentVersion(self: Tbd) ?VersionField {
|
|
return switch (self) {
|
|
.v3 => |v3| v3.current_version,
|
|
.v4 => |v4| v4.current_version,
|
|
};
|
|
}
|
|
|
|
pub fn compatibilityVersion(self: Tbd) ?VersionField {
|
|
return switch (self) {
|
|
.v3 => |v3| v3.compatibility_version,
|
|
.v4 => |v4| v4.compatibility_version,
|
|
};
|
|
}
|
|
|
|
pub fn installName(self: Tbd) []const u8 {
|
|
return switch (self) {
|
|
.v3 => |v3| v3.install_name,
|
|
.v4 => |v4| v4.install_name,
|
|
};
|
|
}
|
|
};
|
|
|
|
pub const TapiError = error{
|
|
NotLibStub,
|
|
FileTooBig,
|
|
} || yaml.YamlError || std.fs.File.ReadError;
|
|
|
|
pub const LibStub = struct {
|
|
/// Underlying memory for stub's contents.
|
|
yaml: Yaml,
|
|
|
|
/// Typed contents of the tbd file.
|
|
inner: []Tbd,
|
|
|
|
pub fn loadFromFile(allocator: Allocator, file: fs.File) TapiError!LibStub {
|
|
const source = try file.readToEndAlloc(allocator, std.math.maxInt(u32));
|
|
defer allocator.free(source);
|
|
|
|
var lib_stub = LibStub{
|
|
.yaml = try Yaml.load(allocator, source),
|
|
.inner = undefined,
|
|
};
|
|
|
|
// TODO revisit this logic in the hope of simplifying it.
|
|
lib_stub.inner = blk: {
|
|
err: {
|
|
log.debug("trying to parse as []TbdV4", .{});
|
|
const inner = lib_stub.yaml.parse([]TbdV4) catch break :err;
|
|
var out = try lib_stub.yaml.arena.allocator().alloc(Tbd, inner.len);
|
|
for (inner, 0..) |doc, i| {
|
|
out[i] = .{ .v4 = doc };
|
|
}
|
|
break :blk out;
|
|
}
|
|
|
|
err: {
|
|
log.debug("trying to parse as TbdV4", .{});
|
|
const inner = lib_stub.yaml.parse(TbdV4) catch break :err;
|
|
var out = try lib_stub.yaml.arena.allocator().alloc(Tbd, 1);
|
|
out[0] = .{ .v4 = inner };
|
|
break :blk out;
|
|
}
|
|
|
|
err: {
|
|
log.debug("trying to parse as []TbdV3", .{});
|
|
const inner = lib_stub.yaml.parse([]TbdV3) catch break :err;
|
|
var out = try lib_stub.yaml.arena.allocator().alloc(Tbd, inner.len);
|
|
for (inner, 0..) |doc, i| {
|
|
out[i] = .{ .v3 = doc };
|
|
}
|
|
break :blk out;
|
|
}
|
|
|
|
err: {
|
|
log.debug("trying to parse as TbdV3", .{});
|
|
const inner = lib_stub.yaml.parse(TbdV3) catch break :err;
|
|
var out = try lib_stub.yaml.arena.allocator().alloc(Tbd, 1);
|
|
out[0] = .{ .v3 = inner };
|
|
break :blk out;
|
|
}
|
|
|
|
return error.NotLibStub;
|
|
};
|
|
|
|
return lib_stub;
|
|
}
|
|
|
|
pub fn deinit(self: *LibStub) void {
|
|
self.yaml.deinit();
|
|
}
|
|
};
|