From 97fec78b40539038fcb6e1a223d4d72b8ea06390 Mon Sep 17 00:00:00 2001 From: Louis Schmieder Date: Sun, 9 Aug 2020 04:12:29 +0200 Subject: [PATCH] io: input/output streams (#6078) --- vlib/io/net_stream_test.v | 181 ++++++++++++++++++++++++++++++++++++ vlib/io/netinstream.v | 188 ++++++++++++++++++++++++++++++++++++++ vlib/io/netoutstream.v | 184 +++++++++++++++++++++++++++++++++++++ vlib/io/stream.v | 52 +++++++++++ 4 files changed, 605 insertions(+) create mode 100644 vlib/io/net_stream_test.v create mode 100644 vlib/io/netinstream.v create mode 100644 vlib/io/netoutstream.v create mode 100644 vlib/io/stream.v diff --git a/vlib/io/net_stream_test.v b/vlib/io/net_stream_test.v new file mode 100644 index 0000000000..a0ff86e457 --- /dev/null +++ b/vlib/io/net_stream_test.v @@ -0,0 +1,181 @@ +import net +import io + +struct Test { + a int + b f32 + c string +} + +fn setup() (net.Socket, net.Socket, net.Socket) { + server := net.listen(0) or { panic(err) } + server_port := server.get_port() + client := net.dial('127.0.0.1', server_port) or { panic(err) } + socket := server.accept() or { panic(err) } + return server, client, socket +} + +fn test_arrays() { + _, c, s := setup() + + mut nos := io.new_net_output_stream(s) + mut nis := io.new_net_input_stream(c) + + //bytes + a := [byte(76), 7, 43, 5] + nos.write_bytes(a) or { assert false } + c_a := nis.read_bytes(4) + assert a == c_a + + //u16s + b := [u16(546), 3434, 33] + nos.write_u16s(b) or { assert false } + c_b := nis.read_u16s(3) + assert b == c_b + + //u32s + d := [u32(10), 34324, 454, 34, 352] + nos.write_u32s(d) or { assert false } + c_d := nis.read_u32s(5) + assert d == c_d + + //u64s + e := [u64(32542), 23213, 23244353, 324534534] + nos.write_u64s(e) or { assert false } + c_e := nis.read_u64s(4) + assert e == c_e + + //i8s + f := [i8(20), 40, 5, 10] + nos.write_i8s(f) or { assert false } + c_f := nis.read_i8s(4) + assert f == c_f + + //i16s + g := [i16(3434), 3242, 655, 445, 23] + nos.write_i16s(g) or { assert false } + c_g := nis.read_i16s(5) + assert g == c_g + + //i32s + h := [342, 32424, 565, 343, 7676, 34] + nos.write_ints(h) or { assert false } + c_h := nis.read_ints(6) + assert h == c_h + //i64s + i := [i64(354345), 45435564, 54645654, 3242342] + nos.write_i64s(i) or { assert false } + c_i := nis.read_i64s(4) + assert i == c_i +} + +fn test_primitives() { + _, c, s := setup() + + mut nos := io.new_net_output_stream(s) + mut nis := io.new_net_input_stream(c) + + // bytes + a := byte(45) + nos.write_byte(a) or { assert false } + c_a := nis.read_byte() + assert a == c_a + + // u16 + b := u16(345) + nos.write_u16(b) or { assert false } + c_b := nis.read_u16() + assert b == c_b + + // u32 + d := u32(353453) + nos.write_u32(d) or { assert false } + c_d := nis.read_u32() + assert d == c_d + + // u64 + e := u64(43645645654) + nos.write_u64(e) or { assert false } + c_e := nis.read_u64() + assert e == c_e + + // i8 + f := i8(43) + nos.write_i8(f) or { assert false } + c_f := nis.read_i8() + assert f == c_f + + // i16 + g := i16(676) + nos.write_i16(g) or { assert false } + c_g := nis.read_i16() + assert g == c_g + + // int + h := 4543565 + nos.write_int(h) or { assert false } + c_h := nis.read_int() + assert h == c_h + + // i64 + i := i64(4343654654654) + nos.write_i64(i) or { assert false } + c_i := nis.read_i64() + assert i == c_i +} + +fn test_floats() { + _, c, s := setup() + + mut nos := io.new_net_output_stream(s) + mut nis := io.new_net_input_stream(c) + + a := f32(7.5) + nos.write_f32(a) or { assert false } + c_a := nis.read_f32() + assert a == c_a + + b := f64(43587349857834579834.45435435) + nos.write_f64(b) or { assert false } + c_b := nis.read_f64() + assert b == c_b + + d := [f32(7.3), 3.45, 546.3, 4545.3] + nos.write_f32s(d) or { assert false } + c_d := nis.read_f32s(4) + assert d == c_d + + e := [f64(345324324.3242342), 3243242.342, 344564.343242423, 43543.43534, 34234.34324] + nos.write_f64s(e) or { assert false } + c_e := nis.read_f64s(5) + assert e == c_e +} + +fn test_string() { + _, c, s := setup() + + mut nos := io.new_net_output_stream(s) + mut nis := io.new_net_input_stream(c) + + a := 'hello' + nos.write_string(a) or { assert false } + c_a := nis.read_string(5) + assert a == c_a +} + +fn test_struct() { + _, c, s := setup() + + mut nos := io.new_net_output_stream(s) + mut nis := io.new_net_input_stream(c) + + a := Test{ + a: 1 + b: 2.0 + c: 'test' + } + nos.write_struct(a, sizeof(Test)) or { assert false } + got := &Test(nis.read_struct(sizeof(Test))) + de_ref := *got + assert a.a == de_ref.a && a.b == de_ref.b && a.c == de_ref.c +} diff --git a/vlib/io/netinstream.v b/vlib/io/netinstream.v new file mode 100644 index 0000000000..adeb8e7d81 --- /dev/null +++ b/vlib/io/netinstream.v @@ -0,0 +1,188 @@ +module io + +import net +import encoding.binary + +struct NetInputStream { +mut: + sock &net.Socket +} + +pub fn new_net_input_stream(sock &net.Socket) &NetInputStream { + return &NetInputStream{ + sock: sock + } +} + +pub fn (mut nis NetInputStream) read_int() int { + return int(binary.big_endian_u32(nis.read_bytes(sizeof(int)))) +} + +pub fn (mut nis NetInputStream) read_ints(l u32) []int { + bytes := nis.read_bytes(sizeof(int) * l) + mut ints := []int{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(int)) + b := bytes[offs..int(u32(offs) + sizeof(int))] + ints << int(binary.big_endian_u32(b)) + } + return ints +} + +pub fn (mut nis NetInputStream) read_i8() i8 { + return i8(nis.read_byte()) +} + +pub fn (mut nis NetInputStream) read_i8s(l u32) []i8 { + bytes := nis.read_bytes(sizeof(i8) * l) + mut i8s := []i8{} + for i in 0 .. l { + i8s << i8(bytes[i]) + } + return i8s +} + +pub fn (mut nis NetInputStream) read_i16() i16 { + return i16(binary.big_endian_u16(nis.read_bytes(sizeof(i16)))) +} + +pub fn (mut nis NetInputStream) read_i16s(l u32) []i16 { + bytes := nis.read_bytes(sizeof(i16) * l) + mut i16s := []i16{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(i16)) + b := bytes[offs..int(u32(offs) + sizeof(i16))] + i16s << i16(binary.big_endian_u16(b)) + } + return i16s +} + +pub fn (mut nis NetInputStream) read_i64() i64 { + return i64(binary.big_endian_u64(nis.read_bytes(sizeof(i64)))) + +} + +pub fn (mut nis NetInputStream) read_i64s(l u32) []i64 { + bytes := nis.read_bytes(sizeof(i64) * l) + mut i64s := []i64{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(i64)) + b := bytes[offs..int(u32(offs) + sizeof(i64))] + i64s << i64(binary.big_endian_u64(b)) + } + return i64s +} + +pub fn (mut nis NetInputStream) read_byte() byte { + ptr, _ := nis.sock.recv(int(sizeof(byte))) + unsafe { + return ptr[0] + } +} + +pub fn (mut nis NetInputStream) read_bytes(l u32) []byte { + mut bytes := []byte{len: int(l), cap: int(l)} + for i in 0..l { + bytes[i] = nis.read_byte() + } + return bytes +} + +pub fn (mut nis NetInputStream) read_u16() u16 { + return binary.big_endian_u16(nis.read_bytes(sizeof(u16))) +} + +pub fn (mut nis NetInputStream) read_u16s(l u32) []u16 { + bytes := nis.read_bytes(sizeof(u16) * l) + mut u16s := []u16{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(u16)) + b := bytes[offs..int(u32(offs) + sizeof(u16))] + u16s << binary.big_endian_u16(b) + + } + return u16s +} + +pub fn (mut nis NetInputStream) read_u32() u32 { + return binary.big_endian_u32(nis.read_bytes(sizeof(u32))) +} + +pub fn (mut nis NetInputStream) read_u32s(l u32) []u32 { + bytes := nis.read_bytes(sizeof(u32) * l) + mut u32s := []u32{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(u32)) + b := bytes[offs..int(u32(offs) + sizeof(u32))] + u32s << binary.big_endian_u32(b) + } + return u32s +} + +pub fn (mut nis NetInputStream) read_u64() u64 { + return binary.big_endian_u64(nis.read_bytes(sizeof(u64))) +} + +pub fn (mut nis NetInputStream) read_u64s(l u32) []u64 { + bytes := nis.read_bytes(sizeof(u64) * l) + mut u64s := []u64{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(u64)) + b := bytes[offs..int(u32(offs) + sizeof(u64))] + u64s << binary.big_endian_u64(b) + } + return u64s +} +pub fn (mut nis NetInputStream) read_f32() f32 { + bytes := nis.read_bytes(sizeof(f32)) + f := &f32(bytes.data) + return *f +} + +pub fn (mut nis NetInputStream) read_f32s(l u32) []f32 { + bytes := nis.read_bytes(sizeof(f32) * l) + mut f32s := []f32{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(f32)) + b := bytes[offs..int(u32(offs) + sizeof(f32))] + f := &f32(b.data) + unsafe { + f32s << *f + } + } + return f32s +} + +pub fn (mut nis NetInputStream) read_f64() f64 { + bytes := nis.read_bytes(sizeof(f64)) + f := &f64(bytes.data) + return *f +} + +pub fn (mut nis NetInputStream) read_f64s(l u32) []f64 { + bytes := nis.read_bytes(sizeof(f64) * l) + mut f64s := []f64{} + for i in 0 .. l { + offs := int(u32(i) * sizeof(f64)) + b := bytes[offs..int(u32(offs) + sizeof(f64))] + f := &f64(b.data) + unsafe { + f64s << *f + } + } + return f64s +} + +pub fn (mut nis NetInputStream) read_string(l u32) string { + bytes := nis.read_bytes(l) + return tos(bytes.data, bytes.len) +} + +pub fn (mut nis NetInputStream) skip(l u32) { + nis.read_bytes(l) +} + +// TODO make it generic +pub fn (mut nis NetInputStream) read_struct(l u32) voidptr { + return voidptr(nis.read_bytes(l).data) +} diff --git a/vlib/io/netoutstream.v b/vlib/io/netoutstream.v new file mode 100644 index 0000000000..6275375a78 --- /dev/null +++ b/vlib/io/netoutstream.v @@ -0,0 +1,184 @@ +module io + +import net +import encoding.binary + +struct NetOutputStream { +mut: + sock &net.Socket +} + +pub fn new_net_output_stream(sock &net.Socket) &NetOutputStream { + return &NetOutputStream{ + sock: sock + } +} + +pub fn (mut nos NetOutputStream) write_int(d int) ? { + mut bytes := []byte{len: int(sizeof(int))} + binary.big_endian_put_u32(mut bytes, u32(d)) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_ints(d []int) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(int))} + binary.big_endian_put_u32(mut tmp, u32(u)) + bytes << tmp + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_i8(d i8) ? { + nos.sock.send([byte(d)].data, int(sizeof(i8)))? +} + +pub fn (mut nos NetOutputStream) write_i8s(d []i8) ? { + nos.sock.send(d.data, int(sizeof(i8) * u32(d.len)))? +} + +pub fn (mut nos NetOutputStream) write_i16(d i16) ? { + mut bytes := []byte{len: int(sizeof(i16))} + binary.big_endian_put_u16(mut bytes, u16(d)) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_i16s(d []i16) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(i16))} + binary.big_endian_put_u16(mut tmp, u16(u)) + bytes << tmp + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_i64(d i64) ? { + mut bytes := []byte{len: int(sizeof(i64))} + binary.big_endian_put_u64(mut bytes, u64(d)) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_i64s(d []i64) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(i64))} + binary.big_endian_put_u64(mut tmp, u64(u)) + bytes << tmp + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_byte(d byte) ? { + nos.sock.send([d].data, int(sizeof(byte)))? +} + +pub fn (mut nos NetOutputStream) write_bytes(d []byte) ? { + nos.sock.send(d.data, int(sizeof(byte) * u32(d.len)))? +} + +pub fn (mut nos NetOutputStream) write_u16(d u16) ? { + mut bytes := []byte{len: int(sizeof(u16))} + binary.big_endian_put_u16(mut bytes, d) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_u16s(d []u16) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(u16))} + binary.big_endian_put_u16(mut tmp, u) + bytes << tmp + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_u32(d u32) ? { + mut bytes := []byte{len: int(sizeof(u32))} + binary.big_endian_put_u32(mut bytes, d) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_u32s(d []u32) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(u32))} + binary.big_endian_put_u32(mut tmp, u) + bytes << tmp + } + nos.sock.send(bytes.data, int(sizeof(u32) * u32(d.len)))? +} + +pub fn (mut nos NetOutputStream) write_u64(d u64) ? { + mut bytes := []byte{len: int(sizeof(u64))} + binary.big_endian_put_u64(mut bytes, d) + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_u64s(d []u64) ? { + mut bytes := []byte{} + for u in d { + mut tmp := []byte{len: int(sizeof(u64))} + binary.big_endian_put_u64(mut tmp, u) + bytes << tmp + } + nos.sock.send(bytes.data, int(sizeof(u64) * u32(d.len)))? +} + +pub fn (mut nos NetOutputStream) write_f32(d f32) ? { + pb := &byte(&d) + mut bytes := []byte{len: int(sizeof(f32))} + unsafe { + for i in 0..bytes.len { + bytes[i] = pb[i] + } + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_f32s(d []f32) ? { + mut bytes := []byte{} + for f in d { + pb := &byte(&f) + unsafe { + for i in 0..int(sizeof(f32)) { + bytes << pb[i] + } + } + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_f64(d f64) ? { + pb := &byte(&d) + mut bytes := []byte{len: int(sizeof(f64))} + unsafe { + for i in 0..bytes.len { + bytes[i] = pb[i] + } + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_f64s(d []f64) ? { + mut bytes := []byte{} + for f in d { + pb := &byte(&f) + unsafe { + for i in 0..int(sizeof(f64)) { + bytes << pb[i] + } + } + } + nos.sock.send(bytes.data, bytes.len)? +} + +pub fn (mut nos NetOutputStream) write_string(d string) ? { + nos.write_bytes(d.bytes())? +} + +// TODO make it generic +pub fn (mut nos NetOutputStream) write_struct(d voidptr, l u32) ? { + nos.sock.send(byteptr(d), int(l))? +} diff --git a/vlib/io/stream.v b/vlib/io/stream.v new file mode 100644 index 0000000000..a1d8216ada --- /dev/null +++ b/vlib/io/stream.v @@ -0,0 +1,52 @@ +module io + +pub interface InputStream { + read_int() int + read_ints(l u32) []int + read_i8() i8 + read_i8s(l u32) []i8 + read_i16() i16 + read_i16s(l u32) []i16 + read_i64() i64 + read_i64s(l u32) []i64 + read_byte() byte + read_bytes(l u32) []byte + read_u16() u16 + read_u16s(l u32) []u16 + read_u32() u32 + read_u32s(l u32) []u32 + read_u64() u64 + read_u64s(l u32) []u64 + read_f32() f32 + read_f32s(l u32) []f32 + read_f64() f64 + read_f64s(l u32) []f64 + read_string(l u32) + skip(l u32) + read_struct(l u32) voidptr +} + +pub interface OutputStream { + write_int(d int) ? + write_ints(d []int) ? + write_i8(d i8) ? + write_i8s(d []i8) ? + write_i16(d i16) ? + write_i16s(d []i16) ? + write_i64(d i64) ? + write_i64s(d []i64) ? + write_byte(d byte) ? + write_bytes(d []byte) ? + write_u16(d u16) ? + write_u16s(d []u16) ? + write_u32(d u32) ? + write_u32s(d []u32) ? + write_u64(d u64) ? + write_u64s(d []u64) ? + write_f32(d f32) ? + write_f32s(d []f32) ? + write_f64(d f64) ? + write_f64s(d []f64) ? + write_string(d string) ? + write_struct(d voidptr, l u32) ? +}