Guest User

Untitled

a guest
Jul 9th, 2019
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.01 KB | None | 0 0
  1. const std = @import("std");
  2. const builtin = @import("builtin");
  3.  
  4. const debug = std.debug;
  5.  
  6. /// An errorset for an ArrayVec
  7. const ArrayError = error {
  8.     CapacityError,
  9. };
  10.  
  11. pub fn ArrayVec(comptime T: type, comptime SIZE: usize) type {
  12.     return struct {
  13.         array: [SIZE]T,
  14.         length: usize,
  15.  
  16.         const Self = @This();
  17.  
  18.         /// Returns a new empty ArrayVec.
  19.         pub fn new() Self {
  20.             return Self {
  21.                 .array = undefined, .length = comptime_int(0),
  22.             };
  23.         }
  24.  
  25.         /// Returns the length of the ArrayVec.
  26.         pub fn len(self: *const Self) usize {
  27.             return self.length;
  28.         }
  29.  
  30.         /// Returns the capacity of the ArrayVec.
  31.         pub fn capacity(self: *const Self) usize {
  32.             return SIZE;
  33.         }
  34.  
  35.         /// Set's the length of the ArrayVec.
  36.         /// This changes the `meaning` of valid elements in the array.
  37.         pub fn set_len(self: *Self, new_len: usize) void {
  38.             debug.assert(new_len <= self.capacity());
  39.             self.length = new_len;
  40.         }
  41.  
  42.         /// Pushes `element` onto the array.
  43.         /// Panic's if the array was already full.
  44.         fn push(self: *Self, element: T) void {
  45.             self.try_push(element) catch unreachable;
  46.         }
  47.  
  48.         /// Pushes `element` onto the array.
  49.         /// If the array was already full,
  50.         /// An error is returned.
  51.         fn try_push(self: *Self, element: T) !void {
  52.             if (self.len() < self.capacity()) {
  53.                 self.push_unchecked(element);
  54.             } else {
  55.                 return ArrayError.CapacityError;
  56.             }
  57.         }
  58.  
  59.         /// Pushes `element` onto the array.
  60.         /// This function does *NOT* boundscheck.
  61.         fn push_unchecked(self: *Self, element: T) void {
  62.             // Store the length in a variable for reuse.
  63.             var self_len = self.len();
  64.  
  65.             debug.assert(self_len < self.capacity());
  66.             self.array[self_len] = element;
  67.             self.set_len(self_len + 1);
  68.         }
  69.  
  70.         fn iter(self: *const Self) Iter(T, SIZE) {
  71.            return Iter(T, SIZE).new(self);
  72.         }
  73.  
  74.         fn iter_mut(self: *Self) IterMut(T, SIZE) {
  75.             return IterMut(T, SIZE).new(self);
  76.         }
  77.     };
  78. }
  79.  
  80. fn compile_error_if(comptime condition: bool, comptime msg: []const u8) void {
  81.     if(condition) {
  82.         @compileError(msg);
  83.     }
  84. }
  85.  
  86. fn __iter__(comptime Item: type, comptime Vec: type) type {
  87.     // `Item` should be a pointer.
  88.     // `Vec` should be of type *ArrayVec(Item, N) OR *const ArrayVec(Item, N).
  89.     comptime {
  90.         compile_error_if(
  91.             !std.meta.trait.is(builtin.TypeId.Pointer)(Item),
  92.             "Expected a Pointer for `Item`. Found `" ++ @typeName(Item) ++ "`."
  93.         );
  94.  
  95.         const item_name = switch (@typeInfo(Item)) {
  96.             builtin.TypeId.Pointer => |ptr| @typeName(ptr.child),
  97.             else => unreachable
  98.         };
  99.  
  100.         const name = switch (std.meta.trait.isConstPtr(Vec)) {
  101.             true => "*const ArrayVec(" ++ item_name,
  102.             else => "*ArrayVec(" ++ item_name,
  103.         };
  104.  
  105.         compile_error_if(
  106.             !std.mem.eql(u8, name, @typeName(Vec)[0..name.len]),
  107.             "Expected type `*const ArrayVec` or `*ArrayVec`. Found `" ++ @typeName(Vec) ++ "`."
  108.         );
  109.     }
  110.  
  111.     return struct {
  112.         array: Vec,
  113.         index: usize,
  114.  
  115.         const Self = @This();
  116.  
  117.         fn new(arrayvec: Vec) Self {
  118.             return  Self { .array = arrayvec, .index = comptime_int(0) };
  119.         }
  120.        
  121.         fn next(self: *Self) ?Item {
  122.             if (self.index < self.array.len()) {
  123.                 var elem = &self.array.array[self.index];
  124.                 self.index += 1;
  125.                 return elem;
  126.             } else {
  127.                 return null;
  128.             }
  129.         }
  130.     };
  131. }
  132.  
  133. fn Iter(comptime T: type, comptime SIZE: usize) type {
  134.     return __iter__(*const T, *const ArrayVec(T, SIZE));
  135. }
  136.  
  137. fn IterMut(comptime T: type, comptime SIZE: usize) type {
  138.     return __iter__(*T, *ArrayVec(T, SIZE));
  139. }
  140.  
  141. test "const basic functions" {
  142.     comptime {
  143.         var arrayvec = ArrayVec(i32, 10).new();
  144.         debug.assert(arrayvec.len() == 0);
  145.         debug.assert(arrayvec.capacity() == 10);
  146.     }
  147. }
  148.  
  149. test "const iter" {
  150.     comptime {
  151.         var arrayvec = ArrayVec(i32, 10).new();
  152.        
  153.         arrayvec.push(10);
  154.         arrayvec.push(20);
  155.  
  156.         var iter = arrayvec.iter();
  157.         debug.assert(iter.next().?.* == 10);
  158.         debug.assert(iter.next().?.* == 20);
  159.     }
  160. }
  161.  
  162. test "const iter mut" {
  163.     comptime {
  164.         var arrayvec = ArrayVec(i32, 10).new();
  165.        
  166.         arrayvec.push(10);
  167.         arrayvec.push(20);
  168.  
  169.         var iter = arrayvec.iter_mut();
  170.        
  171.         while(iter.next()) |item| {
  172.             item.* *= 2;
  173.         }
  174.        
  175.         var iter2 = arrayvec.iter();
  176.         debug.assert(iter2.next().?.* == 20);
  177.         debug.assert(iter2.next().?.* == 40);
  178.          
  179.     }
  180. }
Advertisement
Add Comment
Please, Sign In to add comment