1 module nxt.container.array_store; 2 3 import std.experimental.allocator.common : isAllocator; 4 5 @safe: 6 7 /++ Array storage. 8 +/ 9 struct ArrayStore(T, Allocator = GCAllocator, Capacity = size_t) 10 if (!is(immutable T == immutable bool) && // use `BitArray` instead for now 11 (is(Capacity == ulong) || // three 64-bit words 12 is(Capacity == uint)) && // two 64-bit words 13 isAllocator!Allocator) { /+ TODO: extract to separate D module ArrayStore +/ 14 pragma(inline, true): 15 16 this(T[] slice, in Capacity length) @trusted pure nothrow @nogc { // construct from slice 17 static if (__traits(hasMember, this, "_slice")) 18 _slice = slice; 19 else { 20 _ptr = slice.ptr; 21 assert(slice.length <= Capacity.max); 22 _capacity = cast(Capacity)slice.length; // trusted within this module. TODO: try to get rid of this 23 } 24 _length = length; 25 } 26 27 this(T* ptr, in Capacity capacityAndLength) @trusted pure nothrow @nogc { 28 version (DigitalMars) pragma(inline, false); 29 static if (__traits(hasMember, this, "_slice")) 30 _slice = ptr[0 .. capacityAndLength]; 31 else { 32 _ptr = ptr; 33 _capacity = capacityAndLength; 34 } 35 _length = capacityAndLength; 36 } 37 38 this(T* ptr, in Capacity capacity, in Capacity length) @trusted pure nothrow @nogc { 39 version (DigitalMars) pragma(inline, false); 40 static if (__traits(hasMember, this, "_slice")) 41 _slice = ptr[0 .. capacity]; 42 else { 43 _ptr = ptr; 44 _capacity = capacity; 45 } 46 _length = length; 47 } 48 49 inout(T)* ptr() inout @trusted pure nothrow @nogc { 50 static if (__traits(hasMember, this, "_slice")) 51 return _slice.ptr; 52 else 53 return _ptr; 54 } 55 56 Capacity capacity() const @trusted pure nothrow @nogc { 57 static if (__traits(hasMember, this, "_slice")) 58 return _slice.length; 59 else 60 return _capacity; 61 } 62 63 Capacity length() const @trusted pure nothrow @nogc { 64 return _length; 65 } 66 67 inout(T)[] opSlice() inout @trusted pure nothrow @nogc { 68 static if (__traits(hasMember, this, "_slice")) 69 return _slice; 70 else 71 return _ptr[0 .. _capacity]; 72 } 73 74 package: 75 import std.traits : hasFunctionAttributes; 76 enum isNoGc = hasFunctionAttributes!(Allocator.allocate, "@nogc"); 77 static if (isNoGc) 78 import nxt.gc_traits : NoGc; 79 static if (is(Capacity == size_t)) { 80 static if (isNoGc) { 81 @NoGc T[] _slice; // non-GC-allocated 82 /+ TODO: static assert(!mustAddGCRange!(typeof(slice))); +/ 83 } else 84 T[] _slice; // GC-allocated 85 Capacity _length; 86 } else { 87 static if (isNoGc) 88 @NoGc T* _ptr; // non-GC-allocated 89 else 90 T* _ptr; // GC-allocated 91 Capacity _capacity; 92 Capacity _length; 93 } 94 }