1 module nxt.borrowed;
2 
3 /** Write-borrowed access to range `Range`. */
4 struct WriteBorrowed(Range, Owner)
5     // if (isInstanceOf!(Owned, Owner))
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() @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 (isInstanceOf!(Owned, Owner))
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() @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)
66     {
67         return typeof(this)(_range[i .. j], _owner);
68     }
69 
70     /// Get read-only slice.
71     auto opSlice() inout
72     {
73         return this;            // same as copy
74     }
75 
76     @property bool empty() const @safe pure nothrow @nogc
77     {
78         import std.range.primitives : empty; // pick this if `_range` doesn't have it
79         return _range.empty;
80     }
81 
82     @property auto ref front() inout @safe pure
83     {
84         assert(!empty);
85         import std.range.primitives : front; // pick this if `_range` doesn't have it
86         return _range.front;
87     }
88 
89     typeof(this) save()         // forward range
90     {
91         return this;
92     }
93 
94     void popFront() @safe
95     {
96         import std.range.primitives : popFront; // pick this if `_range` doesn't have it
97         _range.popFront();
98     }
99 
100     Range _range;               /// constant range
101     alias _range this;          /// behave like range
102 
103 private:
104     Owner* _owner = null;       /// pointer to container owner
105 }