lib/choir/src/backends/artifact/model/option.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const Allocator = std.mem.Allocator;
  3 const artifact = @import("root.zig");
  4 const slice = artifact.slice;
  5 
  6 pub const OptionValueTag = enum(u8) {
  7     flag = 1,
  8     signed = 2,
  9     unsigned = 3,
 10     text = 4,
 11     bytes = 5,
 12 };
 13 
 14 pub const OptionValue = union(OptionValueTag) {
 15     flag: bool,
 16     signed: i64,
 17     unsigned: u64,
 18     text: []const u8,
 19     bytes: []const u8,
 20 
 21     pub fn dupe(self: OptionValue, allocator: Allocator) Allocator.Error!OptionValue {
 22         return switch (self) {
 23             .flag => |value| .{ .flag = value },
 24             .signed => |value| .{ .signed = value },
 25             .unsigned => |value| .{ .unsigned = value },
 26             .text => |value| .{ .text = try slice.dupe(allocator, value) },
 27             .bytes => |value| .{ .bytes = try slice.dupe(allocator, value) },
 28         };
 29     }
 30 
 31     pub fn deinit(self: OptionValue, allocator: Allocator) void {
 32         switch (self) {
 33             .text => |value| slice.free(allocator, value),
 34             .bytes => |value| slice.free(allocator, value),
 35             else => {},
 36         }
 37     }
 38 
 39     pub fn eql(self: OptionValue, other: OptionValue) bool {
 40         if (std.meta.activeTag(self) != std.meta.activeTag(other)) return false;
 41         return switch (self) {
 42             .flag => |value| value == other.flag,
 43             .signed => |value| value == other.signed,
 44             .unsigned => |value| value == other.unsigned,
 45             .text => |value| std.mem.eql(u8, value, other.text),
 46             .bytes => |value| std.mem.eql(u8, value, other.bytes),
 47         };
 48     }
 49 };
 50 
 51 pub const BuildOption = struct {
 52     key: []const u8,
 53     value: OptionValue,
 54 
 55     pub fn dupe(self: BuildOption, allocator: Allocator) Allocator.Error!BuildOption {
 56         const key = try slice.dupe(allocator, self.key);
 57         errdefer slice.free(allocator, key);
 58         return .{ .key = key, .value = try self.value.dupe(allocator) };
 59     }
 60 
 61     pub fn deinit(self: BuildOption, allocator: Allocator) void {
 62         slice.free(allocator, self.key);
 63         self.value.deinit(allocator);
 64     }
 65 
 66     pub fn eql(self: BuildOption, other: BuildOption) bool {
 67         return std.mem.eql(u8, self.key, other.key) and self.value.eql(other.value);
 68     }
 69 };
 70 
 71 pub const Options = struct {
 72     allocator: Allocator,
 73     values: std.ArrayListUnmanaged(BuildOption) = .empty,
 74 
 75     pub fn init(allocator: Allocator) Options {
 76         return .{ .allocator = allocator };
 77     }
 78 
 79     pub fn add(self: *Options, option: BuildOption) Allocator.Error!void {
 80         try self.values.ensureTotalCapacity(self.allocator, self.values.items.len + 1);
 81         const owned = try option.dupe(self.allocator);
 82         self.values.appendAssumeCapacity(owned);
 83     }
 84 
 85     pub fn cloneInto(self: Options, target: *Options) Allocator.Error!void {
 86         for (self.values.items) |option| try target.add(option);
 87     }
 88 
 89     pub fn deinit(self: *Options) void {
 90         for (self.values.items) |option| option.deinit(self.allocator);
 91         self.values.deinit(self.allocator);
 92         self.* = undefined;
 93     }
 94 
 95     pub fn eql(self: Options, other: Options) bool {
 96         if (self.values.items.len != other.values.items.len) return false;
 97         for (self.values.items, other.values.items) |left, right| {
 98             if (!left.eql(right)) return false;
 99         }
100         return true;
101     }
102 };