1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 module capnproto.AnyPointer; 23 24 import std.string : startsWith; 25 import std.traits; 26 27 import capnproto.Data; 28 import capnproto.Constants; 29 import capnproto.SegmentBuilder; 30 import capnproto.SegmentReader; 31 import capnproto.Text; 32 import capnproto.WireHelpers; 33 import capnproto.WirePointer; 34 35 struct AnyPointer 36 { 37 public: //Types. 38 static struct Reader 39 { 40 public: //Methods. 41 this(const(SegmentReader)* segment, int pointer, int nestingLimit) 42 { 43 this.segment = segment; 44 this.pointer = pointer; 45 this.nestingLimit = nestingLimit; 46 } 47 48 bool isNull() 49 { 50 return WirePointer.isNull(this.segment.buffer.get!long(this.pointer * Constants.BYTES_PER_WORD)); 51 } 52 53 T.Reader getAs(T)() 54 { 55 alias name = fullyQualifiedName!T; 56 static if(name.startsWith("capnproto.DataList") || name.startsWith("capnproto.EnumList") || name.startsWith("capnproto.PrimitiveList") || name.startsWith("capnproto.ListList") || name.startsWith("capnproto.StructList") || name.startsWith("capnproto.TextList")) 57 return WireHelpers.readListPointer!(T.Reader)(cast(SegmentReader*)this.segment, this.pointer, null, 0, T.elementSize, this.nestingLimit); 58 else 59 return WireHelpers.readStructPointer!(T.Reader)(cast(SegmentReader*)this.segment, this.pointer, null, 0, this.nestingLimit); 60 //return factory.fromPointerReader(this.segment, this.pointer, this.nestingLimit); 61 } 62 63 private: //Variables. 64 const(SegmentReader)* segment; 65 int pointer; //Offset in words. 66 int nestingLimit; 67 } 68 69 static struct Builder 70 { 71 public: //Methods. 72 this(SegmentBuilder* segment, int pointer) 73 { 74 this.segment = segment; 75 this.pointer = pointer; 76 } 77 78 bool isNull() 79 { 80 return WirePointer.isNull(this.segment.buffer.get!long(this.pointer * Constants.BYTES_PER_WORD)); 81 } 82 83 T.Builder getAs(T)() 84 { 85 alias name = fullyQualifiedName!T; 86 87 static if(is(T : Data)) 88 return WireHelpers.getWritableDataPointer(this.pointer, this.segment, null, 0, 0); 89 else static if(is(T : Text)) 90 return WireHelpers.getWritableTextPointer(this.pointer, this.segment, null, 0, 0); 91 else static if(name.startsWith("capnproto.DataList") || name.startsWith("capnproto.EnumList") || name.startsWith("capnproto.PrimitiveList") || name.startsWith("capnproto.ListList") || name.startsWith("capnproto.TextList")) 92 return WireHelpers.getWritableListPointer!(T.Builder)(this.pointer, this.segment, T.elementSize, null, 0); 93 else static if(name.startsWith("capnproto.StructList")) 94 return WireHelpers.getWritableStructListPointer!(T.Builder)(this.pointer, this.segment, T.structSize, null, 0); 95 else 96 return WireHelpers.getWritableStructPointer!(T.Builder)(this.pointer, this.segment, T.structSize, null, 0); 97 //return fromPointerBuilder!(T.Builder)(this.segment, this.pointer); 98 } 99 100 T.Builder initAs(T)() 101 { 102 alias name = fullyQualifiedName!T; 103 static if(is(T : AnyPointer)) 104 { 105 auto result = T.Builder(this.segment, this.pointer); 106 result.clear(); 107 return result; 108 } 109 else 110 return WireHelpers.initStructPointer!(T.Builder)(this.pointer, this.segment, T.structSize); 111 //return T.initFromPointerBuilder(this.segment, this.pointer, 0); 112 } 113 114 T.Builder initAs(T)(int elementCount) 115 { 116 alias name = fullyQualifiedName!T; 117 118 static if(is(T : Data)) 119 return WireHelpers.initDataPointer(this.pointer, this.segment, elementCount); 120 else static if(is(T : Text)) 121 return WireHelpers.initTextPointer(this.pointer, this.segment, elementCount); 122 else static if(name.startsWith("capnproto.DataList") || name.startsWith("capnproto.EnumList") || name.startsWith("capnproto.PrimitiveList") || name.startsWith("capnproto.ListList") || name.startsWith("capnproto.TextList")) 123 return WireHelpers.initListPointer!(T.Builder)(this.pointer, this.segment, elementCount, T.elementSize); 124 else static if(name.startsWith("capnproto.StructList")) 125 return WireHelpers.initStructListPointer!(T.Builder)(this.pointer, this.segment, elementCount, T.structSize); 126 else 127 return WireHelpers.initStructPointer!(T.Builder)(this.pointer, this.segment, elementCount); 128 } 129 130 void setAs(T, U)(U reader) 131 { 132 alias name = fullyQualifiedName!U; 133 134 static if(is(T : Data)) 135 WireHelpers.setDataPointer(this.pointer, this.segment, reader); 136 else static if(is(T : Text)) 137 WireHelpers.setTextPointer(this.pointer, this.segment, reader); 138 else static if(name.startsWith("capnproto.DataList") || name.startsWith("capnproto.EnumList") || name.startsWith("capnproto.PrimitiveList") || name.startsWith("capnproto.ListList") || name.startsWith("capnproto.StructList") || name.startsWith("capnproto.TextList")) 139 WireHelpers.setListPointer(this.segment, this.pointer, reader.b); 140 else 141 WireHelpers.setStructPointer(this.segment, this.pointer, reader.b); 142 //factory.setPointerBuilder(this.segment, this.pointer, reader); 143 } 144 145 Reader asReader() 146 { 147 return Reader(segment.asReader(), pointer, 0x7fffffff); 148 } 149 150 void clear() 151 { 152 WireHelpers.zeroObject(this.segment, this.pointer); 153 this.segment.buffer.put!long(this.pointer * 8, 0L); 154 } 155 156 private: //Variables. 157 SegmentBuilder* segment; 158 int pointer; 159 } 160 }