1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: change optional to result of io (#16075)

This commit is contained in:
yuyi
2022-10-16 14:28:57 +08:00
committed by GitHub
parent 6e46933c55
commit f6844e9766
187 changed files with 1885 additions and 1874 deletions

View File

@ -5,9 +5,9 @@ import io
fn main() {
// Make a new connection
mut conn := net.dial_tcp('google.com:80')?
mut conn := net.dial_tcp('google.com:80')!
// Simple http HEAD request for a file
conn.write_string('GET /index.html HTTP/1.0\r\n\r\n')?
conn.write_string('GET /index.html HTTP/1.0\r\n\r\n')!
// Wrap in a buffered reader
mut r := io.new_buffered_reader(reader: conn)
for {

View File

@ -2,9 +2,9 @@ import net.http
import sync
import time
fn vlang_time(mut wg sync.WaitGroup) ?string {
fn vlang_time(mut wg sync.WaitGroup) !string {
start := time.ticks()
data := http.get('https://vlang.io/utc_now')?
data := http.get('https://vlang.io/utc_now')!
finish := time.ticks()
println('Finish getting time ${finish - start} ms')
println(data.body)
@ -12,9 +12,9 @@ fn vlang_time(mut wg sync.WaitGroup) ?string {
return data.body
}
fn remote_ip(mut wg sync.WaitGroup) ?string {
fn remote_ip(mut wg sync.WaitGroup) !string {
start := time.ticks()
data := http.get('https://api.ipify.org')?
data := http.get('https://api.ipify.org')!
finish := time.ticks()
println('Finish getting ip ${finish - start} ms')
println(data.body)

View File

@ -10,9 +10,9 @@ type FNAdder = fn (int, int) int
fn main() {
library_file_path := os.join_path(os.dir(@FILE), dl.get_libname('library'))
handle := dl.open_opt(library_file_path, dl.rtld_lazy)?
handle := dl.open_opt(library_file_path, dl.rtld_lazy)!
eprintln('handle: ${ptr_str(handle)}')
f := FNAdder(dl.sym_opt(handle, 'add_1')?)
f := FNAdder(dl.sym_opt(handle, 'add_1')!)
eprintln('f: ${ptr_str(f)}')
res := f(1, 2)
eprintln('res: $res')

View File

@ -34,5 +34,5 @@ fn main() {
mut server := Server{
handler: ExampleHandler{}
}
server.listen_and_serve()?
server.listen_and_serve()
}

View File

@ -5,7 +5,7 @@ import os
const numeric_char = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `.`, `e`, `E`]
// Convert expression to Reverse Polish Notation.
fn expr_to_rev_pol(expr string) ?[]string {
fn expr_to_rev_pol(expr string) ![]string {
if expr == '' {
return error('err: empty expression')
}
@ -63,7 +63,7 @@ fn expr_to_rev_pol(expr string) ?[]string {
}
// Evaluate the result of Reverse Polish Notation.
fn eval_rev_pol(rev_pol []string) ?f64 {
fn eval_rev_pol(rev_pol []string) !f64 {
mut stack := []f64{}
for item in rev_pol {
if is_num_string(item) {

View File

@ -1,5 +1,5 @@
import net
conn := net.dial_tcp('[::1]:57000')?
peer_addr := conn.peer_addr()?
conn := net.dial_tcp('[::1]:57000')!
peer_addr := conn.peer_addr()!
println('$peer_addr')

View File

@ -1,5 +1,5 @@
import net
conn := net.dial_tcp('google.com:80')?
peer_addr := conn.peer_addr()?
conn := net.dial_tcp('google.com:80')!
peer_addr := conn.peer_addr()!
println('$peer_addr')

View File

@ -3,18 +3,18 @@ import io
fn main() {
// Make a new connection
mut conn := net.dial_tcp('google.com:80')?
mut conn := net.dial_tcp('google.com:80')!
defer {
conn.close() or {}
}
println(' peer: ${conn.peer_addr()?}')
println('local: ${conn.addr()?}')
println(' peer: ${conn.peer_addr()!}')
println('local: ${conn.addr()!}')
// Simple http HEAD request for a file
conn.write_string('HEAD /index.html HTTP/1.0\r\n\r\n')?
conn.write_string('HEAD /index.html HTTP/1.0\r\n\r\n')!
// Read all the data that is waiting
result := io.read_all(reader: conn)?
result := io.read_all(reader: conn)!
// Cast to string and print result
println(result.bytestr())
}

View File

@ -2,9 +2,9 @@ import net.http
import sync
import time
fn send_request(mut wg sync.WaitGroup) ?string {
fn send_request(mut wg sync.WaitGroup) !string {
start := time.ticks()
data := http.get('https://google.com')?
data := http.get('https://google.com')!
finish := time.ticks()
println('Finish getting time ${finish - start} ms')
wg.done()

View File

@ -12,7 +12,7 @@ fn main() {
mut buf := []u8{len: 100}
if is_server {
println('UDP echo server, listening for udp packets on port: $port')
mut c := net.listen_udp(':$port')?
mut c := net.listen_udp(':$port')!
for {
read, addr := c.read(mut buf) or { continue }
println('received $read bytes from $addr')
@ -23,7 +23,7 @@ fn main() {
}
} else {
println('UDP client, sending packets to port: ${port}.\nType `exit` to exit.')
mut c := net.dial_udp('localhost:$port')?
mut c := net.dial_udp('localhost:$port')!
for {
mut line := os.input('client > ')
match line {
@ -36,8 +36,8 @@ fn main() {
}
else {}
}
c.write_string(line)?
read, _ := c.read(mut buf)?
c.write_string(line)!
read, _ := c.read(mut buf)!
println('server : ' + buf[0..read].bytestr())
}
}

View File

@ -6,7 +6,7 @@ import sim.anim
import sim.args as simargs
fn main() {
args := simargs.parse_args(extra_workers: 1)? as simargs.ParallelArgs
args := simargs.parse_args(extra_workers: 1)! as simargs.ParallelArgs
mut app := anim.new_app(args)
mut workers := []thread{cap: args.workers}
@ -27,7 +27,7 @@ fn main() {
workers << go sim.sim_worker(id, app.request_chan, [app.result_chan])
}
handle_request := fn [app] (request &sim.SimRequest) ? {
handle_request := fn [app] (request &sim.SimRequest) ! {
app.request_chan <- request
}

View File

@ -7,11 +7,11 @@ import sim.args as simargs
import sim.img
fn main() {
args := simargs.parse_args(extra_workers: 2)? as simargs.ParallelArgs
args := simargs.parse_args(extra_workers: 2)! as simargs.ParallelArgs
img_settings := img.image_settings_from_grid(args.grid)
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)?
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)!
mut app := anim.new_app(args)
mut workers := []thread{cap: args.workers + 1}
@ -41,7 +41,7 @@ fn main() {
workers << go sim.sim_worker(id, app.request_chan, [app.result_chan, img_result_chan])
}
handle_request := fn [app] (request &sim.SimRequest) ? {
handle_request := fn [app] (request &sim.SimRequest) ! {
app.request_chan <- request
}

View File

@ -31,21 +31,21 @@ pub:
pub type SimArgs = ParallelArgs | SequentialArgs
pub fn parse_args(config ParserSettings) ?SimArgs {
pub fn parse_args(config ParserSettings) !SimArgs {
if config.sequential {
args := parse_sequential_args()?
args := parse_sequential_args()!
return SimArgs(args)
} else {
args := parse_parallel_args(config.extra_workers)?
args := parse_parallel_args(config.extra_workers)!
return SimArgs(args)
}
}
fn parse_sequential_args() ?SequentialArgs {
fn parse_sequential_args() !SequentialArgs {
mut fp := flag.new_flag_parser(os.args)
fp.application('vps')
fp.version('v0.1.0')
fp.limit_free_args(0, 0)?
fp.limit_free_args(0, 0)!
fp.description('This is a pendulum simulation written in pure V')
fp.skip_executable()
@ -64,7 +64,7 @@ fn parse_sequential_args() ?SequentialArgs {
fp.finalize() or {
println(fp.usage())
return none
return error('none')
}
params := sim.sim_params(
@ -92,11 +92,11 @@ fn parse_sequential_args() ?SequentialArgs {
return args
}
fn parse_parallel_args(extra_workers int) ?ParallelArgs {
fn parse_parallel_args(extra_workers int) !ParallelArgs {
mut fp := flag.new_flag_parser(os.args)
fp.application('vps')
fp.version('v0.1.0')
fp.limit_free_args(0, 0)?
fp.limit_free_args(0, 0)!
fp.description('This is a pendulum simulation written in pure V')
fp.skip_executable()
@ -117,7 +117,7 @@ fn parse_parallel_args(extra_workers int) ?ParallelArgs {
fp.finalize() or {
println(fp.usage())
return none
return error('none')
}
params := sim.sim_params(

View File

@ -39,34 +39,34 @@ mut:
cache_size int
}
pub fn ppm_writer_for_fname(fname string, settings ImageSettings) ?&PPMWriter {
pub fn ppm_writer_for_fname(fname string, settings ImageSettings) !&PPMWriter {
mut writer := &PPMWriter{
cache_size: settings.cache_size
cache: []u8{cap: settings.cache_size}
}
writer.start_for_file(fname, settings)?
writer.start_for_file(fname, settings)!
return writer
}
pub fn (mut writer PPMWriter) start_for_file(fname string, settings ImageSettings) ? {
writer.file = os.create(fname)?
writer.file.writeln('P6 $settings.width $settings.height 255')?
pub fn (mut writer PPMWriter) start_for_file(fname string, settings ImageSettings) ! {
writer.file = os.create(fname)!
writer.file.writeln('P6 $settings.width $settings.height 255')!
}
pub fn (mut writer PPMWriter) handle_pixel(p gx.Color) ? {
pub fn (mut writer PPMWriter) handle_pixel(p gx.Color) ! {
if writer.cache.len >= writer.cache_size {
writer.write()?
writer.flush()?
writer.write()!
writer.flush()!
}
writer.cache << [p.r, p.g, p.b]
}
pub fn (mut writer PPMWriter) flush() ? {
pub fn (mut writer PPMWriter) flush() ! {
writer.cache.clear()
}
pub fn (mut writer PPMWriter) write() ? {
writer.file.write(writer.cache)?
pub fn (mut writer PPMWriter) write() ! {
writer.file.write(writer.cache)!
}
pub fn (mut writer PPMWriter) close() {

View File

@ -29,7 +29,7 @@ pub fn new_image_writer(mut writer PPMWriter, settings ImageSettings) &ImageWrit
}
}
pub fn (mut iw ImageWritter) handle(result sim.SimResult) ?int {
pub fn (mut iw ImageWritter) handle(result sim.SimResult) !int {
total_pixels := iw.settings.width * iw.settings.height
// find the closest magnet
@ -46,7 +46,7 @@ pub fn (mut iw ImageWritter) handle(result sim.SimResult) ?int {
if iw.current_index == total_pixels {
iw.writer.write() or { panic('Could not write image') }
return none
return error('none')
}
return iw.current_index

View File

@ -3,11 +3,11 @@ module sim
import benchmark
import term
pub type SimRequestHandler = fn (request &SimRequest) ?
pub type SimRequestHandler = fn (request &SimRequest) !
pub type SimStartHandler = fn () ?
pub type SimStartHandler = fn () !
pub type SimFinishHandler = fn () ?
pub type SimFinishHandler = fn () !
pub const (
default_width = 600

View File

@ -6,7 +6,7 @@ import sim.args as simargs
import sim.img
fn main() {
args := simargs.parse_args()? as simargs.ParallelArgs
args := simargs.parse_args()! as simargs.ParallelArgs
img_settings := img.image_settings_from_grid(args.grid)
@ -17,7 +17,7 @@ fn main() {
request_chan := chan &sim.SimRequest{cap: args.workers}
result_chan := chan &sim.SimResult{cap: args.workers}
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)?
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)!
mut image_writer := img.new_image_writer(mut writer, img_settings)
mut workers := []thread{cap: args.workers}

View File

@ -6,14 +6,14 @@ import sim.args as simargs
import sim.img
fn main() {
args := simargs.parse_args(extra_workers: 1)? as simargs.ParallelArgs
args := simargs.parse_args(extra_workers: 1)! as simargs.ParallelArgs
img_settings := img.image_settings_from_grid(args.grid)
request_chan := chan &sim.SimRequest{cap: args.workers}
result_chan := chan &sim.SimResult{cap: args.workers}
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)?
mut writer := img.ppm_writer_for_fname(args.filename, img_settings)!
mut workers := []thread{cap: args.workers + 1}
mut bmark := benchmark.start()
@ -39,7 +39,7 @@ fn main() {
workers << go img.image_worker(mut writer, result_chan, img_settings)
handle_request := fn [request_chan] (request &sim.SimRequest) ? {
handle_request := fn [request_chan] (request &sim.SimRequest) ! {
request_chan <- request
}

View File

@ -6,19 +6,19 @@ import sim.args as simargs
import sim.img
fn main() {
args := simargs.parse_args(sequential: true)? as simargs.SequentialArgs
args := simargs.parse_args(sequential: true)! as simargs.SequentialArgs
mut bmark := benchmark.start()
defer {
bmark.measure(@FN)
}
mut writer := img.ppm_writer_for_fname(args.filename, img.image_settings_from_grid(args.grid))?
mut writer := img.ppm_writer_for_fname(args.filename, img.image_settings_from_grid(args.grid))!
defer {
writer.close()
}
handle_request := fn [mut writer] (request &sim.SimRequest) ? {
handle_request := fn [mut writer] (request &sim.SimRequest) ! {
result := sim.compute_result(request)
pixel := img.compute_pixel(result)
return writer.handle_pixel(pixel)
@ -26,5 +26,5 @@ fn main() {
sim.run(args.params, grid: args.grid, on_request: sim.SimRequestHandler(handle_request))
writer.write()?
writer.write()!
}

View File

@ -9,11 +9,11 @@ import net
// telnet 127.0.0.1 12345
fn main() {
mut server := net.listen_tcp(.ip6, ':12345')?
laddr := server.addr()?
mut server := net.listen_tcp(.ip6, ':12345')!
laddr := server.addr()!
eprintln('Listen on $laddr ...')
for {
mut socket := server.accept()?
mut socket := server.accept()!
go handle_client(mut socket)
}
}

View File

@ -14,21 +14,21 @@ fn main() {
}
// create TCP listener
mut listener := net.listen_tcp(.ip, 'localhost:9001')?
mut listener := net.listen_tcp(.ip, 'localhost:9001')!
defer {
listener.close() or {}
}
addr := listener.addr()?
addr := listener.addr()!
eprintln('Listening on $addr')
eprintln('Type `stop` to stop the server')
// create file descriptor notifier
mut notifier := notify.new()?
mut notifier := notify.new()!
defer {
notifier.close() or {}
}
notifier.add(os.stdin().fd, .read)?
notifier.add(listener.sock.handle, .read)?
notifier.add(os.stdin().fd, .read)!
notifier.add(listener.sock.handle, .read)!
for {
for event in notifier.wait(time.infinite) {

View File

@ -150,10 +150,10 @@ fn (item_list Item_list) get_file_path() string {
* Scan functions
*
******************************************************************************/
fn (mut item_list Item_list) scan_folder(path string, in_index int) ? {
fn (mut item_list Item_list) scan_folder(path string, in_index int) ! {
println('Scanning [$path]')
mut folder_list := []string{}
lst := os.ls(path)?
lst := os.ls(path)!
// manage the single files
for c, x in lst {
@ -171,7 +171,7 @@ fn (mut item_list Item_list) scan_folder(path string, in_index int) ? {
if ext == .zip {
item.i_type = .zip
item_list.lst << item
item_list.scan_zip(pt, item_list.lst.len - 1)?
item_list.scan_zip(pt, item_list.lst.len - 1)!
continue
}
if is_image(ext) == true {
@ -194,7 +194,7 @@ fn (mut item_list Item_list) scan_folder(path string, in_index int) ? {
i_type: .folder
}
item_list.lst << item
item_list.scan_folder(pt, item_list.lst.len - 1)?
item_list.scan_folder(pt, item_list.lst.len - 1)!
}
// println(item_list.lst.len)
// println("==================================")

View File

@ -11,14 +11,14 @@
import sokol.gfx
import szip
fn (mut il Item_list) scan_zip(path string, in_index int) ? {
fn (mut il Item_list) scan_zip(path string, in_index int) ! {
println('Scanning ZIP [$path]')
mut zp := szip.open(path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)?
n_entries := zp.total()?
mut zp := szip.open(path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)!
n_entries := zp.total()!
// println(n_entries)
for index in 0 .. n_entries {
zp.open_entry_by_index(index)?
is_dir := zp.is_dir()?
zp.open_entry_by_index(index)!
is_dir := zp.is_dir()!
name := zp.name()
size := zp.size()
// println("$index ${name} ${size:10} $is_dir")
@ -47,7 +47,7 @@ fn (mut il Item_list) scan_zip(path string, in_index int) ? {
zp.close()
}
fn (mut app App) load_texture_from_zip() ?(gfx.Image, int, int) {
fn (mut app App) load_texture_from_zip() !(gfx.Image, int, int) {
item := app.item_list.lst[app.item_list.item_index]
// println("Load from zip [${item.path}]")
@ -58,15 +58,15 @@ fn (mut app App) load_texture_from_zip() ?(gfx.Image, int, int) {
}
app.zip_index = item.container_index
// println("Opening the zip [${item.path}]")
app.zip = szip.open(item.path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)?
app.zip = szip.open(item.path, szip.CompressionLevel.no_compression, szip.OpenMode.read_only)!
}
// println("Now get the image")
app.zip.open_entry_by_index(item.container_item_index)?
app.zip.open_entry_by_index(item.container_item_index)!
zip_entry_size := int(item.size)
app.resize_buf_if_needed(zip_entry_size)
app.zip.read_entry_buf(app.mem_buf, app.mem_buf_size)?
app.zip.read_entry_buf(app.mem_buf, app.mem_buf_size)!
app.zip.close_entry()
return app.load_texture_from_buffer(app.mem_buf, zip_entry_size)
}

View File

@ -17,7 +17,7 @@ fn main() {
mut app := &App{}
app.serve_static('/favicon.ico', 'favicon.ico')
// Automatically make available known static mime types found in given directory.
os.chdir(os.dir(os.executable()))?
os.chdir(os.dir(os.executable()))!
app.handle_static('assets', true)
vweb.run(app, port)
}

View File

@ -8,7 +8,7 @@ import term
// it connects to the server who will broadcast your messages
// to all other connected clients
fn main() {
mut ws := start_client()?
mut ws := start_client()!
println(term.green('client $ws.id ready'))
println('Write message and enter to send...')
for {
@ -16,7 +16,7 @@ fn main() {
if line == '' {
break
}
ws.write_string(line)?
ws.write_string(line)!
}
ws.close(1000, 'normal') or { println(term.red('panicing $err')) }
unsafe {
@ -24,23 +24,23 @@ fn main() {
}
}
fn start_client() ?&websocket.Client {
mut ws := websocket.new_client('ws://localhost:30000')?
fn start_client() !&websocket.Client {
mut ws := websocket.new_client('ws://localhost:30000')!
// mut ws := websocket.new_client('wss://echo.websocket.org:443')?
// use on_open_ref if you want to send any reference object
ws.on_open(fn (mut ws websocket.Client) ? {
ws.on_open(fn (mut ws websocket.Client) ! {
println(term.green('websocket connected to the server and ready to send messages...'))
})
// use on_error_ref if you want to send any reference object
ws.on_error(fn (mut ws websocket.Client, err string) ? {
ws.on_error(fn (mut ws websocket.Client, err string) ! {
println(term.red('error: $err'))
})
// use on_close_ref if you want to send any reference object
ws.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
ws.on_close(fn (mut ws websocket.Client, code int, reason string) ! {
println(term.green('the connection to the server successfully closed'))
})
// on new messages from other clients, display them in blue text
ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {
if msg.payload.len > 0 {
message := msg.payload.bytestr()
println(term.blue('$message'))

View File

@ -6,24 +6,24 @@ import term
// this server accepts client connections and broadcast all messages to other connected clients
fn main() {
println('press ctrl-c to quit...')
start_server()?
start_server()!
}
fn start_server() ? {
fn start_server() ! {
mut s := websocket.new_server(.ip6, 30000, '')
// Make that in execution test time give time to execute at least one time
s.ping_interval = 100
s.on_connect(fn (mut s websocket.ServerClient) ?bool {
s.on_connect(fn (mut s websocket.ServerClient) !bool {
// Here you can look att the client info and accept or not accept
// just returning a true/false
if s.resource_name != '/' {
return false
}
return true
})?
})!
// on_message_ref, broadcast all incoming messages to all clients except the one sent it
s.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, mut m websocket.Server) ? {
s.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, mut m websocket.Server) ! {
// for _, cli in m.clients {
for i, _ in m.clients {
mut c := m.clients[i]
@ -33,7 +33,7 @@ fn start_server() ? {
}
}, s)
s.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
s.on_close(fn (mut ws websocket.Client, code int, reason string) ! {
println(term.green('client ($ws.id) closed connection'))
})
s.listen() or { println(term.red('error on server listen: $err')) }

View File

@ -6,27 +6,27 @@ import net.websocket
fn main() {
go start_server()
time.sleep(100 * time.millisecond)
start_client()?
start_client()!
}
// start_server starts the websocket server, it receives messages
// and send it back to the client that sent it
fn start_server() ? {
fn start_server() ! {
mut s := websocket.new_server(.ip6, 30000, '')
// Make that in execution test time give time to execute at least one time
s.ping_interval = 100
s.on_connect(fn (mut s websocket.ServerClient) ?bool {
s.on_connect(fn (mut s websocket.ServerClient) !bool {
// Here you can look att the client info and accept or not accept
// just returning a true/false
if s.resource_name != '/' {
return false
}
return true
})?
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
})!
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {
ws.write(msg.payload, msg.opcode) or { panic(err) }
})
s.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
s.on_close(fn (mut ws websocket.Client, code int, reason string) ! {
// println('client ($ws.id) closed connection')
})
s.listen() or { println('error on server listen: $err') }
@ -37,23 +37,23 @@ fn start_server() ? {
// start_client starts the websocket client, it writes a message to
// the server and prints all the messages received
fn start_client() ? {
mut ws := websocket.new_client('ws://localhost:30000')?
fn start_client() ! {
mut ws := websocket.new_client('ws://localhost:30000')!
// mut ws := websocket.new_client('wss://echo.websocket.org:443')?
// use on_open_ref if you want to send any reference object
ws.on_open(fn (mut ws websocket.Client) ? {
ws.on_open(fn (mut ws websocket.Client) ! {
println('open!')
})
// use on_error_ref if you want to send any reference object
ws.on_error(fn (mut ws websocket.Client, err string) ? {
ws.on_error(fn (mut ws websocket.Client, err string) ! {
println('error: $err')
})
// use on_close_ref if you want to send any reference object
ws.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
ws.on_close(fn (mut ws websocket.Client, code int, reason string) ! {
println('closed')
})
// use on_message_ref if you want to send any reference object
ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {
if msg.payload.len > 0 {
message := msg.payload.bytestr()
println('client got type: $msg.opcode payload:\n$message')
@ -72,7 +72,7 @@ fn start_client() ? {
}
}
fn write_echo(mut ws websocket.Client) ? {
fn write_echo(mut ws websocket.Client) ! {
message := 'echo this'
for i := 0; i <= 10; i++ {
// Server will send pings every 30 seconds