import java.nio { JavaByteBuffer=ByteBuffer { allocateJavaByteBuffer=allocate } } "Represents a buffer of [[Byte]]s (from 0 to 255 inclusive, unsigned)." by ("Stéphane Épardaud", "Alex Szczuczko") shared native class ByteBuffer extends Buffer<Byte> { "Allocates a new [[ByteBuffer]] filled with the given [[initialData]]. The capacity of the new buffer will be the number of bytes given. The returned buffer will be ready to be `read`, with its `position` set to `0` and its limit set to the buffer `capacity`." shared native new ({Byte*} initialData) extends Buffer<Byte>() {} "Creates a [[ByteBuffer]] initally backed by the given [[initialArray]]. The capacity of the new buffer will be the size of the array. The returned buffer will be ready to be `read`, with its `position` set to `0` and its limit set to the buffer `capacity`." shared native new ofArray(Array<Byte> initialArray) extends Buffer<Byte>() {} "Allocates a new zeroed [[ByteBuffer]] of the given [[initialCapacity]]." shared native new ofSize(Integer initialCapacity) extends Buffer<Byte>() {} shared actual native Integer capacity; shared actual native void clear(); shared actual native void flip(); shared actual native Byte get(); shared actual native Object? implementation; shared actual native variable Integer limit; shared actual native variable Integer position; shared actual native void put(Byte element); shared actual native void resize(Integer newSize, Boolean growLimit); shared actual native Array<Byte> array; } shared native ("js") class ByteBuffer extends Buffer<Byte> { variable Array<Byte> buf; shared native ("js") new ({Byte*} initialData) extends Buffer<Byte>() { buf = Array(initialData); } shared native ("js") new ofArray(Array<Byte> initialArray) extends Buffer<Byte>() { buf = initialArray; } shared native ("js") new ofSize(Integer initialCapacity) extends Buffer<Byte>() { buf = Array.ofSize(initialCapacity, 0.byte); } shared actual native ("js") Integer capacity => buf.size; variable Integer _position = 0; shared actual native ("js") Integer position => _position; // Have to define assign for position after limit due to circular dependency variable Integer _limit = buf.size; shared actual native ("js") Integer limit => _limit; native ("js") assign limit { "Limit must be non-negative" assert (limit >= 0); "Limit must be no larger than capacity" assert (limit <= capacity); // Position must be be no larger than the limit if (position > limit) { position = limit; } _limit = limit; } native ("js") assign position { "Position must be non-negative" assert (position >= 0); "Position must be no larger than limit" assert (position <= limit); _position = position; } shared actual native ("js") Byte get() { value byte = buf[position]; if (exists byte) { position++; return byte; } else { throw BufferUnderflowException("No byte at position ``position``"); } } shared actual native ("js") void put(Byte element) { if (position > limit) { throw BufferOverflowException("No space at position ``position``"); } buf[position] = element; position++; } shared actual native ("js") void clear() { position = 0; limit = capacity; } shared actual native ("js") void flip() { limit = position; position = 0; } shared actual native ("js") void resize(Integer newSize, Boolean growLimit) { resizeBuffer { newSize = newSize; growLimit = growLimit; current = this; intoNew = () { // copy value dest = Array.ofSize(newSize, 0.byte); buf.copyTo(dest, 0, 0, this.available); // change buffer buf = dest; }; }; } shared actual native ("js") Array<Byte> array => buf; shared actual native ("js") Object? implementation => buf; } shared native ("jvm") class ByteBuffer extends Buffer<Byte> { variable JavaByteBuffer buf; shared native ("jvm") new ({Byte*} initialData) extends Buffer<Byte>() { buf = allocateJavaByteBuffer(initialData.size); initialData.each(void(byte) => buf.put(byte)); buf.clear(); } shared native ("jvm") new ofArray(Array<Byte> initialArray) extends Buffer<Byte>() { buf = allocateJavaByteBuffer(initialArray.size); initialArray.each(void(byte) => buf.put(byte)); buf.clear(); } shared native ("jvm") new ofSize(Integer initialCapacity) extends Buffer<Byte>() { buf = allocateJavaByteBuffer(initialCapacity); } shared actual native ("jvm") Integer capacity => buf.capacity(); shared actual native ("jvm") Integer limit => buf.limit(); native ("jvm") assign limit { "Limit must be non-negative" assert (limit >= 0); "Limit must be no larger than capacity" assert (limit <= capacity); buf.limit(limit); } shared actual native ("jvm") Integer position => buf.position(); native ("jvm") assign position { "Position must be non-negative" assert (position >= 0); "Position must be no larger than limit" assert (position <= limit); buf.position(position); } shared actual native ("jvm") Byte get() { if (position > limit) { throw BufferUnderflowException("No byte at position ``position``"); } return buf.get(); } shared actual native ("jvm") void put(Byte element) { if (position > limit) { throw BufferOverflowException("No space at position ``position``"); } buf.put(element); } shared actual native ("jvm") void clear() => buf.clear(); shared actual native ("jvm") void flip() => buf.flip(); shared actual native ("jvm") void resize(Integer newSize, Boolean growLimit) { resizeBuffer { newSize = newSize; growLimit = growLimit; current = this; intoNew = () { // copy value dest = allocateJavaByteBuffer(newSize); dest.put(buf); // change buffer buf = dest; }; }; } shared actual native ("jvm") Array<Byte> array => buf.array().byteArray; shared actual native ("jvm") Object? implementation => buf; }