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