1 module dmdtags.span; 2 3 // extern(C++) compatible slice type 4 struct Span(T) 5 { 6 private T* _ptr; 7 private size_t _length; 8 9 this(inout(T)[] slice) inout 10 { 11 _ptr = &slice[0]; 12 _length = slice.length; 13 } 14 15 inout(T)* ptr() inout { return _ptr; } 16 size_t length() const { return _length; } 17 18 inout(T)[] opIndex() inout 19 { 20 return ptr[0 .. length]; 21 } 22 23 ref inout(T) opIndex(size_t i) inout 24 { 25 assert(i < length); 26 return ptr[i]; 27 } 28 29 size_t[2] opSlice(size_t dim)(size_t start, size_t end) const 30 { 31 return [start, end]; 32 } 33 34 alias opDollar(size_t dim) = length; 35 36 inout(T)[] opIndex(size_t[2] bounds) inout 37 { 38 size_t start = bounds[0], end = bounds[1]; 39 assert(start <= end && end <= length); 40 return ptr[start .. end]; 41 } 42 43 bool opEquals(const Span rhs) const 44 { 45 return this[] == rhs[]; 46 } 47 48 int opCmp(const Span rhs) const 49 { 50 import std.algorithm.comparison: cmp; 51 52 return this[].cmp(rhs[]); 53 } 54 55 // qual(Span!T) -> Span!(qual(T)) 56 auto headMutable(this This)() 57 { 58 import std.traits: CopyTypeQualifiers; 59 60 return Span!(CopyTypeQualifiers!(This, T))(this[]); 61 } 62 63 void toString(Sink)(ref Sink sink) 64 { 65 import std.algorithm.mutation: copy; 66 67 copy(this[], sink); 68 } 69 } 70 71 inout(Span!T) span(T)(inout(T)[] slice) 72 { 73 return inout(Span!T)(slice); 74 } 75 76 unittest { 77 int[] arr = [1, 2, 3]; 78 auto span = span(arr); 79 80 assert(span.length == arr.length); 81 assert(span.ptr == arr.ptr); 82 assert(span[0] == 1); 83 assert(span[] == arr); 84 import std.stdio; 85 debug writeln(span[1 .. $]); 86 assert(span[1 .. $] == arr[1 .. $]); 87 }