1 /*
2  * hunt-proton: AMQP Protocol library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.proton.amqp.Binary;
13 
14 import hunt.io.ByteBuffer;
15 import hunt.collection.Collection;
16 import hunt.proton.codec.ReadableBuffer;
17 import hunt.io.BufferUtils;
18 
19 class Binary
20 {
21     private  byte[] _data;
22     private  int _offset;
23     private  int _length;
24     private  int _hashCode;
25 
26     this( byte[] data)
27     {
28         this(data, 0, cast(int)(data.length));
29     }
30 
31     this( byte[] data, int offset,int length)
32     {
33         _data = data;
34         _offset = offset;
35         _length = length;
36     }
37 
38     public ByteBuffer asByteBuffer()
39     {
40         return BufferUtils.toBuffer(_data,_offset,_length);
41     }
42 
43     //override
44     //public int hashCode()
45     //{
46     //    int hc = _hashCode;
47     //    if(hc == 0)
48     //    {
49     //        for (int i = 0; i < _length; i++)
50     //        {
51     //            hc = 31*hc + (0xFF & _data[_offset + i]);
52     //        }
53     //        _hashCode = hc;
54     //    }
55     //    return hc;
56     //}
57 
58     override
59     public  size_t toHash() @trusted nothrow
60     {
61             int hc = _hashCode;
62             if(hc == 0)
63             {
64                 for (int i = 0; i < _length; i++)
65                 {
66                     hc = 31*hc + (0xFF & _data[_offset + i]);
67                 }
68                 _hashCode = hc;
69             }
70             return cast(size_t)hc;
71     }
72 
73    override bool opEquals(Object o)
74     {
75         if (this is o)
76         {
77             return true;
78         }
79 
80         if (o is null || cast(Binary)o is null)
81         {
82             return false;
83         }
84 
85         Binary buf = cast(Binary) o;
86         int size = _length;
87         if (size != buf.getLength())
88         {
89             return false;
90         }
91 
92         byte[] myData = _data;
93         byte[] theirData = buf.getArray();
94         int myOffset = _offset;
95         int theirOffset = buf.getArrayOffset();
96         int myLimit = myOffset + size;
97 
98         while(myOffset < myLimit)
99         {
100             if (myData[myOffset++] != theirData[theirOffset++])
101             {
102                 return false;
103             }
104         }
105 
106         return true;
107     }
108 
109     public int getArrayOffset()
110     {
111         return _offset;
112     }
113 
114     public byte[] getArray()
115     {
116         return _data;
117     }
118 
119     public int getLength()
120     {
121         return _length;
122     }
123 
124 
125     public static Binary combine(Collection!Binary binaries)
126     {
127         if(binaries.size() == 1)
128         {
129             return binaries.iterator().front();
130         }
131 
132         byte[] data ;
133         foreach(Binary binary ; binaries)
134         {
135             data ~= binary.getArray()[binary.getArrayOffset() .. $];
136         }
137         return new Binary(data);
138     }
139 
140     public Binary subBinary(int offset,int length)
141     {
142         return new Binary(_data, _offset+offset, length);
143     }
144 
145     public static Binary create(ReadableBuffer buffer)
146     {
147         if (buffer is null)
148         {
149             return null;
150         }
151         else if (!buffer.hasArray())
152         {
153             byte[] data = new byte [buffer.remaining()];
154             ReadableBuffer dup = buffer.duplicate();
155             dup.get(data);
156             return new Binary(data);
157         }
158         else
159         {
160             return new Binary(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
161         }
162     }
163 
164     public static Binary create(ByteBuffer buffer)
165     {
166         if (buffer is null)
167         {
168             return null;
169         }
170         if (buffer.isDirect() || buffer.isReadOnly())
171         {
172             byte[] data = new byte [buffer.remaining()];
173             ByteBuffer dup = buffer.duplicate();
174             dup.get(data);
175             return new Binary(data);
176         }
177         else
178         {
179             return new Binary(buffer.array(), buffer.arrayOffset()+buffer.position(), buffer.remaining());
180         }
181     }
182 
183     public static Binary copy(Binary source)
184     {
185         if (source is null)
186         {
187             return null;
188         }
189         else
190         {
191             byte[] data ;
192           //  System.arraycopy(source.getArray(), source.getArrayOffset(), data, 0, source.getLength());
193             data ~= source.getArray()[source.getArrayOffset() .. $];
194             return new Binary(data);
195         }
196     }
197 }