1 /// Lazy substitute-based range (replace on state.) 2 module tern.algorithm.lazy_substitute; 3 4 5 import tern.traits; 6 import tern.object : loadLength; 7 import std.conv; 8 9 /// Lazy substitute-based range implementation. 10 public struct LazySubstitute(A, B, C) 11 if (isForward!A && isIndexable!A && isCallable!F) 12 { 13 A _range; 14 alias _range this; 15 16 public: 17 final: 18 size_t length; 19 B from; 20 C to; 21 22 string toString() 23 { 24 return this[0..length].to!string; 25 } 26 27 /// Gets the internally held range after predication. 28 T range() 29 { 30 if (length == 0) 31 return T.init; 32 33 return this[0..length]; 34 } 35 36 this(A _range, B from, C to) 37 { 38 _range = _range; 39 length = _range.loadLength; 40 this.from = from; 41 this.to = to; 42 } 43 44 A opSlice(ptrdiff_t start, ptrdiff_t end) 45 { 46 A slice; 47 foreach (ref u; _range) 48 { 49 slice ~= opIndex(start++); 50 51 if (start >= end) 52 break; 53 } 54 return slice; 55 } 56 57 auto opSliceAssign(T)(T ahs, ptrdiff_t start, ptrdiff_t end) 58 { 59 A slice; 60 foreach (ref u; _range) 61 { 62 slice ~= opIndex(ahs[start], start++); 63 64 if (start >= end) 65 break; 66 } 67 return slice; 68 } 69 70 ref auto opIndex(ptrdiff_t index) 71 { 72 if (_range[index] == from) 73 return _range[index] = to; 74 else 75 return _range[index]; 76 } 77 78 size_t opDollar() 79 { 80 return length; 81 } 82 }