DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

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 }