# Pastebin Vuswc6mq use "buffered" class BitWriter var _content: Array[U8] = _content.create(1) var _size: USize = 0 var _offset: USize = 0 fun ref done(): Array[U8] iso^ => var byte_amount: USize = (_content.size() / 8) var output: Array[U8] iso = recover iso output.create(byte_amount) end if ((_content.size() % 8) != 0) then byte_amount = byte_amount + 1 end while _content.size() > 0 do var curr: Array[U8] = curr.create(8) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr.push(_secure_pop(_content)) curr = curr.reverse() output.push(_bits_to_byte(curr)) end _content.reserve(1) _size = 0 _offset = 0 recover iso (consume output).reverse() end fun ref _check(size': USize) => if (_content.size() - _offset) < size' then _content.undefined(_offset + size') end fun ref string(str: String) => for byte' in str.array().values() do byte(byte') end fun ref byte_array(bytes: Array[U8]) => for byte' in bytes.values() do byte(byte') end fun ref byte(byte': U8) => bit_array(_byte_to_bits(byte')) fun ref bit_array(bits: Array[U8]) => _check(bits.size()) for bit' in bits.values() do bit(bit') end fun ref bits_of_byte(byte': U8, amount: USize) => var skip: USize = 8 - amount var ar: Array[U8] = _byte_to_bits(byte') try while skip > 0 do ar.pop() skip = skip - 1 end end var out: Array[U8] = out.create(USize(amount)) var am: USize = consume amount try while am > 0 do out.push(ar.pop()) am = am - 1 end end out fun ref bit(bit': U8) => try _check(1) _content(_offset) = (bit' and 0b00000001) //So it actually is just one bit _offset = _offset + 1 _size = _size + 1 end fun _byte_to_bits(byte': U8): Array[U8] => var bits: Array[U8] = bits.create(8) var mask: U8 = 0b00000001 bits.push(((byte' >> 7) and mask)) bits.push(((byte' >> 6) and mask)) bits.push(((byte' >> 5) and mask)) bits.push(((byte' >> 4) and mask)) bits.push(((byte' >> 3) and mask)) bits.push(((byte' >> 2) and mask)) bits.push(((byte' >> 1) and mask)) bits.push((byte' and mask)) bits fun _bits_to_byte(bits: Array[U8]): U8 => var res: U8 = 0 try res = (bits.pop()) or (bits.pop() << 1) or (bits.pop() << 2) or (bits.pop() << 3) or (bits.pop() << 4) or (bits.pop() << 5) or (bits.pop() << 6) or (bits.pop() << 7) end res fun _secure_pop(ar: Array[U8]): U8 => var p: U8 = 0 try var popped: (None | U8) = ar.pop() p = match popped | None => 0 else popped as U8 end end p class Frame let _final: Bool let _rsv: (Bool, Bool, Bool) let _opcode: String let _use_mask: Bool let _payload_type: U8 let _payload_size: U64 let _mask_key: (None | U32) let _data: Array[U8] val new create(final': Bool, opcode': String, data': String) => _final = final' _rsv = (false, false, false) _opcode = opcode' _use_mask = false _payload_type = if data'.size() <= 126 then 0 else if data'.size() <= 65536 then 1 else 2 end end _payload_size = data'.size().u64() _mask_key = None _data = data'.array() fun build(): Array[ByteSeq] iso^ => let writer = Writer let bw = BitWriter bw.bit(1) // FIN bw.bit(0) // RSV1 bw.bit(0) // RSV2 bw.bit(0) // RSV3 bw.bit(0) bw.bit(0) bw.bit(1) bw.bit(0) if (_payload_size <= 126) then bw.bit(1) end for byte' in bw.done().values() do writer.u8(byte') end writer.done()