Type Proposal Example
| /** | |
| * A binary bit-based writer and reader designed for packets. | |
| * @class | |
| */ | |
| export class Packet | |
| { | |
| /** | |
| * The byte buffer for the packet. | |
| * @private | |
| */ | |
| buffer:uint32[]; | |
| /** | |
| * The current bit index of the writer and reader. | |
| * @private | |
| */ | |
| bitIndex:uint32; | |
| /** | |
| * The maximum bit index of the writer and reader. | |
| * @private | |
| */ | |
| maximumBitIndex:uint32; | |
| /** | |
| * Error handler. | |
| * @private | |
| */ | |
| error:(message:string); | |
| /** | |
| * Constructor for writing. | |
| * @constructs | |
| */ | |
| constructor() | |
| { | |
| this.bitIndex = 0; | |
| this.maximumBitIndex = 0; | |
| // 1500 bytes - Websocket Header - TCP Header = Default Packet Size | |
| this.buffer = new uint32[1400]; | |
| } | |
| /** | |
| * Constructor for reading. | |
| * @constructs | |
| * @param buffer The buffer to read from. | |
| * @param error Error callback. | |
| */ | |
| constructor(buffer:uint8[], error:(message:string)) | |
| { | |
| packet.buffer = uint32[](buffer.buffer); | |
| packet.error = (message) => | |
| { | |
| error(message); | |
| this.error = null; | |
| }; | |
| packet.ReadHeader(); | |
| } | |
| /** | |
| * Buffer | |
| */ | |
| get Buffer() | |
| { | |
| return UInt8[](this.buffer.buffer, 0, (this.bitIndex + 7) / 8); | |
| } | |
| /** | |
| * BitIndex | |
| */ | |
| get BitIndex() | |
| { | |
| return this.bitIndex; | |
| } | |
| set BitIndex(value) | |
| { | |
| this.bitIndex = value; | |
| } | |
| /** | |
| * MaximumBitIndex | |
| */ | |
| get MaximumBitIndex() | |
| { | |
| return this.maximumBitIndex; | |
| } | |
| set MaximumBitIndex(value) | |
| { | |
| this.maximumBitIndex = value; | |
| } | |
| /** | |
| * headerSize | |
| */ | |
| get headerSize() | |
| { | |
| return 16; | |
| } | |
| /** | |
| * Error | |
| */ | |
| get Error() | |
| { | |
| return this.error == null; | |
| } | |
| /** | |
| * Computes the log2 of a value. | |
| * @param value The value to compute the log2 of. | |
| */ | |
| Log2(value:uint32) | |
| { | |
| if (value == 0) | |
| { | |
| return 0; | |
| } | |
| else | |
| { | |
| var left:uint32 = 0; | |
| var right:uint32 = 32; | |
| for (var i = 0; i < 5; ++i) | |
| { | |
| if (value >> (32 - (left + right) / 2) != 0) | |
| { | |
| // Left | |
| right = (left + right) / 2; | |
| } | |
| else | |
| { | |
| // Right | |
| left = (left + right) / 2; | |
| } | |
| } | |
| return 32 - left; | |
| } | |
| } | |
| /** | |
| * Moves the bit index after the header. | |
| */ | |
| ResetBitIndex() | |
| { | |
| this.bitIndex = this.headerSize; | |
| } | |
| /** | |
| * Returns a string of 0s and 1s representing the bits in the this.buffer. | |
| */ | |
| Trace() | |
| { | |
| var s = ''; | |
| for (var copyBits = 0; copyBits < Math.max(this.bitIndex, this.maximumBitIndex); ++copyBits) | |
| { | |
| s += (this.buffer[copyBits / 32] << copyBits % 32 >> 31) == 0 ? '0' : '1'; | |
| } | |
| return s; | |
| } | |
| /** | |
| * Reads the length of the packet stored in the header. | |
| */ | |
| ReadHeader() | |
| { | |
| this.maximumBitIndex = this.buffer[0] >> 32 - this.headerSize; | |
| this.bitIndex += this.headerSize; | |
| } | |
| /** | |
| * Writes a 16 bit header. | |
| */ | |
| Begin() | |
| { | |
| this.bitIndex += this.headerSize; | |
| } | |
| /** | |
| * Writes maxBitIndex to the packet header created with Begin. | |
| */ | |
| End() | |
| { | |
| this.maximumBitIndex = this.bitIndex; | |
| this.buffer[0] |= this.maximumBitIndex << 32 - this.headerSize; | |
| } | |
| /** | |
| * Writes an event to the packet. | |
| * @param value The event value. | |
| */ | |
| WriteEvent(value:uint8) | |
| { | |
| this.WriteUInt8(value); | |
| } | |
| /** | |
| * Writes a boolean to the packet. | |
| * @param value The boolean value. | |
| */ | |
| WriteBoolean(value:boolean) | |
| { | |
| if (value) | |
| { | |
| this.buffer[this.bitIndex / 32] |= 1 << 31 - this.bitIndex % 32; | |
| } | |
| this.bitIndex++; | |
| } | |
| /** | |
| * Writes an 8-bit unsigned integer to the packet. | |
| * @param value The 8 bit unsigned integer value. | |
| */ | |
| WriteUInt8(value:uint8) | |
| { | |
| var offset = this.bitIndex % 32; | |
| this.buffer[this.bitIndex / 32] |= value << 24 >> offset; | |
| if (offset > 24) | |
| { | |
| this.buffer[this.bitIndex / 32 + 1] |= value << 56 - offset; | |
| } | |
| this.bitIndex += 8; | |
| } | |
| /** | |
| * Writes an 8-bit signed integer to the packet. | |
| * @param value The 8 bit signed integer value. | |
| */ | |
| WriteInt8(value:int8) | |
| { | |
| this.WriteUInt8(uint8(int8[]([value]).buffer)[0]); | |
| } | |
| /** | |
| * Writes an 16-bit unsigned integer to the packet. | |
| * @param value The 16 bit unsigned integer value. | |
| */ | |
| WriteUInt16(value:uint16) | |
| { | |
| var offset = this.bitIndex % 32; | |
| this.buffer[this.bitIndex / 32] |= value << 16 >> offset; | |
| if (offset > 16) | |
| { | |
| this.buffer[this.bitIndex / 32 + 1] |= value << 48 - offset; | |
| } | |
| this.bitIndex += 16; | |
| } | |
| /** | |
| * Writes an 16-bit signed integer to the packet. | |
| * @param value The 16 bit signed integer value. | |
| */ | |
| WriteInt16(value:int16) | |
| { | |
| this.WriteUInt16(uint16(int16[]([value]).buffer)[0]); | |
| } | |
| /** | |
| * Writes an 32-bit unsigned integer to the packet. | |
| * @param value The 32 bit unsigned integer value. | |
| */ | |
| WriteUInt32(value:uint32) | |
| { | |
| var offset = this.bitIndex % 32; | |
| this.buffer[this.bitIndex / 32] |= value >> offset; | |
| if (offset > 0) | |
| { | |
| this.buffer[this.bitIndex / 32 + 1] |= value << 32 - offset; | |
| } | |
| this.bitIndex += 32; | |
| } | |
| /** | |
| * Writes an 32-bit signed integer to the packet. | |
| * @param value The 32 bit signed integer value. | |
| */ | |
| WriteInt32(value:int32) | |
| { | |
| this.WriteUInt32(uint32(int32[]([value]).buffer)[0]); | |
| } | |
| /** | |
| * Writes an n-bit unsigned integer to the packet. | |
| * @param value The unsigned integer value. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteUIntN(value:uint32, bits:uint32) | |
| { | |
| var offset = this.bitIndex % 32; | |
| this.buffer[this.bitIndex / 32] |= value << 32 - bits >> offset; | |
| if (offset > 32 - bits) | |
| { | |
| this.buffer[this.bitIndex / 32 + 1] |= value << 64 - bits - offset; | |
| } | |
| this.bitIndex += bits; | |
| } | |
| /** | |
| * Writes an n-bit unsigned integer to the packet. | |
| * @param value The signed integer value. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteIntN(value:uint32, bits:uint32) | |
| { | |
| this.WriteUIntN(uint32(int32[]([value]).buffer)[0], bits); | |
| } | |
| /** | |
| * Writes an unsigned integer to the packet. | |
| * @param value The unsigned integer value. | |
| * @param maximum The inclusive maximum for the range starting at 0. | |
| */ | |
| WriteUInt(value:uint32, maximum:uint32) | |
| { | |
| var bits = this.Log2(maximum); | |
| value -= minimum; | |
| this.WriteUIntN(value, bits); | |
| } | |
| /** | |
| * Writes an unsigned integer to the packet. | |
| * @param value The unsigned integer value. | |
| * @param minimum The inclusive minimum for the range. | |
| * @param maximum The inclusive maximum for the range. | |
| */ | |
| WriteUInt(value:uint32, minimum:uint32, maximum:uint32) | |
| { | |
| var bits = this.Log2(maximum - minimum); | |
| value -= minimum; | |
| this.WriteUIntN(value, bits); | |
| } | |
| /** | |
| * Writes an signed integer to the packet. | |
| * @param value The signed integer value. | |
| * @param maximum The inclusive maximum for the range starting at 0. | |
| */ | |
| WriteInt(value:int32, maximum:int32) | |
| { | |
| var bits = this.Log2(maximum); | |
| value -= minimum; | |
| this.WriteUIntN(value, bits); | |
| } | |
| /** | |
| * Writes an signed integer to the packet. | |
| * @param value The signed integer value. | |
| * @param minimum The inclusive minimum for the range. | |
| * @param maximum The inclusive maximum for the range. | |
| */ | |
| WriteInt(value:int32, minimum:int32, maximum:int32) | |
| { | |
| var bits = this.Log2(maximum - minimum); | |
| value -= minimum; | |
| this.WriteUIntN(uint32(int32[]([value]).buffer)[0], bits); | |
| } | |
| /** | |
| * Writes an unsigned integer to the packet using a variable width encoding. | |
| * @param value The unsigned integer value. | |
| * @param bits The number of bits to use for the sequence. Choose a bits value that represents the number of bits to hold the average value. | |
| */ | |
| WriteVariableWidthUInt(value:uint32, bits:uint32) | |
| { | |
| var shift = bits; | |
| // Stop when our value can fit inside | |
| for (; shift < 32 && value >= (0x1 << shift); shift += bits) | |
| { | |
| this.WriteBoolean(true); // Write a 1 for a continuation bit signifying one more interval is needed | |
| } | |
| if (shift < 32) | |
| { | |
| this.WriteBoolean(false); // Write a 0 for a continuation bit signifying the end | |
| } | |
| this.WriteUIntN(value, shift > 32 ? 32 : shift); | |
| } | |
| /** | |
| * Writes an signed integer to the packet using a variable width encoding. | |
| * @param {uint32} value The signed integer value. | |
| * @param {uint32} bits The number of bits to use for the sequence. Choose a bits value that represents the number of bits to hold the average value. | |
| */ | |
| WriteVariableWidthInt(value:uint32, bits:uint32) | |
| { | |
| var shift = bits; | |
| // Stop when our value can fit inside | |
| for (; shift < 32 && (value < -(0x1 << (shift - 1)) || value >= 0x1 << (shift - 1)); shift += bits) | |
| { | |
| this.WriteBoolean(true); // Write a 1 for a continuation bit signifying one more interval is needed | |
| } | |
| if (shift < 32) | |
| { | |
| this.WriteBoolean(false); // Write a 0 for a continuation bit signifying the end | |
| } | |
| this.WriteIntN(value, shift > 32 ? 32 : shift); | |
| } | |
| /** | |
| * Writes a 32 bit float to the packet. | |
| * @param value The floating point value. | |
| */ | |
| WriteFloat32(value:float32) | |
| { | |
| this.WriteUInt32(uint32(float32[]([value]).buffer)[0]); | |
| } | |
| /** | |
| * Writes a 32 bit float to the packet. | |
| * @param value The floating point value. | |
| * @param maximum The inclusive maximum for the range starting at 0. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteFloat32(value:float32, maximum:float32, bits:uint32) | |
| { | |
| this.WriteUIntN(Math.round(value / maximum * ((0x1 << bits) - 1)), bits); | |
| } | |
| /** | |
| * Writes a 32 bit float to the packet. | |
| * @param value The floating point value. | |
| * @param minimum The inclusive minimum for the range. | |
| * @param maximum The inclusive maximum for the range. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteFloat32(value:float32, minimum:float32, maximum:float32, bits:uint32) | |
| { | |
| if (minimum < 0 && maximum > 0) | |
| { | |
| this.WriteUIntN(value == 0 ? 0 : Math.round((value - minimum) / (maximum - minimum) * ((0x1 << bits) - 2)) + 1, bits); | |
| } | |
| else | |
| { | |
| this.WriteUIntN(Math.round((value - minimum) / (maximum - minimum) * ((0x1 << bits) - 1)), bits); | |
| } | |
| } | |
| /** | |
| * Writes a 64 bit float to the packet. | |
| * @param value The floating point value. | |
| */ | |
| WriteFloat64(value:float32) | |
| { | |
| var float64UInt32 = uint32(float64[]([value]).buffer); | |
| this.WriteUInt32(float64UInt32[0]); | |
| this.WriteUInt32(float64UInt32[1]); | |
| } | |
| /** | |
| * Writes a 64 bit float to the packet. | |
| * @param value The floating point value. | |
| * @param maximum The inclusive maximum for the range starting at 0. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteFloat64(value:float32, maximum:float32, bits:uint32) | |
| { | |
| this.WriteUIntN(Math.round(value / maximum * ((0x1 << bits) - 1)), bits); | |
| } | |
| /** | |
| * Writes a 64 bit float to the packet. | |
| * @param value The floating point value. | |
| * @param minimum The inclusive minimum for the range. | |
| * @param maximum The inclusive maximum for the range. | |
| * @param bits The number of bits to use. | |
| */ | |
| WriteFloat64(value:float32, minimum:float32, maximum:float32, bits:uint32) | |
| { | |
| if (minimum < 0 && maximum > 0) | |
| { | |
| this.WriteUIntN(value == 0 ? 0 : Math.round((value - minimum) / (maximum - minimum) * ((0x1 << bits) - 2)) + 1, bits); | |
| } | |
| else | |
| { | |
| this.WriteUIntN(Math.round((value - minimum) / (maximum - minimum) * ((0x1 << bits) - 1)), bits); | |
| } | |
| } | |
| /** | |
| * Writes a string to the packet. | |
| * @param value The string value. | |
| */ | |
| WriteString(value:string) | |
| { | |
| this.WriteUInt16(value.length); | |
| for (var index = 0; index < value.length; ++index) | |
| { | |
| this.WriteUIntN(value.charCodeAt(index), 7); | |
| } | |
| } | |
| /** | |
| * Writes a packet to the packet. | |
| * @param value The packet. | |
| */ | |
| WritePacket(value:Packet) | |
| { | |
| value.BitIndex = 0; | |
| for (var copyBits = 0; copyBits < value.MaximumBitIndex; copyBits += 32) | |
| { | |
| var bits = value.MaximumBitIndex - copyBits > 32 ? 32 : value.MaximumBitIndex - copyBits; | |
| // Read n-bits from value. | |
| var valueUIntN:uint32 = 0; | |
| var offset = value.bitIndex % 32; | |
| valueUIntN |= value.buffer[value.bitIndex / 32] << offset >> 32 - bits; | |
| if (offset > 32 - bits) | |
| { | |
| valueUIntN |= value.buffer[value.bitIndex / 32 + 1] >> 64 - bits - offset; | |
| } | |
| value.bitIndex += bits; | |
| // Write n-bits to the buffer. | |
| offset = this.bitIndex % 32; | |
| this.buffer[this.bitIndex / 32] |= valueUIntN << 32 - bits >> offset; | |
| if (offset > 32 - bits) | |
| { | |
| this.buffer[this.bitIndex / 32 + 1] |= valueUIntN << 64 - bits - offset; | |
| } | |
| this.bitIndex += bits; | |
| } | |
| } | |
| /** | |
| * Reads an event from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadEvent(callback:(uint8, Packet):void) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 8 > this.maximumBitIndex) | |
| { | |
| this.error('Event expected'); | |
| } | |
| this.ReadUInt8(callback); | |
| } | |
| /** | |
| * Reads a 1-bit boolean from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadBoolean(callback:(boolean, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var value = false; | |
| if (this.bitIndex + 1 > this.maximumBitIndex) | |
| { | |
| this.error('Boolean expected'); | |
| } | |
| else | |
| { | |
| value = (this.buffer[this.bitIndex / 32] << this.bitIndex % 32 >> 31) == 1; | |
| this.bitIndex++; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads an 8-bit unsigned integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUInt8(callback:(uint8, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 8 > this.maximumBitIndex) | |
| { | |
| this.error('uint8 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 24; | |
| if (offset > 24) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 56 - offset; | |
| } | |
| this.bitIndex += 8; | |
| callback(value); | |
| } | |
| } | |
| /** | |
| * Reads an 8-bit signed integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadInt8(callback:(int8, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 8 > this.maximumBitIndex) | |
| { | |
| this.error('int8 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 24; | |
| if (offset > 24) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 56 - offset; | |
| } | |
| this.bitIndex += 8; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads a 16-bit unsigned integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUInt16(callback:(uint16, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 16 > this.maximumBitIndex) | |
| { | |
| this.error('uint16 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 16; | |
| if (offset > 16) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 48 - offset; | |
| } | |
| this.bitIndex += 16; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads a 16-bit signed integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadInt16(callback:(int16, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 16 > this.maximumBitIndex) | |
| { | |
| this.error('int16 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 16; | |
| if (offset > 16) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 48 - offset; | |
| } | |
| this.bitIndex += 16; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads a 32-bit unsigned integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUInt32(callback:(uint32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 32 > this.maximumBitIndex) | |
| { | |
| this.error('uint32 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset; | |
| if (offset > 0) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 32 - offset; | |
| } | |
| this.bitIndex += 32; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads a 32-bit signed integer from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadInt32(callback:(int32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 32 > this.maximumBitIndex) | |
| { | |
| this.error('int32 expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset; | |
| if (offset > 0) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 32 - offset; | |
| } | |
| this.bitIndex += 32; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads an n-bit unsigned integer from the packet. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUIntN(bits:uint32, callback:(uint32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('uint' + bits + ' expected'); | |
| } | |
| else | |
| { | |
| var value = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 32 - bits; | |
| if (offset > 32 - bits) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 64 - bits - offset; | |
| } | |
| this.bitIndex += bits; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads an n-bit signed integer from the packet. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadIntN(bits:uint32, callback:(int32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('int' + bits + ' expected'); | |
| } | |
| else | |
| { | |
| var value:uint32 = 0; | |
| var offset = this.bitIndex % 32; | |
| value |= this.buffer[this.bitIndex / 32] << offset >> 32 - bits; | |
| if (offset > 32 - bits) | |
| { | |
| value |= this.buffer[this.bitIndex / 32 + 1] >> 64 - bits - offset; | |
| } | |
| this.bitIndex += bits; | |
| callback(value, this); | |
| } | |
| } | |
| /** | |
| * Reads an unsigned integer from the packet. | |
| * @param maximum The inclusive maximum used for the range starting at 0. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUInt(maximum:uint32, callback:(uint32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bits = this.Log2(maximum); | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('uint' + bits + ' with range [' + minimum + ', ' + maximum + '] expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value + minimum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads an unsigned integer from the packet. | |
| * @param minimum The inclusive minimum used for the range. | |
| * @param maximum The inclusive maximum used for the range. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadUInt(minimum:uint32, maximum:uint32, callback:(uint32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bits = this.Log2(maximum - minimum); | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('uint' + bits + ' with range [' + minimum + ', ' + maximum + '] expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value + minimum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a signed integer from the packet. | |
| * @param maximum The inclusive maximum used for the range starting at 0. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadInt(maximum:int32, callback:(int32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bits = this.Log2(maximum); | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('int' + bits + ' with range [' + minimum + ', ' + maximum + '] expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value + minimum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a signed integer from the packet. | |
| * @param minimum The inclusive minimum used for the range. | |
| * @param maximum The inclusive maximum used for the range. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadInt(minimum:int32, maximum:int32, callback:(int32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bits = this.Log2(maximum - minimum); | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('int' + bits + ' with range [' + minimum + ', ' + maximum + '] expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value + minimum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads an unsigned integer from the packet that was written using an n-bit variable width encoding. | |
| * @param bits The number of bits used for the sequence. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadVariableWidthUInt(bits:uint32, callback:(uint32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bitCount = 0; | |
| var continuationBitValue; | |
| do | |
| { | |
| continuationBitValue = false; | |
| this.ReadBoolean((continuationBit) => | |
| { | |
| continuationBitValue = continuationBit; | |
| bitCount += bits; | |
| }); | |
| } | |
| while (continuationBitValue && bitCount < 32); | |
| if (bitCount > 32) | |
| { | |
| this.error('uint expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bitCount, callback); | |
| } | |
| } | |
| /** | |
| * Read a signed integer from the packet that was written using an n-bit variable width encoding. | |
| * @param bits The number of bits used for the sequence. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadVariableWidthInt(bits, callback:(int32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| var bitCount = 0; | |
| var continuationBitValue; | |
| do | |
| { | |
| continuationBitValue = false; | |
| this.ReadBoolean((continuationBit) => | |
| { | |
| continuationBitValue = continuationBit; | |
| bitCount += bits; | |
| }); | |
| } | |
| while (continuationBitValue && bitCount < 32); | |
| if (bitCount > 32) | |
| { | |
| this.error('int expected'); | |
| } | |
| else | |
| { | |
| this.ReadIntN(bitCount, callback); | |
| } | |
| } | |
| /** | |
| * Reads a 32-bit floating point from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat32(callback:(float32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 32 > this.maximumBitIndex) | |
| { | |
| this.error('float32 expected'); | |
| } | |
| else | |
| { | |
| var arrayBuffer = new ArrayBuffer(4); | |
| var float32 = new Float32Array(arrayBuffer); | |
| var float32UInt32 = new Uint32Array(arrayBuffer); | |
| this.ReadUInt32((value) => | |
| { | |
| float32UInt32[0] = value; | |
| }); | |
| callback(float32[0], this); | |
| } | |
| } | |
| /** | |
| * Reads a 32-bit floating point from the packet. | |
| * @param maximum The inclusive maximum used for the range starting at 0. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat32(maximum:float32, bits:uint32, callback:(float32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('float32 expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value / ((0x1 << bits) - 1) * maximum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a 32-bit floating point from the packet. | |
| * @param minimum The inclusive minimum used for the range. | |
| * @param maximum The inclusive maximum used for the range. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat32(minimum:float32, maximum:float32, bits:uint32, callback:(float32, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('float32 expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| if (minimum < 0 && maximum > 0) | |
| { | |
| callback(value == 0 ? 0 : (value - 1) / ((0x1 << bits) - 2) * (maximum - minimum) + minimum, this); | |
| } | |
| else | |
| { | |
| callback(value / ((0x1 << bits) - 1) * (maximum - minimum) + minimum, this); | |
| } | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a 64-bit floating point from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat64(callback:(float64, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + 64 > this.maximumBitIndex) | |
| { | |
| this.error('float64 expected'); | |
| } | |
| else | |
| { | |
| var arrayBuffer = new ArrayBuffer(8); | |
| var float64 = new Float64Array(arrayBuffer); | |
| var float64UInt32 = new Uint32Array(arrayBuffer); | |
| this.ReadUInt32((value) => | |
| { | |
| float64UInt32[0] = value; | |
| }); | |
| this.ReadUInt32((value) => | |
| { | |
| float64UInt32[1] = value; | |
| }); | |
| callback(float64[0], this); | |
| } | |
| } | |
| /** | |
| * Reads a 64-bit floating point from the packet. | |
| * @param maximum The inclusive maximum used for the range starting at 0. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat64(maximum:float64, bits:uint32, callback:(float64, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('float64 expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| callback(value / ((0x1 << bits) - 1) * maximum, this); | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a 64-bit floating point from the packet. | |
| * @param minimum The inclusive minimum used for the range. | |
| * @param maximum The inclusive maximum used for the range. | |
| * @param bits The number of bits used. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadFloat64(minimum:float64, maximum:float64, bits:uint32 callback:(float64, Packet)) | |
| { | |
| if (this.error == null) return; | |
| if (this.bitIndex + bits > this.maximumBitIndex) | |
| { | |
| this.error('float64 expected'); | |
| } | |
| else | |
| { | |
| this.ReadUIntN(bits, (value) => | |
| { | |
| if (minimum < 0 && maximum > 0) | |
| { | |
| callback(value == 0 ? 0 : (value - 1) / ((0x1 << bits) - 2) * (maximum - minimum) + minimum, this); | |
| } | |
| else | |
| { | |
| callback(value / ((0x1 << bits) - 1) * (maximum - minimum) + minimum, this); | |
| } | |
| }); | |
| } | |
| } | |
| /** | |
| * Reads a string from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadString(callback:(string, Packet)) | |
| { | |
| var value = ''; | |
| var packet = this; | |
| this.ReadUInt16((length) => | |
| { | |
| for (var index = 0; index < length; ++index) | |
| { | |
| packet.ReadUIntN(7, (charCode) => | |
| { | |
| value += string.fromCharCode(charCode); | |
| }); | |
| } | |
| callback(value, this); | |
| }); | |
| } | |
| /** | |
| * Reads a packet from the packet. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadPacket(callback:(Packet, Packet)) | |
| { | |
| if (this.error == null) return; | |
| this.ReadUIntN(this.headerSize, (maximumBitIndex, packet) => | |
| { | |
| if (packet.bitIndex + maximumBitIndex - packet.headerSize > packet.maximumBitIndex) | |
| { | |
| packet.error('Packet expected'); | |
| } | |
| else | |
| { | |
| var bitIndex = packet.BitIndex; | |
| var value = Packet.Create(packet.Buffer.buffer, packet.error); | |
| value.BitIndex = packet.bitIndex; | |
| value.MaximumBitIndex = packet.bitIndex + maximumBitIndex - packet.headerSize; | |
| packet.bitIndex += maximumBitIndex - packet.headerSize; | |
| callback(value, packet); | |
| } | |
| }); | |
| } | |
| /** | |
| * Reads a block of data with one callback. | |
| * @param readOperations A datatype string or array starting with a datatype string followed by arguments. As an example to use ReadUInt8 you would use the datatype string 'UInt8'. For ReadUIntN | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| Read(...readOperations, callback:(..., Packet)) | |
| { | |
| var values = []; | |
| for (var i = 0; i < readOperations.length; ++i) | |
| { | |
| if (typeof readOperations[i] == 'string') | |
| { | |
| this['Read' + readOperations[i]]((value) => | |
| { | |
| values.push(value); | |
| }); | |
| } | |
| else | |
| { | |
| readOperations[i].push((value) => | |
| { | |
| values.push(value); | |
| }); | |
| this['Read' + readOperations[i].shift()].apply(this, readOperations[i]); | |
| } | |
| } | |
| values.push(this); | |
| callback.apply(this, values); | |
| } | |
| /** | |
| * Reads a boolean and executes read operations on true. | |
| * @param trueReadOperations A datatype string or array starting with a datatype string followed by arguments. As an example to use ReadUInt8 you would use the datatype string 'UInt8'. | |
| * @param callback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadConditional(...trueReadOperations, trueCallback:(..., Packet)) | |
| { | |
| this.ReadBoolean((conditional, packet) => | |
| { | |
| if (conditional) | |
| { | |
| var values = []; | |
| for (var i = 0; i < trueReadOperations.length; ++i) | |
| { | |
| if (typeof trueReadOperations[i] == 'string') | |
| { | |
| packet['Read' + trueReadOperations[i]]((value) => | |
| { | |
| values.push(value); | |
| }); | |
| } | |
| else | |
| { | |
| trueReadOperations[i].push((value) => | |
| { | |
| values.push(value); | |
| }); | |
| packet['Read' + trueReadOperations[i].shift()].apply(packet, trueReadOperations[i]); | |
| } | |
| } | |
| values.push(packet); | |
| trueCallback.apply(arguments.callee.caller, values); | |
| } | |
| }); | |
| } | |
| /** | |
| * Reads a boolean and executes read operations on true or false. | |
| * @param trueReadOperations A datatype string or array starting with a datatype string followed by arguments. As an example to use ReadUInt8 you would use the datatype string 'UInt8'. | |
| * @param trueCallback A callback with the result. Only executes if the read succeeds. | |
| * @param falseReadOperations A datatype string or array starting with a datatype string followed by arguments. As an example to use ReadUInt8 you would use the datatype string 'UInt8'. | |
| * @param falseCallback A callback with the result. Only executes if the read succeeds. | |
| */ | |
| ReadConditional(...trueReadOperations, trueCallback:(..., Packet), ...falseReadOperations, falseCallback:(..., Packet)) | |
| { | |
| this.ReadBoolean((conditional, packet) => | |
| { | |
| if (conditional) | |
| { | |
| var values = []; | |
| for (var i = 0; i < trueReadOperations.length; ++i) | |
| { | |
| if (typeof trueReadOperations[i] == 'string') | |
| { | |
| packet['Read' + trueReadOperations[i]]((value) => | |
| { | |
| values.push(value); | |
| }); | |
| } | |
| else | |
| { | |
| trueReadOperations[i].push((value) => | |
| { | |
| values.push(value); | |
| }); | |
| packet['Read' + trueReadOperations[i].shift()].apply(packet, trueReadOperations[i]); | |
| } | |
| } | |
| values.push(packet); | |
| trueCallback.apply(packet, values); | |
| } | |
| else | |
| { | |
| var values = []; | |
| for (var i = 0; i < falseReadOperations.length; ++i) | |
| { | |
| if (typeof falseReadOperations[i] == 'string') | |
| { | |
| packet['Read' + falseReadOperations[i]]((value) => | |
| { | |
| values.push(value); | |
| }); | |
| } | |
| else | |
| { | |
| falseReadOperations[i].push((value) => | |
| { | |
| values.push(value); | |
| }); | |
| packet['Read' + falseReadOperations[i].shift()].apply(packet, falseReadOperations[i]); | |
| } | |
| } | |
| values.push(packet); | |
| falseCallback.apply(packet, values); | |
| } | |
| }); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment