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.WirePointer;
23 
24 import java.nio.ByteBuffer;
25 
26 import capnproto.Constants;
27 
28 struct WirePointer
29 {
30 public: //Variables.
31 	static enum byte STRUCT = 0;
32 	static enum byte LIST = 1;
33 	static enum byte FAR = 2;
34 	static enum byte OTHER = 3;
35 
36 public: //Methods.
37 	static bool isNull(long wirePointer)
38 	{
39 		return wirePointer == 0;
40 	}
41 	
42 	static int offsetAndKind(ulong wirePointer)
43 	{
44 		return cast(int)(wirePointer & 0xffffffff);
45 	}
46 	
47 	static byte kind(long wirePointer)
48 	{
49 		return cast(byte)(offsetAndKind(wirePointer) & 3);
50 	}
51 	
52 	static int target(int offset, long wirePointer)
53 	{
54 		return offset + 1 + (offsetAndKind(wirePointer) >> 2);
55 	}
56 	
57 	static void setKindAndTarget(ref ByteBuffer buffer, int offset, byte kind, int targetOffset)
58 	{
59 		buffer.put!int(offset * 8, (((targetOffset - offset) - 1) << 2) | kind);
60 	}
61 	
62 	static void setKindWithZeroOffset(ref ByteBuffer buffer, int offset, byte kind)
63 	{
64 		buffer.put!int(offset * Constants.BYTES_PER_WORD, kind);
65 	}
66 	
67 	static void setKindAndTargetForEmptyStruct(ref ByteBuffer buffer, int offset)
68 	{
69 		//# This pointer points at an empty struct. Assuming the
70 		//# WirePointer itself is in-bounds, we can set the target to
71 		//# point either at the WirePointer itself or immediately after
72 		//# it. The latter would cause the WirePointer to be "null"
73 		//# (since for an empty struct the upper 32 bits are going to
74 		//# be zero). So we set an offset of -1, as if the struct were
75 		//# allocated immediately before this pointer, to distinguish
76 		//# it from null.
77 		
78 		buffer.put!int(offset * 8, 0xfffffffc);
79 	}
80 	
81 	static void setOffsetAndKind(ref ByteBuffer buffer, int offset, int offsetAndKind)
82 	{
83 		buffer.put!int(offset * 8, offsetAndKind);
84 	}
85 	
86 	static int inlineCompositeListElementCount(long wirePointer)
87 	{
88 		return offsetAndKind(wirePointer) >>> 2;
89 	}
90 	
91 	static void setKindAndInlineCompositeListElementCount(ref ByteBuffer buffer, int offset, byte kind, int elementCount)
92 	{
93 		int lval = (elementCount << 2) | kind;
94 		buffer.put!int(offset * 8, (elementCount << 2) | kind);
95 	}
96 	
97 	static int upper32Bits(long wirePointer)
98 	{
99 		return cast(int)(wirePointer >>> 32);
100 	}
101 }