lib::packed.zig (5316B)
1 const std = @import("std"); 2 3 const utils = @import("lib::utils.zig"); 4 5 const Error = error{NullPointer}; 6 7 pub fn Pointer(Type: type) type { 8 return packed struct { 9 const Self = @This(); 10 11 pub const optional = utils.is_type(Type, "optional"); 12 13 pub const Ptr = if (optional) @typeInfo(Type).optional.child else Type; 14 pub const Val = @typeInfo(Ptr).pointer.child; 15 pub const Opt = if (optional) ?Val else Val; 16 17 _ptr: usize, 18 19 pub fn create(allocator: std.mem.Allocator) !Self { 20 return Self.init(try allocator.create(Val)); 21 } 22 23 pub fn init(arg: Type) Self { 24 return Self{ 25 ._ptr = if (utils.optional(arg)) |val| 26 @intFromPtr(val) 27 else 28 0, 29 }; 30 } 31 32 pub fn ptr(self: Self) Type { 33 return if (optional and self._ptr == 0) 34 null 35 else 36 @ptrFromInt(self._ptr); 37 } 38 39 pub fn get(self: Self) Opt { 40 return if (utils.optional(self.ptr())) |pointer| 41 pointer.* 42 else if (optional) 43 null 44 else 45 unreachable; 46 } 47 48 pub fn set(self: Self, val: Val) if (optional) Error.NullPointer!void else void { 49 if (utils.optional(self.ptr())) |pointer| 50 pointer.* = val 51 else if (optional) 52 return Error.NullPointer 53 else 54 unreachable; 55 } 56 57 pub fn destroy(self: Self, allocator: std.mem.Allocator) void { 58 if (utils.optional(self.ptr())) |pointer| 59 allocator.destroy(pointer); 60 } 61 }; 62 } 63 64 pub fn Object(Type: type) type { 65 return packed struct { 66 const Self = @This(); 67 68 const Ptr = Pointer(Type); 69 70 _ptr: Ptr, 71 _own: bool, 72 73 pub fn create(allocator: std.mem.Allocator) !Self { 74 var self = Self.init(try allocator.create(Ptr.Val)); 75 if (utils.fn_error(Ptr.Val.init)) |_| 76 self._ptr.set(try Ptr.Val.init(allocator)) 77 else 78 self._ptr.set(Ptr.Val.init(allocator)); 79 80 self._own = true; 81 return self; 82 } 83 84 pub fn init(arg: Type) Self { 85 return Self{ 86 ._ptr = Ptr.init(arg), 87 ._own = false, 88 }; 89 } 90 91 pub fn own(self: Self) bool { 92 return self._own; 93 } 94 95 pub fn ptr(self: Self) Type { 96 return self._ptr.ptr(); 97 } 98 99 pub fn get(self: Self) Ptr.Opt { 100 return self._ptr.get(); 101 } 102 103 pub fn set(self: Self, val: Ptr.Val) if (Ptr.optional) Error.NullPointer!void else void { 104 self._ptr.set(val); 105 } 106 107 pub fn destroy(self: Self, allocator: std.mem.Allocator) void { 108 if (self._own) 109 self._ptr.ptr().deinit(); 110 self._ptr.destroy(allocator); 111 } 112 }; 113 } 114 115 pub fn Slice(Type: type) type { 116 return packed struct { 117 const Self = @This(); 118 const Ptr = Pointer(utils.with_size(Type, .many)); 119 120 _ptr: Ptr, 121 _len: usize, 122 123 pub fn create(allocator: std.mem.Allocator, count: usize) !Self { 124 return Self.init(try allocator.alloc(Ptr.Val, count)); 125 } 126 127 pub fn init(arg: Type) Self { 128 return if (Ptr.optional) 129 Self{ 130 ._ptr = Ptr.init(if (arg) |val| val.ptr else null), 131 ._len = if (arg) |val| val.len else 0, 132 } 133 else 134 Self{ 135 ._ptr = Ptr.init(arg.ptr), 136 ._len = arg.len, 137 }; 138 } 139 140 pub fn ptr(self: Self) Type { 141 return if (utils.optional(self._ptr.ptr())) |pointer| 142 pointer[0..self._len] 143 else if (Ptr.optional) 144 null 145 else 146 unreachable; 147 } 148 149 pub fn get(self: Self, idx: usize) Ptr.Opt { 150 return if (utils.optional(self.ptr())) |pointer| 151 pointer[idx] 152 else 153 null; 154 } 155 156 pub fn len(self: Self) usize { 157 return self._len; 158 } 159 160 pub fn set(self: Self, val: []Ptr.Val) if (Ptr.optional) Error.NullPointer!void else void { 161 if (utils.optional(self.ptr())) |pointer| 162 @memcpy(pointer, val) 163 else if (Ptr.optional) 164 return Error.NullPointer 165 else 166 unreachable; 167 } 168 169 pub fn destroy(self: Self, allocator: std.mem.Allocator) void { 170 if (utils.optional(self.ptr())) |pointer| 171 allocator.free(pointer); 172 } 173 }; 174 } 175 176 pub fn Packed(Type: type) type { 177 const Ptr = if (utils.is_type(Type, "optional")) @typeInfo(Type).optional.child else Type; 178 const Child = @typeInfo(Ptr).pointer.child; 179 180 return if (@typeInfo(Ptr).pointer.size == .slice) 181 Slice(Type) 182 else if ((utils.is_type(Child, "union") or 183 utils.is_type(Child, "enum") or 184 utils.is_type(Child, "struct")) and 185 @hasDecl(Child, "init") and 186 @hasDecl(Child, "deinit")) 187 Object(Type) 188 else 189 Pointer(Type); 190 }