1 module nxt.borrowed;
2 
3 /** Write-borrowed access to range `Range`. */
4 struct WriteBorrowed(Range, Owner)
5     // if (is(Owner == Owned!(_), _))
6 {
7     this(Range range, Owner* owner)
8     {
9         assert(owner);
10         _range = range;
11         _owner = owner;
12         owner._writeBorrowed = true;
13     }
14 
15     @disable this(this);        // cannot be copied
16 
17     ~this() nothrow @nogc
18     {
19         debug assert(_owner._writeBorrowed, "Write borrow flag is already false, something is wrong with borrowing logic");
20         _owner._writeBorrowed = false;
21     }
22 
23     Range _range;                   /// range
24     alias _range this;              /// behave like range
25 
26 private:
27     Owner* _owner = null;           /// pointer to container owner
28 }
29 
30 /** Read-borrowed access to range `Range`. */
31 struct ReadBorrowed(Range, Owner)
32     // if (is(Owner == Owned!(_), _))
33 {
34     this(const Range range, Owner* owner)
35     {
36         import core.internal.traits : Unqual;
37         _range = *(cast(Unqual!Range*)&range);
38         _owner = owner;
39         if (_owner)
40         {
41             assert(_owner._readBorrowCount != _owner.readBorrowCountMax, "Cannot have more borrowers");
42             _owner._readBorrowCount = _owner._readBorrowCount + 1;
43         }
44     }
45 
46     this(this)
47     {
48         if (_owner)
49         {
50             assert(_owner._readBorrowCount != _owner.readBorrowCountMax, "Cannot have more borrowers");
51             _owner._readBorrowCount = _owner._readBorrowCount + 1;
52         }
53     }
54 
55     ~this() nothrow @nogc
56     {
57         if (_owner)
58         {
59             assert(_owner._readBorrowCount != 0, "Read borrow counter is already zero, something is wrong with borrowing logic");
60             _owner._readBorrowCount = _owner._readBorrowCount - 1;
61         }
62     }
63 
64     /// Get read-only slice in range `i` .. `j`.
65     auto opSlice(size_t i, size_t j) => typeof(this)(_range[i .. j], _owner);
66 
67     /// Get read-only slice.
68     auto opSlice() inout => this;            // same as copy
69 
70     bool empty() const @property @safe pure nothrow @nogc
71     {
72         import std.range.primitives : empty; // pick this if `_range` doesn't have it
73         return _range.empty;
74     }
75 
76     @property auto ref front() inout @safe pure in(!empty)
77     {
78         import std.range.primitives : front; // pick this if `_range` doesn't have it
79         return _range.front;
80     }
81 
82     typeof(this) save() => this;
83 
84     void popFront() @safe in(!empty)
85     {
86         import std.range.primitives : popFront; // pick this if `_range` doesn't have it
87         _range.popFront();
88     }
89 
90     Range _range;               /// constant range
91     alias _range this;          /// behave like range
92 
93 private:
94     Owner* _owner = null;       /// pointer to container owner
95 }