1 /*
2  * Copyright 2013 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 module hunt.net.buffer.ReadOnlyByteBufferBuf;
17 
18 import hunt.net.buffer.AbstractByteBuf;
19 import hunt.net.buffer.AbstractReferenceCountedByteBuf;
20 import hunt.net.buffer.ByteBuf;
21 import hunt.net.buffer.ByteBufAllocator;
22 import hunt.net.buffer.ByteBufUtil;
23 
24 import hunt.Byte;
25 import hunt.io.ByteBuffer;
26 import hunt.Exceptions;
27 import hunt.net.Exceptions;
28 import hunt.stream.Common;
29 import hunt.util.StringBuilder;
30 import hunt.util.ByteOrder;
31 
32 import std.conv;
33 import std.format;
34 
35 
36 /**
37  * Read-only ByteBuf which wraps a read-only ByteBuffer.
38  */
39 class ReadOnlyByteBufferBuf : AbstractReferenceCountedByteBuf {
40 
41     protected ByteBuffer buffer;
42     private ByteBufAllocator allocator;
43     private ByteBuffer tmpNioBuf;
44 
45     this(ByteBufAllocator allocator, ByteBuffer buffer) {
46         super(buffer.remaining());
47         if (!buffer.isReadOnly()) {
48             throw new IllegalArgumentException("must be a readonly buffer: " ~ typeid(buffer).name);
49         }
50 
51         this.allocator = allocator;
52         this.buffer = buffer.slice().order(ByteOrder.BigEndian);
53         writerIndex(this.buffer.limit());
54     }
55 
56     override
57     protected void deallocate() { }
58 
59     override
60     bool isWritable() {
61         return false;
62     }
63 
64     override
65     bool isWritable(int numBytes) {
66         return false;
67     }
68 
69     override
70     ByteBuf ensureWritable(int minWritableBytes) {
71         throw new ReadOnlyBufferException();
72     }
73 
74     override
75     int ensureWritable(int minWritableBytes, bool force) {
76         return 1;
77     }
78 
79     override
80     byte getByte(int index) {
81         ensureAccessible();
82         return _getByte(index);
83     }
84 
85     override
86     protected byte _getByte(int index) {
87         return buffer.get(index);
88     }
89 
90     override
91     short getShort(int index) {
92         ensureAccessible();
93         return _getShort(index);
94     }
95 
96     override
97     protected short _getShort(int index) {
98         return buffer.getShort(index);
99     }
100 
101     override
102     short getShortLE(int index) {
103         ensureAccessible();
104         return _getShortLE(index);
105     }
106 
107     override
108     protected short _getShortLE(int index) {
109         return ByteBufUtil.swapShort(buffer.getShort(index));
110     }
111 
112     override
113     int getUnsignedMedium(int index) {
114         ensureAccessible();
115         return _getUnsignedMedium(index);
116     }
117 
118     override
119     protected int _getUnsignedMedium(int index) {
120         return (getByte(index) & 0xff)     << 16 |
121                (getByte(index + 1) & 0xff) << 8  |
122                getByte(index + 2) & 0xff;
123     }
124 
125     override
126     int getUnsignedMediumLE(int index) {
127         ensureAccessible();
128         return _getUnsignedMediumLE(index);
129     }
130 
131     override
132     protected int _getUnsignedMediumLE(int index) {
133         return getByte(index)      & 0xff       |
134                (getByte(index + 1) & 0xff) << 8 |
135                (getByte(index + 2) & 0xff) << 16;
136     }
137 
138     override
139     int getInt(int index) {
140         ensureAccessible();
141         return _getInt(index);
142     }
143 
144     override
145     protected int _getInt(int index) {
146         return buffer.getInt(index);
147     }
148 
149     override
150     int getIntLE(int index) {
151         ensureAccessible();
152         return _getIntLE(index);
153     }
154 
155     override
156     protected int _getIntLE(int index) {
157         return ByteBufUtil.swapInt(buffer.getInt(index));
158     }
159 
160     override
161     long getLong(int index) {
162         ensureAccessible();
163         return _getLong(index);
164     }
165 
166     override
167     protected long _getLong(int index) {
168         return buffer.getLong(index);
169     }
170 
171     override
172     long getLongLE(int index) {
173         ensureAccessible();
174         return _getLongLE(index);
175     }
176 
177     override
178     protected long _getLongLE(int index) {
179         return ByteBufUtil.swapLong(buffer.getLong(index));
180     }
181 
182     override
183     ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
184         checkDstIndex(index, length, dstIndex, dst.capacity());
185         if (dst.hasArray()) {
186             getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);
187         } else if (dst.nioBufferCount() > 0) {
188             foreach(ByteBuffer bb; dst.nioBuffers(dstIndex, length)) {
189                 int bbLen = bb.remaining();
190                 getBytes(index, bb);
191                 index += bbLen;
192             }
193         } else {
194             dst.setBytes(dstIndex, this, index, length);
195         }
196         return this;
197     }
198 
199     override
200     ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
201         checkDstIndex(index, length, dstIndex, cast(int)dst.length);
202 
203         ByteBuffer tmpBuf = internalNioBuffer();
204         tmpBuf.clear().position(index).limit(index + length);
205         tmpBuf.get(dst, dstIndex, length);
206         return this;
207     }
208 
209     override
210     ByteBuf getBytes(int index, ByteBuffer dst) {
211         checkIndex(index, dst.remaining());
212 
213         ByteBuffer tmpBuf = internalNioBuffer();
214         tmpBuf.clear().position(index).limit(index + dst.remaining());
215         dst.put(tmpBuf);
216         return this;
217     }
218 
219     override
220     ByteBuf setByte(int index, int value) {
221         throw new ReadOnlyBufferException();
222     }
223 
224     override
225     protected void _setByte(int index, int value) {
226         throw new ReadOnlyBufferException();
227     }
228 
229     override
230     ByteBuf setShort(int index, int value) {
231         throw new ReadOnlyBufferException();
232     }
233 
234     override
235     protected void _setShort(int index, int value) {
236         throw new ReadOnlyBufferException();
237     }
238 
239     override
240     ByteBuf setShortLE(int index, int value) {
241         throw new ReadOnlyBufferException();
242     }
243 
244     override
245     protected void _setShortLE(int index, int value) {
246         throw new ReadOnlyBufferException();
247     }
248 
249     override
250     ByteBuf setMedium(int index, int value) {
251         throw new ReadOnlyBufferException();
252     }
253 
254     override
255     protected void _setMedium(int index, int value) {
256         throw new ReadOnlyBufferException();
257     }
258 
259     override
260     ByteBuf setMediumLE(int index, int value) {
261         throw new ReadOnlyBufferException();
262     }
263 
264     override
265     protected void _setMediumLE(int index, int value) {
266         throw new ReadOnlyBufferException();
267     }
268 
269     override
270     ByteBuf setInt(int index, int value) {
271         throw new ReadOnlyBufferException();
272     }
273 
274     override
275     protected void _setInt(int index, int value) {
276         throw new ReadOnlyBufferException();
277     }
278 
279     override
280     ByteBuf setIntLE(int index, int value) {
281         throw new ReadOnlyBufferException();
282     }
283 
284     override
285     protected void _setIntLE(int index, int value) {
286         throw new ReadOnlyBufferException();
287     }
288 
289     override
290     ByteBuf setLong(int index, long value) {
291         throw new ReadOnlyBufferException();
292     }
293 
294     override
295     protected void _setLong(int index, long value) {
296         throw new ReadOnlyBufferException();
297     }
298 
299     override
300     ByteBuf setLongLE(int index, long value) {
301         throw new ReadOnlyBufferException();
302     }
303 
304     override
305     protected void _setLongLE(int index, long value) {
306         throw new ReadOnlyBufferException();
307     }
308 
309     override
310     int capacity() {
311         return maxCapacity();
312     }
313 
314     override
315     ByteBuf capacity(int newCapacity) {
316         throw new ReadOnlyBufferException();
317     }
318 
319     override
320     ByteBufAllocator alloc() {
321         return allocator;
322     }
323 
324     override
325     ByteOrder order() {
326         return ByteOrder.BigEndian;
327     }
328 
329     override
330     ByteBuf unwrap() {
331         return null;
332     }
333 
334     override
335     bool isReadOnly() {
336         return buffer.isReadOnly();
337     }
338 
339     override
340     bool isDirect() {
341         return buffer.isDirect();
342     }
343 
344     override
345     ByteBuf getBytes(int index, OutputStream output, int length) {
346         ensureAccessible();
347         if (length == 0) {
348             return this;
349         }
350 
351         if (buffer.hasArray()) {
352             output.write(buffer.array(), index + buffer.arrayOffset(), length);
353         } else {
354             byte[] tmp = ByteBufUtil.threadLocalTempArray(length);
355             ByteBuffer tmpBuf = internalNioBuffer();
356             tmpBuf.clear().position(index);
357             tmpBuf.get(tmp, 0, length);
358             output.write(tmp, 0, length);
359         }
360         return this;
361     }
362 
363     // override
364     // int getBytes(int index, GatheringByteChannel output, int length) {
365     //     ensureAccessible();
366     //     if (length == 0) {
367     //         return 0;
368     //     }
369 
370     //     ByteBuffer tmpBuf = internalNioBuffer();
371     //     tmpBuf.clear().position(index).limit(index + length);
372     //     return output.write(tmpBuf);
373     // }
374 
375     // override
376     // int getBytes(int index, FileChannel output, long position, int length) {
377     //     ensureAccessible();
378     //     if (length == 0) {
379     //         return 0;
380     //     }
381 
382     //     ByteBuffer tmpBuf = internalNioBuffer();
383     //     tmpBuf.clear().position(index).limit(index + length);
384     //     return output.write(tmpBuf, position);
385     // }
386 
387     override
388     ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
389         throw new ReadOnlyBufferException();
390     }
391 
392     override
393     ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
394         throw new ReadOnlyBufferException();
395     }
396 
397     override
398     ByteBuf setBytes(int index, ByteBuffer src) {
399         throw new ReadOnlyBufferException();
400     }
401 
402     override
403     int setBytes(int index, InputStream input, int length) {
404         throw new ReadOnlyBufferException();
405     }
406 
407     // override
408     // int setBytes(int index, ScatteringByteChannel input, int length) {
409     //     throw new ReadOnlyBufferException();
410     // }
411 
412     // override
413     // int setBytes(int index, FileChannel input, long position, int length) {
414     //     throw new ReadOnlyBufferException();
415     // }
416 
417     protected final ByteBuffer internalNioBuffer() {
418         ByteBuffer tmpNioBuf = this.tmpNioBuf;
419         if (tmpNioBuf is null) {
420             this.tmpNioBuf = tmpNioBuf = buffer.duplicate();
421         }
422         return tmpNioBuf;
423     }
424 
425     override
426     ByteBuf copy(int index, int length) {
427         ensureAccessible();
428         ByteBuffer src;
429         try {
430             src = cast(ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
431         } catch (IllegalArgumentException ignored) {
432             throw new IndexOutOfBoundsException("Too many bytes to read - Need " ~ to!string(index + length));
433         }
434 
435         ByteBuf dst = src.isDirect() ? alloc().directBuffer(length) : alloc().heapBuffer(length);
436         dst.writeBytes(src);
437         return dst;
438     }
439 
440     override
441     int nioBufferCount() {
442         return 1;
443     }
444 
445     override
446     ByteBuffer[] nioBuffers(int index, int length) {
447         return [nioBuffer(index, length)];
448     }
449 
450     override
451     ByteBuffer nioBuffer(int index, int length) {
452         checkIndex(index, length);
453         return cast(ByteBuffer) buffer.duplicate().position(index).limit(index + length);
454     }
455 
456     override
457     ByteBuffer internalNioBuffer(int index, int length) {
458         ensureAccessible();
459         return cast(ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length);
460     }
461 
462     override
463     bool hasArray() {
464         return buffer.hasArray();
465     }
466 
467     override
468     byte[] array() {
469         return buffer.array();
470     }
471 
472     override
473     int arrayOffset() {
474         return buffer.arrayOffset();
475     }
476 
477     override
478     bool hasMemoryAddress() {
479         return false;
480     }
481 
482     override
483     long memoryAddress() {
484         throw new UnsupportedOperationException();
485     }
486 }