1 module anansi.traits; 2 3 import std.range, std.traits, std.typecons; 4 import anansi.container : List, Array; 5 6 // ---------------------------------------------------------------------------- 7 // Graph concepts 8 // ---------------------------------------------------------------------------- 9 10 template isGraph (G) { 11 enum bool isGraph = is(typeof( 12 (inout int = 0) { 13 G g = G.init; // We can create a graph 14 G.VertexDescriptor v; // T defines a vertex descriptor type 15 G.EdgeDescriptor e; // T defines an eddge descriptor type 16 })); 17 } 18 19 template isIncidenceGraph (G) { 20 enum bool isIncidenceGraph = isGraph!G && is(typeof( 21 (inout int = 0) { 22 G g; 23 G.VertexDescriptor v; 24 size_t x = g.outDegree(v); // Can query vertex degree 25 foreach(e; g.outEdges(v)) { // Can enumerate vertex edges 26 G.EdgeDescriptor e2 = e; // Edge values are EdgeDescriptors 27 G.VertexDescriptor src = g.source(e); // Can query edge source 28 G.VertexDescriptor dst = g.target(e); // Can query edge target 29 } 30 })); 31 } 32 33 // ---------------------------------------------------------------------------- 34 // Property map 35 // ---------------------------------------------------------------------------- 36 37 template isReadablePropertyMap (T, IndexT, ValueT) { 38 enum bool isReadablePropertyMap = is(typeof( 39 (ref T t, IndexT idx) { 40 ValueT v = t[idx]; // can query 41 })); 42 } 43 44 template isPropertyMap (T, IndexT, ValueT) { 45 enum bool isPropertyMap = is(typeof( 46 (ref T t, IndexT idx) { 47 ValueT v = t[idx]; // can query 48 t[idx] = v; // can set 49 })); 50 } 51 52 // ---------------------------------------------------------------------------- 53 // Queue concept 54 // ---------------------------------------------------------------------------- 55 56 /** 57 * 58 */ 59 template isQueue(T, ValueT) { 60 enum bool isQueue = is(typeof( 61 (ref T t) { 62 bool e = t.empty; 63 ValueT v = t.front; 64 t.push(v); 65 t.pop(); 66 })); 67 } 68 69 // ---------------------------------------------------------------------------- 70 // Container specifiers 71 // ---------------------------------------------------------------------------- 72 73 final struct VecS { 74 alias IndexType = size_t; 75 enum IndexesAreStable = false; 76 77 static struct Store(ValueType) { 78 auto push(ValueType value) { 79 auto rval = _store.insertBack(value); 80 return PushResult!(typeof(rval))(rval, true); 81 } 82 83 void erase(IndexType index) { 84 _store.erase(index); 85 } 86 87 auto indexRange() const { 88 return iota(0, _store.length); 89 } 90 91 ref inout(ValueType) get_value(IndexType index) inout { 92 return _store[index]; 93 } 94 95 IndexType rewriteIndex(IndexType removedIndex, IndexType target) { 96 if (target > removedIndex) { 97 return target - 1; 98 } 99 else { 100 return target; 101 } 102 } 103 104 @property auto dup() { 105 return Store(_store.dup); 106 } 107 108 alias _store this; 109 Array!ValueType _store; 110 } 111 } 112 113 final struct ListS { 114 alias IndexType = void*; 115 enum IndexesAreStable = true; 116 117 static struct Store(ValueType) { 118 auto push(ValueType value) { 119 auto rval = _store.insertBack(value); 120 return PushResult!(typeof(rval))(rval, true); 121 } 122 123 void erase(IndexType index) { 124 auto node = cast(List!(ValueType).Node*) index; 125 _store.remove(node); 126 } 127 128 void eraseFrontOfRange(List!(ValueType).Range range) 129 in { 130 assert (!range.empty, "Range must not be empty."); 131 } 132 body { 133 _store.remove(range.frontNode); 134 } 135 136 auto indexRange() const { 137 static struct IndexRange { 138 alias Node = List!(ValueType).Node; 139 140 this(const(Node)* front, const(Node)* back) { 141 _front = front; 142 _back = back; 143 } 144 145 @property bool empty() const { return _front is null; } 146 @property void* front() const { return cast(void*) _front; } 147 void popFront() { 148 if (_front is _back) 149 _front = _back = null; 150 else 151 _front = _front.nextNode; 152 } 153 154 private: 155 const(Node)* _front; 156 const(Node)* _back; 157 } 158 159 static assert(isInputRange!IndexRange); 160 static assert(is(ElementType!IndexRange == void*)); 161 162 return IndexRange(_store.frontNode, _store.backNode); 163 } 164 165 ref inout(ValueType) get_value(IndexType index) inout { 166 auto node = cast(inout(List!(ValueType).Node)*) index; 167 return node.value; 168 } 169 170 @property auto dup() { 171 return Store(_store.dup); 172 } 173 174 alias _store this; 175 176 List!ValueType _store; 177 } 178 } 179 180 struct PushResult(IndexType) { 181 IndexType index; 182 bool addedNew; 183 } 184 185 // ---------------------------------------------------------------------------- 186 // 187 // ---------------------------------------------------------------------------- 188 189 final struct DirectedS {}; 190 final struct UndirectedS {}; 191 final struct BidirectionalS {}; 192 193 // ---------------------------------------------------------------------------- 194 // 195 // ---------------------------------------------------------------------------- 196 197 final static struct NoProperty {}; 198 199 template isNone(T) { 200 enum isNone = false; 201 } 202 203 template isNone(T: NoProperty) { 204 enum isNone = true; 205 } 206 207 template isNotNone(T) { 208 enum isNotNone = !(isNone!T); 209 }