Last active
March 19, 2017 16:10
-
-
Save MagnificentPako/56fad6b8ba8686a96f78a7c954bcaeea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "buffered" | |
class Frame | |
let _final: Bool | |
let _rsv: (Bool, Bool, Bool) | |
let _opcode: Opcode | |
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': Opcode, 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/home/paul/doc/dev/Pony/helloworld/frame.pony:40:25: receiver type is not a subtype of target type | |
for byte' in bw.done().values() do | |
^ | |
Info: | |
/home/paul/doc/dev/Pony/helloworld/frame.pony:40:18: receiver type: BitWriter iso! | |
for byte' in bw.done().values() do | |
^ | |
/home/paul/doc/dev/Pony/helloworld/bitwriter.pony:7:3: target type: BitWriter ref | |
fun ref done(): Array[U8] => | |
^ | |
/home/paul/doc/dev/Pony/helloworld/frame.pony:40:25: this would be possible if the arguments and return value were all sendable | |
for byte' in bw.done().values() do | |
^ | |
/home/paul/doc/dev/Pony/helloworld/bitwriter.pony:1:1: BitWriter iso! is not a subtype of BitWriter ref: iso! is not a subcap of ref | |
class BitWriter | |
^ | |
Error: | |
/home/paul/doc/dev/Pony/helloworld/frame.pony:40:5: cannot infer type of for loop iterator | |
for byte' in bw.done().values() do | |
^ | |
Error: | |
/home/paul/doc/dev/Pony/helloworld/frame.pony:41:17: cannot infer type of byte' | |
writer.u8(byte') | |
^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BitWriter | |
var _content: Array[U8] = _content.create(1) | |
var _size: USize = 0 | |
var _offset: USize = 0 | |
fun ref done(): Array[U8] => | |
var byte_amount: USize = (_content.size() / 8) | |
var output: Array[U8] ref = output.create(byte_amount) | |
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 | |
output.reverse() | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment