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:
parent
6e46933c55
commit
f6844e9766
@ -43,7 +43,7 @@ fn main() {
|
||||
vexe := pref.vexe_path()
|
||||
vroot := os.dir(vexe)
|
||||
util.set_vroot_folder(vroot)
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
cmd := diff.find_working_diff_command() or { '' }
|
||||
mut app := App{
|
||||
diff_cmd: cmd
|
||||
|
@ -15,7 +15,7 @@ const vdir = @VEXEROOT
|
||||
fn main() {
|
||||
dump(fast_dir)
|
||||
dump(vdir)
|
||||
os.chdir(fast_dir)?
|
||||
os.chdir(fast_dir)!
|
||||
if !os.exists('$vdir/v') && !os.is_dir('$vdir/vlib') {
|
||||
println('fast.html generator needs to be located in `v/cmd/tools/fast`')
|
||||
}
|
||||
@ -32,11 +32,11 @@ fn main() {
|
||||
// fetch the last commit's hash
|
||||
commit := exec('git rev-parse HEAD')[..8]
|
||||
if !os.exists('table.html') {
|
||||
os.create('table.html')?
|
||||
os.create('table.html')!
|
||||
}
|
||||
mut table := os.read_file('table.html')?
|
||||
mut table := os.read_file('table.html')!
|
||||
if os.exists('website/index.html') {
|
||||
uploaded_index := os.read_file('website/index.html')?
|
||||
uploaded_index := os.read_file('website/index.html')!
|
||||
if uploaded_index.contains('>$commit<') {
|
||||
println('nothing to benchmark')
|
||||
exit(1)
|
||||
@ -48,7 +48,7 @@ fn main() {
|
||||
|
||||
// build an optimized V
|
||||
println(' Building vprod...')
|
||||
os.chdir(vdir)?
|
||||
os.chdir(vdir)!
|
||||
if os.args.contains('-noprod') {
|
||||
exec('./v -o vprod cmd/v') // for faster debugging
|
||||
} else {
|
||||
@ -82,8 +82,8 @@ fn main() {
|
||||
commit_date := exec('git log -n1 --pretty="format:%at" $commit')
|
||||
date := time.unix(commit_date.int())
|
||||
|
||||
os.chdir(fast_dir)?
|
||||
mut out := os.create('table.html')?
|
||||
os.chdir(fast_dir)!
|
||||
mut out := os.create('table.html')!
|
||||
|
||||
// place the new row on top
|
||||
html_message := message.replace_each(['<', '<', '>', '>'])
|
||||
@ -105,25 +105,25 @@ fn main() {
|
||||
<td>${int(f64(vlines) / f64(diff1) * 1000.0)}</td>
|
||||
</tr>\n' +
|
||||
table.trim_space()
|
||||
out.writeln(table)?
|
||||
out.writeln(table)!
|
||||
out.close()
|
||||
|
||||
// regenerate index.html
|
||||
header := os.read_file('header.html')?
|
||||
footer := os.read_file('footer.html')?
|
||||
mut res := os.create('index.html')?
|
||||
res.writeln(header)?
|
||||
res.writeln(table)?
|
||||
res.writeln(footer)?
|
||||
header := os.read_file('header.html')!
|
||||
footer := os.read_file('footer.html')!
|
||||
mut res := os.create('index.html')!
|
||||
res.writeln(header)!
|
||||
res.writeln(table)!
|
||||
res.writeln(footer)!
|
||||
res.close()
|
||||
|
||||
// upload the result to github pages
|
||||
if os.args.contains('-upload') {
|
||||
println('uploading...')
|
||||
os.chdir('website')?
|
||||
os.chdir('website')!
|
||||
os.execute_or_exit('git checkout gh-pages')
|
||||
os.cp('../index.html', 'index.html')?
|
||||
os.rm('../index.html')?
|
||||
os.cp('../index.html', 'index.html')!
|
||||
os.rm('../index.html')!
|
||||
os.system('git commit -am "update benchmark"')
|
||||
os.system('git push origin gh-pages')
|
||||
}
|
||||
|
@ -7,14 +7,14 @@ fn main() {
|
||||
files := os.args#[1..]
|
||||
if files.len > 0 && files[0].starts_with('@') {
|
||||
lst_path := files[0].all_after('@')
|
||||
listed_files := os.read_file(lst_path)?.split('\n')
|
||||
process_files(listed_files)?
|
||||
listed_files := os.read_file(lst_path)!.split('\n')
|
||||
process_files(listed_files)!
|
||||
return
|
||||
}
|
||||
process_files(files)?
|
||||
process_files(files)!
|
||||
}
|
||||
|
||||
fn process_files(files []string) ? {
|
||||
fn process_files(files []string) ! {
|
||||
mut pref := pref.new_preferences()
|
||||
pref.is_fmt = true
|
||||
pref.skip_warnings = true
|
||||
@ -31,7 +31,7 @@ fn process_files(files []string) ? {
|
||||
continue
|
||||
}
|
||||
sw.restart()
|
||||
s := scanner.new_scanner_file(f, .skip_comments, pref)?
|
||||
s := scanner.new_scanner_file(f, .skip_comments, pref)!
|
||||
f_us := sw.elapsed().microseconds()
|
||||
total_us += f_us
|
||||
total_bytes += s.text.len
|
||||
|
@ -125,7 +125,7 @@ fn main() {
|
||||
should_sync := fp.bool('cache-sync', `s`, false, 'Update the local cache')
|
||||
context.is_bisect = fp.bool('bisect', `b`, false, 'Bisect mode. Use the current commit in the repo where oldv is.')
|
||||
if !should_sync && !context.is_bisect {
|
||||
fp.limit_free_args(1, 1)?
|
||||
fp.limit_free_args(1, 1)!
|
||||
}
|
||||
////
|
||||
context.cleanup = fp.bool('clean', 0, false, 'Clean before running (slower).')
|
||||
|
@ -194,7 +194,7 @@ fn main() {
|
||||
fp.description(tool_description)
|
||||
fp.arguments_description('COMMIT_BEFORE [COMMIT_AFTER]')
|
||||
fp.skip_executable()
|
||||
fp.limit_free_args(1, 2)?
|
||||
fp.limit_free_args(1, 2)!
|
||||
context.vflags = fp.string('vflags', 0, '', 'Additional options to pass to the v commands, for example "-cc tcc"')
|
||||
context.hyperfineopts = fp.string('hyperfine_options', 0, '', 'Additional options passed to hyperfine.
|
||||
${flag.space}For example on linux, you may want to pass:
|
||||
|
@ -143,19 +143,19 @@ const (
|
||||
|
||||
fn main() {
|
||||
mut context := Context{}
|
||||
context.parse_options()?
|
||||
context.parse_options()!
|
||||
context.run()
|
||||
context.show_diff_summary()
|
||||
}
|
||||
|
||||
fn (mut context Context) parse_options() ? {
|
||||
fn (mut context Context) parse_options() ! {
|
||||
mut fp := flag.new_flag_parser(os.args)
|
||||
fp.application(os.file_name(os.executable()))
|
||||
fp.version('0.0.1')
|
||||
fp.description('Repeat command(s) and collect statistics. Note: you have to quote each command, if it contains spaces.')
|
||||
fp.arguments_description('CMD1 CMD2 ...')
|
||||
fp.skip_executable()
|
||||
fp.limit_free_args_to_at_least(1)?
|
||||
fp.limit_free_args_to_at_least(1)!
|
||||
context.count = fp.int('count', `c`, 10, 'Repetition count.')
|
||||
context.series = fp.int('series', `s`, 2, 'Series count. `-s 2 -c 4 a b` => aaaabbbbaaaabbbb, while `-s 3 -c 2 a b` => aabbaabbaabb.')
|
||||
context.warmup = fp.int('warmup', `w`, 2, 'Warmup runs. These are done *only at the start*, and are ignored.')
|
||||
|
@ -60,16 +60,16 @@ fn (result MyResult) matches(gpattern string) MyResult {
|
||||
return result
|
||||
}
|
||||
|
||||
fn create_test(tname string, tcontent string) ?string {
|
||||
fn create_test(tname string, tcontent string) !string {
|
||||
tpath := os.join_path(tdir, tname)
|
||||
os.write_file(tpath, tcontent)?
|
||||
os.write_file(tpath, tcontent)!
|
||||
eprintln('>>>>>>>> tpath: $tpath | tcontent: $tcontent')
|
||||
return os.quoted_path(tpath)
|
||||
}
|
||||
|
||||
fn check_assert_continues_works() ? {
|
||||
os.chdir(tdir)?
|
||||
create_test('assert_continues_option_works_test.v', 'fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false }')?
|
||||
fn check_assert_continues_works() ! {
|
||||
os.chdir(tdir)!
|
||||
create_test('assert_continues_option_works_test.v', 'fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false }')!
|
||||
result := check_fail('$vexe -assert continues assert_continues_option_works_test.v')
|
||||
result.has('assert_continues_option_works_test.v:1: fn test_fail1')
|
||||
result.has('assert_continues_option_works_test.v:2: fn test_fail1')
|
||||
@ -77,7 +77,7 @@ fn check_assert_continues_works() ? {
|
||||
result.has('assert_continues_option_works_test.v:5: fn test_fail2')
|
||||
result.has('> assert 2 == 4').has('> assert 2 == 1').has('> assert 2 == 0')
|
||||
// Check if a test function, tagged with [assert_continues], has the same behaviour, without needing additional options
|
||||
create_test('assert_continues_tag_works_test.v', '[assert_continues]fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false\n assert false }')?
|
||||
create_test('assert_continues_tag_works_test.v', '[assert_continues]fn test_fail1() { assert 2==4\nassert 2==1\nassert 2==0 }\nfn test_ok(){ assert true }\nfn test_fail2() { assert false\n assert false }')!
|
||||
tag_res := check_fail('$vexe assert_continues_tag_works_test.v')
|
||||
tag_res.has('assert_continues_tag_works_test.v:1: fn test_fail1')
|
||||
tag_res.has('assert_continues_tag_works_test.v:2: fn test_fail1')
|
||||
@ -113,23 +113,23 @@ fn main() {
|
||||
os.chdir(os.wd_at_startup) or {}
|
||||
}
|
||||
println('> vroot: $vroot | vexe: $vexe | tdir: $tdir')
|
||||
ok_fpath := create_test('a_single_ok_test.v', 'fn test_ok(){ assert true }')?
|
||||
ok_fpath := create_test('a_single_ok_test.v', 'fn test_ok(){ assert true }')!
|
||||
if check_ok('$vexe $ok_fpath') != '' {
|
||||
exit(1)
|
||||
}
|
||||
check_ok('$vexe test $ok_fpath').matches('*OK*a_single_ok_test.v*')
|
||||
check_ok('$vexe test "$tdir"').matches('*OK*a_single_ok_test.v*')
|
||||
//
|
||||
fail_fpath := create_test('a_single_failing_test.v', 'fn test_fail(){ assert 1 == 2 }')?
|
||||
fail_fpath := create_test('a_single_failing_test.v', 'fn test_fail(){ assert 1 == 2 }')!
|
||||
check_fail('$vexe $fail_fpath').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail')
|
||||
check_fail('$vexe test $fail_fpath').has('> assert 1 == 2').has('a_single_failing_test.v:1: fn test_fail')
|
||||
check_fail('$vexe test "$tdir"').has('> assert 1 == 2')
|
||||
rel_dir := os.join_path(tdir, rand.ulid())
|
||||
os.mkdir(rel_dir)?
|
||||
os.chdir(rel_dir)?
|
||||
os.mkdir(rel_dir)!
|
||||
os.chdir(rel_dir)!
|
||||
relative_path := '..' + os.path_separator + 'a_single_ok_test.v'
|
||||
check_ok('$vexe test ${os.quoted_path(relative_path)}').has('OK').has('a_single_ok_test.v')
|
||||
//
|
||||
check_assert_continues_works()?
|
||||
check_assert_continues_works()!
|
||||
println('> all done')
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ fn main() {
|
||||
}
|
||||
// Git clone c2v
|
||||
if !os.exists(c2v_dir) {
|
||||
os.mkdir_all(vmodules)?
|
||||
os.mkdir_all(vmodules)!
|
||||
println('C2V is not installed. Cloning C2V to $c2v_dir ...')
|
||||
os.chdir(vmodules)?
|
||||
os.chdir(vmodules)!
|
||||
res := os.execute('git clone https://github.com/vlang/c2v')
|
||||
if res.exit_code != 0 {
|
||||
eprintln('Failed to download C2V.')
|
||||
@ -27,7 +27,7 @@ fn main() {
|
||||
}
|
||||
// Compile c2v
|
||||
if !os.exists(c2v_bin) {
|
||||
os.chdir(c2v_dir)?
|
||||
os.chdir(c2v_dir)!
|
||||
println('Compiling c2v ...')
|
||||
res2 := os.execute('${os.quoted_path(vexe)} -o ${os.quoted_path(c2v_bin)} -keepc -g -experimental .')
|
||||
if res2.exit_code != 0 {
|
||||
@ -42,7 +42,7 @@ fn main() {
|
||||
}
|
||||
passed_args := util.args_quote_paths(os.args[2..])
|
||||
// println(passed_args)
|
||||
os.chdir(os.wd_at_startup)?
|
||||
os.chdir(os.wd_at_startup)!
|
||||
c2v_cmd := '${os.quoted_path(c2v_bin)} $passed_args'
|
||||
res := os.system(c2v_cmd)
|
||||
if res != 0 {
|
||||
|
@ -44,7 +44,7 @@ fn main() {
|
||||
for hf in hfields.split(',') {
|
||||
ctx.hide_names[hf] = true
|
||||
}
|
||||
fp.limit_free_args_to_at_least(1)?
|
||||
fp.limit_free_args_to_at_least(1)!
|
||||
rest_of_args := fp.remaining_parameters()
|
||||
for vfile in rest_of_args {
|
||||
file := get_abs_path(vfile)
|
||||
|
@ -73,7 +73,7 @@ fn (context Context) file2v(bname string, fbytes []u8, bn_max int) string {
|
||||
return sb.str()
|
||||
}
|
||||
|
||||
fn (context Context) bname_and_bytes(file string) ?(string, []u8) {
|
||||
fn (context Context) bname_and_bytes(file string) !(string, []u8) {
|
||||
fname := os.file_name(file)
|
||||
fname_escaped := fname.replace_each(['.', '_', '-', '_'])
|
||||
byte_name := '$context.prefix$fname_escaped'.to_lower()
|
||||
@ -130,12 +130,12 @@ fn main() {
|
||||
}
|
||||
max_bname := context.max_bname_len(file_byte_map.keys())
|
||||
if context.write_file.len > 0 {
|
||||
mut out_file := os.create(context.write_file)?
|
||||
out_file.write_string(context.header())?
|
||||
mut out_file := os.create(context.write_file)!
|
||||
out_file.write_string(context.header())!
|
||||
for bname, fbytes in file_byte_map {
|
||||
out_file.write_string(context.file2v(bname, fbytes, max_bname))?
|
||||
out_file.write_string(context.file2v(bname, fbytes, max_bname))!
|
||||
}
|
||||
out_file.write_string(context.footer())?
|
||||
out_file.write_string(context.footer())!
|
||||
} else {
|
||||
print(context.header())
|
||||
for bname, fbytes in file_byte_map {
|
||||
|
@ -23,7 +23,7 @@ fn main() {
|
||||
args_string := os.args[1..].join(' ')
|
||||
vexe := os.getenv('VEXE')
|
||||
vroot := os.dir(vexe)
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
folder := os.join_path('cmd', 'tools')
|
||||
tfolder := os.join_path(vroot, 'cmd', 'tools')
|
||||
main_label := 'Building $folder ...'
|
||||
@ -47,7 +47,7 @@ fn main() {
|
||||
exit(1)
|
||||
}
|
||||
//
|
||||
mut executables := os.ls(session.vtmp_dir)?
|
||||
mut executables := os.ls(session.vtmp_dir)!
|
||||
executables.sort()
|
||||
for texe in executables {
|
||||
tname := texe.replace(os.file_ext(texe), '')
|
||||
|
@ -73,25 +73,25 @@ fn main() {
|
||||
},
|
||||
]
|
||||
|
||||
fn run_individual_test(case BumpTestCase) ? {
|
||||
fn run_individual_test(case BumpTestCase) ! {
|
||||
test_file := os.join_path_single(tfolder, case.file_name)
|
||||
|
||||
os.rm(test_file) or {}
|
||||
os.write_file(test_file, case.contents)?
|
||||
os.write_file(test_file, case.contents)!
|
||||
//
|
||||
os.execute_or_exit('${os.quoted_path(vexe)} bump --patch ${os.quoted_path(test_file)}')
|
||||
patch_lines := os.read_lines(test_file)?
|
||||
patch_lines := os.read_lines(test_file)!
|
||||
assert patch_lines[case.line] == case.expected_patch
|
||||
|
||||
os.execute_or_exit('${os.quoted_path(vexe)} bump --minor ${os.quoted_path(test_file)}')
|
||||
minor_lines := os.read_lines(test_file)?
|
||||
minor_lines := os.read_lines(test_file)!
|
||||
assert minor_lines[case.line] == case.expected_minor
|
||||
|
||||
os.execute_or_exit('${os.quoted_path(vexe)} bump --major ${os.quoted_path(test_file)}')
|
||||
major_lines := os.read_lines(test_file)?
|
||||
major_lines := os.read_lines(test_file)!
|
||||
assert major_lines[case.line] == case.expected_major
|
||||
//
|
||||
os.rm(test_file)?
|
||||
os.rm(test_file)!
|
||||
}
|
||||
|
||||
fn test_all_bump_cases() {
|
||||
|
@ -2,10 +2,10 @@ import os
|
||||
|
||||
const test_path = os.join_path(os.temp_dir(), 'v', 'vcreate_test')
|
||||
|
||||
fn init_and_check() ? {
|
||||
fn init_and_check() ! {
|
||||
os.execute_or_exit('${os.quoted_path(@VEXE)} init')
|
||||
|
||||
assert os.read_file('vcreate_test.v')? == [
|
||||
assert os.read_file('vcreate_test.v')! == [
|
||||
'module main\n',
|
||||
'fn main() {',
|
||||
" println('Hello World!')",
|
||||
@ -13,7 +13,7 @@ fn init_and_check() ? {
|
||||
'',
|
||||
].join_lines()
|
||||
|
||||
assert os.read_file('v.mod')? == [
|
||||
assert os.read_file('v.mod')! == [
|
||||
'Module {',
|
||||
" name: 'vcreate_test'",
|
||||
" description: ''",
|
||||
@ -24,7 +24,7 @@ fn init_and_check() ? {
|
||||
'',
|
||||
].join_lines()
|
||||
|
||||
assert os.read_file('.gitignore')? == [
|
||||
assert os.read_file('.gitignore')! == [
|
||||
'# Binaries for programs and plugins',
|
||||
'main',
|
||||
'vcreate_test',
|
||||
@ -37,7 +37,7 @@ fn init_and_check() ? {
|
||||
'',
|
||||
].join_lines()
|
||||
|
||||
assert os.read_file('.gitattributes')? == [
|
||||
assert os.read_file('.gitattributes')! == [
|
||||
'*.v linguist-language=V text=auto eol=lf',
|
||||
'*.vv linguist-language=V text=auto eol=lf',
|
||||
'*.vsh linguist-language=V text=auto eol=lf',
|
||||
@ -45,7 +45,7 @@ fn init_and_check() ? {
|
||||
'',
|
||||
].join_lines()
|
||||
|
||||
assert os.read_file('.editorconfig')? == [
|
||||
assert os.read_file('.editorconfig')! == [
|
||||
'[*]',
|
||||
'charset = utf-8',
|
||||
'end_of_line = lf',
|
||||
@ -59,28 +59,28 @@ fn init_and_check() ? {
|
||||
].join_lines()
|
||||
}
|
||||
|
||||
fn prepare_test_path() ? {
|
||||
fn prepare_test_path() ! {
|
||||
os.rmdir_all(test_path) or {}
|
||||
os.mkdir_all(test_path) or {}
|
||||
os.chdir(test_path)?
|
||||
os.chdir(test_path)!
|
||||
}
|
||||
|
||||
fn test_v_init() {
|
||||
prepare_test_path()?
|
||||
init_and_check()?
|
||||
prepare_test_path()!
|
||||
init_and_check()!
|
||||
}
|
||||
|
||||
fn test_v_init_in_git_dir() {
|
||||
prepare_test_path()?
|
||||
prepare_test_path()!
|
||||
os.execute_or_exit('git init .')
|
||||
init_and_check()?
|
||||
init_and_check()!
|
||||
}
|
||||
|
||||
fn test_v_init_no_overwrite_gitignore() {
|
||||
prepare_test_path()?
|
||||
os.write_file('.gitignore', 'blah')?
|
||||
prepare_test_path()!
|
||||
os.write_file('.gitignore', 'blah')!
|
||||
os.execute_or_exit('${os.quoted_path(@VEXE)} init')
|
||||
assert os.read_file('.gitignore')? == 'blah'
|
||||
assert os.read_file('.gitignore')! == 'blah'
|
||||
}
|
||||
|
||||
fn test_v_init_no_overwrite_gitattributes_and_editorconfig() {
|
||||
@ -95,13 +95,13 @@ trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
'
|
||||
prepare_test_path()?
|
||||
os.write_file('.gitattributes', git_attributes_content)?
|
||||
os.write_file('.editorconfig', editor_config_content)?
|
||||
prepare_test_path()!
|
||||
os.write_file('.gitattributes', git_attributes_content)!
|
||||
os.write_file('.editorconfig', editor_config_content)!
|
||||
os.execute_or_exit('${os.quoted_path(@VEXE)} init')
|
||||
|
||||
assert os.read_file('.gitattributes')? == git_attributes_content
|
||||
assert os.read_file('.editorconfig')? == editor_config_content
|
||||
assert os.read_file('.gitattributes')! == git_attributes_content
|
||||
assert os.read_file('.editorconfig')! == editor_config_content
|
||||
}
|
||||
|
||||
fn testsuite_end() {
|
||||
|
@ -166,7 +166,7 @@ fn main() {
|
||||
}
|
||||
|
||||
toml_conf := fp.string('toml-config', `t`, default_toml, 'Path or string with TOML configuration')
|
||||
arg_paths := fp.finalize()?
|
||||
arg_paths := fp.finalize()!
|
||||
if show_help {
|
||||
println(fp.usage())
|
||||
exit(0)
|
||||
@ -179,7 +179,7 @@ fn main() {
|
||||
}
|
||||
|
||||
if !os.exists(tmp_dir) {
|
||||
os.mkdir_all(tmp_dir)?
|
||||
os.mkdir_all(tmp_dir)!
|
||||
}
|
||||
|
||||
opt.config = new_config(opt.root_path, toml_conf) or { panic(err) }
|
||||
@ -202,7 +202,7 @@ fn main() {
|
||||
eprintln('Compare paths can not be the same directory `$path`/`$target_path`/`$gen_in_path`')
|
||||
exit(1)
|
||||
}
|
||||
compare_screenshots(opt, gen_in_path, target_path)?
|
||||
compare_screenshots(opt, gen_in_path, target_path)!
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ fn generate_screenshots(mut opt Options, output_path string) ! {
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_screenshots(opt Options, output_path string, target_path string) ? {
|
||||
fn compare_screenshots(opt Options, output_path string, target_path string) ! {
|
||||
mut fails := map[string]string{}
|
||||
mut warns := map[string]string{}
|
||||
for app_config in opt.config.apps {
|
||||
@ -306,14 +306,14 @@ fn compare_screenshots(opt Options, output_path string, target_path string) ? {
|
||||
}
|
||||
first := fails.keys()[0]
|
||||
fail_copy := os.join_path(os.temp_dir(), 'fail.' + first.all_after_last('.'))
|
||||
os.cp(first, fail_copy)?
|
||||
os.cp(first, fail_copy)!
|
||||
eprintln('First failed file `$first` is copied to `$fail_copy`')
|
||||
|
||||
diff_file := os.join_path(os.temp_dir(), os.file_name(first).all_before_last('.') +
|
||||
'.diff.tif')
|
||||
diff_copy := os.join_path(os.temp_dir(), 'diff.tif')
|
||||
if os.is_file(diff_file) {
|
||||
os.cp(diff_file, diff_copy)?
|
||||
os.cp(diff_file, diff_copy)!
|
||||
eprintln('First failed diff file `$diff_file` is copied to `$diff_copy`')
|
||||
eprintln('Removing alpha channel from $diff_copy ...')
|
||||
final_fail_result_file := os.join_path(os.temp_dir(), 'diff.png')
|
||||
|
@ -67,16 +67,16 @@ const json_enc = json2.Encoder{
|
||||
escape_unicode: false
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) check_or_create_vls_folder() ? {
|
||||
fn (upd VlsUpdater) check_or_create_vls_folder() ! {
|
||||
if !os.exists(vls_folder) {
|
||||
upd.log('Creating .vls folder...')
|
||||
os.mkdir(vls_folder)?
|
||||
os.mkdir(vls_folder)!
|
||||
}
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) manifest_config() ?map[string]json2.Any {
|
||||
fn (upd VlsUpdater) manifest_config() !map[string]json2.Any {
|
||||
manifest_buf := os.read_file(vls_manifest_path) or { '{}' }
|
||||
manifest_contents := json2.raw_decode(manifest_buf)?.as_map()
|
||||
manifest_contents := json2.raw_decode(manifest_buf)!.as_map()
|
||||
return manifest_contents
|
||||
}
|
||||
|
||||
@ -88,9 +88,9 @@ fn (upd VlsUpdater) exec_asset_file_name() string {
|
||||
return 'vls_${os_name}_${arch + ext}'
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) update_manifest(new_path string, from_source bool, timestamp time.Time) ? {
|
||||
fn (upd VlsUpdater) update_manifest(new_path string, from_source bool, timestamp time.Time) ! {
|
||||
upd.log('Updating permissions...')
|
||||
os.chmod(new_path, 755)?
|
||||
os.chmod(new_path, 755)!
|
||||
|
||||
upd.log('Updating vls.config.json...')
|
||||
mut manifest := upd.manifest_config() or {
|
||||
@ -103,7 +103,7 @@ fn (upd VlsUpdater) update_manifest(new_path string, from_source bool, timestamp
|
||||
}
|
||||
}
|
||||
|
||||
mut manifest_file := os.open_file(vls_manifest_path, 'w+')?
|
||||
mut manifest_file := os.open_file(vls_manifest_path, 'w+')!
|
||||
defer {
|
||||
manifest_file.close()
|
||||
}
|
||||
@ -112,31 +112,31 @@ fn (upd VlsUpdater) update_manifest(new_path string, from_source bool, timestamp
|
||||
manifest['last_updated'] = json2.Any(timestamp.format_ss())
|
||||
manifest['from_source'] = json2.Any(from_source)
|
||||
|
||||
json_enc.encode_value(manifest, mut manifest_file)?
|
||||
json_enc.encode_value(manifest, mut manifest_file)!
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) init_download_prebuilt() ? {
|
||||
fn (upd VlsUpdater) init_download_prebuilt() ! {
|
||||
if !os.exists(vls_cache_folder) {
|
||||
os.mkdir(vls_cache_folder)?
|
||||
os.mkdir(vls_cache_folder)!
|
||||
}
|
||||
|
||||
if os.exists(vls_bin_folder) {
|
||||
os.rmdir_all(vls_bin_folder)?
|
||||
os.rmdir_all(vls_bin_folder)!
|
||||
}
|
||||
|
||||
os.mkdir(vls_bin_folder)?
|
||||
os.mkdir(vls_bin_folder)!
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) get_last_updated_at() ?time.Time {
|
||||
fn (upd VlsUpdater) get_last_updated_at() !time.Time {
|
||||
if manifest := upd.manifest_config() {
|
||||
if 'last_updated' in manifest {
|
||||
return time.parse(manifest['last_updated'] or { '' }.str()) or { return none }
|
||||
return time.parse(manifest['last_updated'] or { '' }.str()) or { return error('none') }
|
||||
}
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) download_prebuilt() ? {
|
||||
fn (upd VlsUpdater) download_prebuilt() ! {
|
||||
mut has_last_updated_at := true
|
||||
last_updated_at := upd.get_last_updated_at() or {
|
||||
has_last_updated_at = false
|
||||
@ -147,14 +147,15 @@ fn (upd VlsUpdater) download_prebuilt() ? {
|
||||
}
|
||||
|
||||
upd.log('Finding prebuilt executables from GitHub release..')
|
||||
resp := http.get('https://api.github.com/repos/vlang/vls/releases')?
|
||||
releases_json := json2.raw_decode(resp.body)?.arr()
|
||||
resp := http.get('https://api.github.com/repos/vlang/vls/releases')!
|
||||
releases_json := json2.raw_decode(resp.body)!.arr()
|
||||
if releases_json.len == 0 {
|
||||
return error('Unable to fetch latest VLS release data: No releases found.')
|
||||
}
|
||||
|
||||
latest_release := releases_json[0].as_map()
|
||||
assets := latest_release['assets']?.arr()
|
||||
latest_assets := latest_release['assets'] or { return }
|
||||
assets := latest_assets.arr()
|
||||
|
||||
mut checksum_asset_idx := -1
|
||||
mut exec_asset_idx := -1
|
||||
@ -164,7 +165,8 @@ fn (upd VlsUpdater) download_prebuilt() ? {
|
||||
|
||||
for asset_idx, raw_asset in assets {
|
||||
asset := raw_asset.as_map()
|
||||
match asset['name']?.str() {
|
||||
t_asset := asset['name'] or { return }
|
||||
match t_asset.str() {
|
||||
exp_asset_name {
|
||||
exec_asset_idx = asset_idx
|
||||
|
||||
@ -196,13 +198,15 @@ fn (upd VlsUpdater) download_prebuilt() ? {
|
||||
}
|
||||
|
||||
upd.log('Executable found for this system. Downloading...')
|
||||
upd.init_download_prebuilt()?
|
||||
http.download_file(exec_asset['browser_download_url']?.str(), exec_asset_file_path)?
|
||||
upd.init_download_prebuilt()!
|
||||
t_asset := exec_asset['browser_download_url'] or { return }
|
||||
http.download_file(t_asset.str(), exec_asset_file_path)!
|
||||
|
||||
checksum_file_path := os.join_path(vls_cache_folder, 'checksums.txt')
|
||||
checksum_file_asset := assets[checksum_asset_idx].as_map()
|
||||
http.download_file(checksum_file_asset['browser_download_url']?.str(), checksum_file_path)?
|
||||
checksums := os.read_file(checksum_file_path)?.split_into_lines()
|
||||
t_checksum_asset := checksum_file_asset['browser_download_url'] or { return }
|
||||
http.download_file(t_checksum_asset.str(), checksum_file_path)!
|
||||
checksums := os.read_file(checksum_file_path)!.split_into_lines()
|
||||
|
||||
upd.log('Verifying checksum...')
|
||||
for checksum_result in checksums {
|
||||
@ -217,7 +221,7 @@ fn (upd VlsUpdater) download_prebuilt() ? {
|
||||
}
|
||||
|
||||
new_exec_path := os.join_path(vls_bin_folder, exp_asset_name)
|
||||
os.cp(exec_asset_file_path, new_exec_path)?
|
||||
os.cp(exec_asset_file_path, new_exec_path)!
|
||||
upd.update_manifest(new_exec_path, false, asset_last_updated_at) or {
|
||||
upd.log('Unable to update config but the executable was updated successfully.')
|
||||
}
|
||||
@ -231,12 +235,12 @@ fn (upd VlsUpdater) print_new_vls_version(new_vls_exec_path string) {
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_checksum(file_path string) ?string {
|
||||
data := os.read_file(file_path)?
|
||||
fn calculate_checksum(file_path string) !string {
|
||||
data := os.read_file(file_path)!
|
||||
return sha256.hexhash(data)
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) compile_from_source() ? {
|
||||
fn (upd VlsUpdater) compile_from_source() ! {
|
||||
git := os.find_abs_path_of_executable('git') or { return error('Git not found.') }
|
||||
|
||||
if !os.exists(vls_src_folder) {
|
||||
@ -280,22 +284,22 @@ fn (upd VlsUpdater) compile_from_source() ? {
|
||||
upd.print_new_vls_version(exec_path)
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) find_ls_path() ?string {
|
||||
manifest := upd.manifest_config()?
|
||||
fn (upd VlsUpdater) find_ls_path() !string {
|
||||
manifest := upd.manifest_config()!
|
||||
if 'server_path' in manifest {
|
||||
server_path := manifest['server_path']?
|
||||
server_path := manifest['server_path'] or { return error('none') }
|
||||
if server_path is string {
|
||||
if server_path.len == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
return server_path
|
||||
}
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
fn (mut upd VlsUpdater) parse(mut fp flag.FlagParser) ? {
|
||||
fn (mut upd VlsUpdater) parse(mut fp flag.FlagParser) ! {
|
||||
is_json := fp.bool('json', ` `, false, 'Print the output as JSON.')
|
||||
if is_json {
|
||||
upd.output = .json
|
||||
@ -364,7 +368,7 @@ fn (mut upd VlsUpdater) parse(mut fp flag.FlagParser) ? {
|
||||
fp.allow_unknown_args()
|
||||
upd.args << fp.finalize() or { fp.remaining_parameters() }
|
||||
} else {
|
||||
fp.finalize()?
|
||||
fp.finalize()!
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,23 +440,23 @@ fn (upd VlsUpdater) check_installation() {
|
||||
}
|
||||
}
|
||||
|
||||
fn (upd VlsUpdater) run(fp flag.FlagParser) ? {
|
||||
fn (upd VlsUpdater) run(fp flag.FlagParser) ! {
|
||||
if upd.is_check {
|
||||
upd.check_installation()
|
||||
} else if upd.setup_kind != .none_ {
|
||||
upd.check_or_create_vls_folder()?
|
||||
upd.check_or_create_vls_folder()!
|
||||
|
||||
match upd.update_source {
|
||||
.github_releases {
|
||||
upd.download_prebuilt() or {
|
||||
if err.code() == 100 {
|
||||
upd.compile_from_source()?
|
||||
upd.compile_from_source()!
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
.git_repo {
|
||||
upd.compile_from_source()?
|
||||
upd.compile_from_source()!
|
||||
}
|
||||
}
|
||||
} else if upd.pass_to_ls {
|
||||
|
@ -133,7 +133,7 @@ fn (r &Repl) function_call(line string) (bool, FnType) {
|
||||
// TODO(vincenzopalazzo) Remove this fancy check and add a regex
|
||||
fn (r &Repl) is_function_call(line string) bool {
|
||||
return !line.starts_with('[') && line.contains('.') && line.contains('(')
|
||||
&& (line.ends_with(')') || line.ends_with('?'))
|
||||
&& (line.ends_with(')') || line.ends_with('?') || line.ends_with('!'))
|
||||
}
|
||||
|
||||
// Convert the list of modules that we parsed already,
|
||||
|
@ -12,11 +12,11 @@ fn main() {
|
||||
fp.version('0.0.1')
|
||||
fp.description('\nScan .v source files, and print the V tokens contained in them.')
|
||||
fp.arguments_description('PATH [PATH]...')
|
||||
fp.limit_free_args_to_at_least(1)?
|
||||
fp.limit_free_args_to_at_least(1)!
|
||||
pref := pref.new_preferences()
|
||||
mut all_paths := fp.remaining_parameters()
|
||||
for path in all_paths {
|
||||
mut scanner := scanner.new_scanner_file(path, .parse_comments, pref)?
|
||||
mut scanner := scanner.new_scanner_file(path, .parse_comments, pref)!
|
||||
mut tok := token.Token{}
|
||||
for tok.kind != .eof {
|
||||
tok = scanner.scan()
|
||||
|
@ -15,7 +15,7 @@ fn main() {
|
||||
short_v_name := vexe_name.all_before('.')
|
||||
//
|
||||
recompilation.must_be_enabled(vroot, 'Please install V from source, to use `$vexe_name self` .')
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
os.setenv('VCOLORS', 'always', true)
|
||||
args := os.args[1..].filter(it != 'self')
|
||||
jargs := args.join(' ')
|
||||
@ -60,7 +60,7 @@ fn list_folder(short_v_name string, bmessage string, message string) {
|
||||
println(message)
|
||||
}
|
||||
|
||||
fn backup_old_version_and_rename_newer(short_v_name string) ?bool {
|
||||
fn backup_old_version_and_rename_newer(short_v_name string) !bool {
|
||||
mut errors := []string{}
|
||||
short_v_file := if os.user_os() == 'windows' { '${short_v_name}.exe' } else { '$short_v_name' }
|
||||
short_v2_file := if os.user_os() == 'windows' { 'v2.exe' } else { 'v2' }
|
||||
|
@ -11,7 +11,7 @@ fn main() {
|
||||
$if windows {
|
||||
println('Setup freetype...')
|
||||
vroot := os.dir(pref.vexe_path())
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
if os.is_dir(freetype_folder) {
|
||||
println('Thirdparty "freetype" is already installed.')
|
||||
} else {
|
||||
|
@ -122,7 +122,7 @@ fn shader_program_name(shader_file string) string {
|
||||
}
|
||||
|
||||
// validate_shader_file returns an error if `shader_file` isn't valid.
|
||||
fn validate_shader_file(shader_file string) ? {
|
||||
fn validate_shader_file(shader_file string) ! {
|
||||
shader_program := os.read_lines(shader_file) or {
|
||||
return error('shader program at "$shader_file" could not be opened for reading')
|
||||
}
|
||||
@ -140,7 +140,7 @@ fn validate_shader_file(shader_file string) ? {
|
||||
|
||||
// compile_shaders compiles all `*.glsl` files found in `input_path`
|
||||
// to their C header file representatives.
|
||||
fn compile_shaders(opt Options, input_path string) ? {
|
||||
fn compile_shaders(opt Options, input_path string) ! {
|
||||
mut path := os.real_path(input_path)
|
||||
path = path.trim_right('/')
|
||||
if os.is_file(path) {
|
||||
@ -172,12 +172,12 @@ fn compile_shaders(opt Options, input_path string) ? {
|
||||
// Currently sokol-shdc allows for multiple --input flags
|
||||
// - but it's only the last entry that's actually compiled/used
|
||||
// Given this fact - we can only compile one '.glsl' file to one C '.h' header
|
||||
compile_shader(co, shader_file)?
|
||||
compile_shader(co, shader_file)!
|
||||
}
|
||||
}
|
||||
|
||||
// compile_shader compiles `shader_file` to a C header file.
|
||||
fn compile_shader(opt CompileOptions, shader_file string) ? {
|
||||
fn compile_shader(opt CompileOptions, shader_file string) ! {
|
||||
path := opt.invoke_path
|
||||
// The output convetion, for now, is to use the name of the .glsl file
|
||||
mut out_file := os.file_name(shader_file).all_before_last('.') + '.h'
|
||||
@ -231,12 +231,12 @@ fn collect(path string, mut list []string) {
|
||||
|
||||
// ensure_external_tools returns nothing if the external
|
||||
// tools can be setup or is already in place.
|
||||
fn ensure_external_tools(opt Options) ? {
|
||||
fn ensure_external_tools(opt Options) ! {
|
||||
if !os.exists(cache_dir) {
|
||||
os.mkdir_all(cache_dir)?
|
||||
os.mkdir_all(cache_dir)!
|
||||
}
|
||||
if opt.force_update {
|
||||
download_shdc(opt)?
|
||||
download_shdc(opt)!
|
||||
return
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ fn ensure_external_tools(opt Options) ? {
|
||||
return
|
||||
}
|
||||
|
||||
download_shdc(opt)?
|
||||
download_shdc(opt)!
|
||||
}
|
||||
|
||||
// shdc_exe returns an absolute path to the `sokol-shdc` tool.
|
||||
@ -261,7 +261,7 @@ fn shdc_exe() string {
|
||||
}
|
||||
|
||||
// download_shdc downloads the `sokol-shdc` tool to an OS specific cache directory.
|
||||
fn download_shdc(opt Options) ? {
|
||||
fn download_shdc(opt Options) ! {
|
||||
// We want to use the same, runtime, OS type as this tool is invoked on.
|
||||
download_url := shdc_urls[runtime_os] or { '' }
|
||||
if download_url == '' {
|
||||
@ -277,26 +277,26 @@ fn download_shdc(opt Options) ? {
|
||||
}
|
||||
}
|
||||
if os.exists(file) {
|
||||
os.rm(file)?
|
||||
os.rm(file)!
|
||||
}
|
||||
|
||||
mut dtmp_file, dtmp_path := util.temp_file(util.TempFileOptions{ path: os.dir(file) })?
|
||||
mut dtmp_file, dtmp_path := util.temp_file(util.TempFileOptions{ path: os.dir(file) })!
|
||||
dtmp_file.close()
|
||||
if opt.verbose {
|
||||
eprintln('$tool_name downloading sokol-shdc from $download_url')
|
||||
}
|
||||
http.download_file(download_url, dtmp_path) or {
|
||||
os.rm(dtmp_path)?
|
||||
os.rm(dtmp_path)!
|
||||
return error('$tool_name failed to download sokol-shdc needed for shader compiling: $err')
|
||||
}
|
||||
// Make it executable
|
||||
os.chmod(dtmp_path, 0o775)?
|
||||
os.chmod(dtmp_path, 0o775)!
|
||||
// Move downloaded file in place
|
||||
os.mv(dtmp_path, file)?
|
||||
os.mv(dtmp_path, file)!
|
||||
if runtime_os in ['linux', 'macos'] {
|
||||
// Use the .exe file ending to minimize platform friction.
|
||||
os.mv(file, shdc)?
|
||||
os.mv(file, shdc)!
|
||||
}
|
||||
// Update internal version file
|
||||
os.write_file(shdc_version_file, update_to_shdc_version)?
|
||||
os.write_file(shdc_version_file, update_to_shdc_version)!
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ fn main() {
|
||||
context.pref = &pref.Preferences{
|
||||
output_mode: .silent
|
||||
}
|
||||
mut source := os.read_file(context.path)?
|
||||
mut source := os.read_file(context.path)!
|
||||
source = source[..context.cut_index]
|
||||
|
||||
go fn (ms int) {
|
||||
|
@ -6,7 +6,7 @@ import v.pref
|
||||
fn main() {
|
||||
vexe := pref.vexe_path()
|
||||
vroot := os.dir(vexe)
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
os.setenv('VCOLORS', 'always', true)
|
||||
self_idx := os.args.index('tracev')
|
||||
args := os.args[1..self_idx]
|
||||
|
@ -26,7 +26,7 @@ fn new_app() App {
|
||||
fn main() {
|
||||
app := new_app()
|
||||
recompilation.must_be_enabled(app.vroot, 'Please install V from source, to use `v up` .')
|
||||
os.chdir(app.vroot)?
|
||||
os.chdir(app.vroot)!
|
||||
println('Updating V...')
|
||||
app.update_from_master()
|
||||
v_hash := version.githash(false)
|
||||
|
@ -14,7 +14,7 @@ fn find_diff_cmd() string {
|
||||
fn test_vet() {
|
||||
vexe := os.getenv('VEXE')
|
||||
vroot := os.dir(vexe)
|
||||
os.chdir(vroot)?
|
||||
os.chdir(vroot)!
|
||||
test_dir := 'cmd/tools/vvet/tests'
|
||||
tests := get_tests_in_dir(test_dir)
|
||||
fails := check_path(vexe, test_dir, tests)
|
||||
|
@ -318,7 +318,7 @@ fn main() {
|
||||
fp.description('Collect all .v files needed for a compilation, then re-run the compilation when any of the source changes.')
|
||||
fp.arguments_description('[--silent] [--clear] [--ignore .db] [--add /path/to/a/file.v] [run] program.v')
|
||||
fp.allow_unknown_args()
|
||||
fp.limit_free_args_to_at_least(1)?
|
||||
fp.limit_free_args_to_at_least(1)!
|
||||
context.is_worker = fp.bool('vwatchworker', 0, false, 'Internal flag. Used to distinguish vwatch manager and worker processes.')
|
||||
context.silent = fp.bool('silent', `s`, false, 'Be more silent; do not print the watch timestamp before each re-run.')
|
||||
context.clear_terminal = fp.bool('clear', `c`, false, 'Clears the terminal before each re-run.')
|
||||
|
@ -145,7 +145,7 @@ fn maybe_color(term_color fn (string) string, str string) string {
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_v_files(path string, recursive bool) ?[]string {
|
||||
fn collect_v_files(path string, recursive bool) ![]string {
|
||||
if path.len == 0 {
|
||||
return error('path cannot be empty')
|
||||
}
|
||||
@ -153,7 +153,7 @@ fn collect_v_files(path string, recursive bool) ?[]string {
|
||||
return error('path does not exist or is not a directory')
|
||||
}
|
||||
mut all_files := []string{}
|
||||
mut entries := os.ls(path)?
|
||||
mut entries := os.ls(path)!
|
||||
mut local_path_separator := os.path_separator
|
||||
if path.ends_with(os.path_separator) {
|
||||
local_path_separator = ''
|
||||
@ -161,7 +161,7 @@ fn collect_v_files(path string, recursive bool) ?[]string {
|
||||
for entry in entries {
|
||||
file := path + local_path_separator + entry
|
||||
if os.is_dir(file) && !os.is_link(file) && recursive {
|
||||
all_files << collect_v_files(file, recursive)?
|
||||
all_files << collect_v_files(file, recursive)!
|
||||
} else if os.exists(file) && (file.ends_with('.v') || file.ends_with('.vsh')) {
|
||||
all_files << file
|
||||
}
|
||||
@ -169,7 +169,7 @@ fn collect_v_files(path string, recursive bool) ?[]string {
|
||||
return all_files
|
||||
}
|
||||
|
||||
fn resolve_module(path string) ?string {
|
||||
fn resolve_module(path string) !string {
|
||||
if os.is_dir(path) {
|
||||
return path
|
||||
} else if os.is_dir(os.join_path(vmod_dir, path)) {
|
||||
|
@ -1901,8 +1901,8 @@ enum State {
|
||||
}
|
||||
|
||||
// write log file and return number of bytes written
|
||||
fn write_log(s State) ?int {
|
||||
mut f := os.create('log.txt')?
|
||||
fn write_log(s State) !int {
|
||||
mut f := os.create('log.txt')!
|
||||
defer {
|
||||
f.close()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -34,5 +34,5 @@ fn main() {
|
||||
mut server := Server{
|
||||
handler: ExampleHandler{}
|
||||
}
|
||||
server.listen_and_serve()?
|
||||
server.listen_and_serve()
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()!
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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("==================================")
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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'))
|
||||
|
@ -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')) }
|
||||
|
@ -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
|
||||
|
@ -624,7 +624,7 @@ pub fn (s string) u64() u64 {
|
||||
// This method directly exposes the `parse_int` function from `strconv`
|
||||
// as a method on `string`. For more advanced features,
|
||||
// consider calling `strconv.common_parse_int` directly.
|
||||
pub fn (s string) parse_uint(_base int, _bit_size int) ?u64 {
|
||||
pub fn (s string) parse_uint(_base int, _bit_size int) !u64 {
|
||||
return strconv.parse_uint(s, _base, _bit_size)
|
||||
}
|
||||
|
||||
@ -644,7 +644,7 @@ pub fn (s string) parse_uint(_base int, _bit_size int) ?u64 {
|
||||
// This method directly exposes the `parse_uint` function from `strconv`
|
||||
// as a method on `string`. For more advanced features,
|
||||
// consider calling `strconv.common_parse_uint` directly.
|
||||
pub fn (s string) parse_int(_base int, _bit_size int) ?i64 {
|
||||
pub fn (s string) parse_int(_base int, _bit_size int) !i64 {
|
||||
return strconv.parse_int(s, _base, _bit_size)
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ pub fn get_libname(libname string) string {
|
||||
|
||||
// open_opt - loads the dynamic shared object.
|
||||
// Unlike open, open_opt return an option.
|
||||
pub fn open_opt(filename string, flags int) ?voidptr {
|
||||
pub fn open_opt(filename string, flags int) !voidptr {
|
||||
shared_object_handle := open(filename, flags)
|
||||
if shared_object_handle == 0 {
|
||||
e := dlerror()
|
||||
@ -39,7 +39,7 @@ pub fn open_opt(filename string, flags int) ?voidptr {
|
||||
|
||||
// sym_opt returns the address of a symbol in a given shared object, if found.
|
||||
// Unlike sym, sym_opt returns an option.
|
||||
pub fn sym_opt(shared_object_handle voidptr, symbol string) ?voidptr {
|
||||
pub fn sym_opt(shared_object_handle voidptr, symbol string) !voidptr {
|
||||
sym_handle := sym(shared_object_handle, symbol)
|
||||
if sym_handle == 0 {
|
||||
e := dlerror()
|
||||
|
@ -71,7 +71,7 @@ pub fn (af []Flag) str() string {
|
||||
// That structure is created with `mut parser := flag.new_flag_parser(os.args)`,
|
||||
// The returned instance can be further customised by calling various methods,
|
||||
// for specifying the accepted options and their values. The user should finally
|
||||
// call `rest := parser.finalize()?` to get the rest of the non optional arguments
|
||||
// call `rest := parser.finalize()!` to get the rest of the non optional arguments
|
||||
// (if there are any left).
|
||||
pub struct FlagParser {
|
||||
pub:
|
||||
@ -278,7 +278,7 @@ fn (mut fs FlagParser) parse_value(longhand string, shorthand u8) []string {
|
||||
// special: it is allowed to define bool flags without value
|
||||
// -> '--flag' is parsed as true
|
||||
// -> '--flag' is equal to '--flag=true'
|
||||
fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand u8) ?string {
|
||||
fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand u8) !string {
|
||||
{
|
||||
full := '--$longhand'
|
||||
for i, arg in fs.args {
|
||||
@ -317,7 +317,7 @@ fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand u8) ?string {
|
||||
// bool_opt returns an option with the bool value of the given command line flag, named `name`.
|
||||
// It returns an error, when the flag is not given by the user.
|
||||
// This version supports abbreviations.
|
||||
pub fn (mut fs FlagParser) bool_opt(name string, abbr u8, usage string) ?bool {
|
||||
pub fn (mut fs FlagParser) bool_opt(name string, abbr u8, usage string) !bool {
|
||||
mut res := false
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<bool>')
|
||||
@ -354,7 +354,7 @@ pub fn (mut fs FlagParser) int_multi(name string, abbr u8, usage string) []int {
|
||||
// int_opt returns an option with the integer value, associated with the flag in `name`.
|
||||
// When the flag is not given by the user, it returns an error.
|
||||
// This version supports abbreviations.
|
||||
pub fn (mut fs FlagParser) int_opt(name string, abbr u8, usage string) ?int {
|
||||
pub fn (mut fs FlagParser) int_opt(name string, abbr u8, usage string) !int {
|
||||
mut res := 0
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<int>')
|
||||
@ -393,7 +393,7 @@ pub fn (mut fs FlagParser) float_multi(name string, abbr u8, usage string) []f64
|
||||
// float_opt returns an option with the floating point value, associated with the flag in `name`.
|
||||
// When the flag is not given by the user, it returns an error.
|
||||
// This version supports abbreviations.
|
||||
pub fn (mut fs FlagParser) float_opt(name string, abbr u8, usage string) ?f64 {
|
||||
pub fn (mut fs FlagParser) float_opt(name string, abbr u8, usage string) !f64 {
|
||||
mut res := 0.0
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<float>')
|
||||
@ -426,7 +426,7 @@ pub fn (mut fs FlagParser) string_multi(name string, abbr u8, usage string) []st
|
||||
// string_opt returns an option with the string value, associated with the flag in `name`.
|
||||
// When the flag is not given by the user, it returns an error.
|
||||
// This version supports abbreviations.
|
||||
pub fn (mut fs FlagParser) string_opt(name string, abbr u8, usage string) ?string {
|
||||
pub fn (mut fs FlagParser) string_opt(name string, abbr u8, usage string) !string {
|
||||
mut res := ''
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<string>')
|
||||
@ -451,7 +451,7 @@ pub fn (mut fs FlagParser) string(name string, abbr u8, sdefault string, usage s
|
||||
// limit_free_args_to_at_least restricts the list of free arguments (non options) to be
|
||||
// at least `n` in length. If the user gives less free arguments to the program,
|
||||
// the parser will return an error.
|
||||
pub fn (mut fs FlagParser) limit_free_args_to_at_least(n int) ? {
|
||||
pub fn (mut fs FlagParser) limit_free_args_to_at_least(n int) ! {
|
||||
if n > flag.max_args_number {
|
||||
return error('flag.limit_free_args_to_at_least expect n to be smaller than $flag.max_args_number')
|
||||
}
|
||||
@ -464,7 +464,7 @@ pub fn (mut fs FlagParser) limit_free_args_to_at_least(n int) ? {
|
||||
// limit_free_args_to_exactly restricts the list of free arguments (non options) to be
|
||||
// at exactly `n` in length. If the user gives more or less free arguments to the program,
|
||||
// the parser will return an error.
|
||||
pub fn (mut fs FlagParser) limit_free_args_to_exactly(n int) ? {
|
||||
pub fn (mut fs FlagParser) limit_free_args_to_exactly(n int) ! {
|
||||
if n > flag.max_args_number {
|
||||
return error('flag.limit_free_args_to_exactly expect n to be smaller than $flag.max_args_number')
|
||||
}
|
||||
@ -478,7 +478,7 @@ pub fn (mut fs FlagParser) limit_free_args_to_exactly(n int) ? {
|
||||
// limit_free_args restricts the list of free arguments (non options) to be between
|
||||
// `min` and `max` in length. If the user gives more or less free arguments to the program,
|
||||
// the parser will return an error.
|
||||
pub fn (mut fs FlagParser) limit_free_args(min int, max int) ? {
|
||||
pub fn (mut fs FlagParser) limit_free_args(min int, max int) ! {
|
||||
if min > max {
|
||||
return error('flag.limit_free_args expect min < max, got $min >= $max')
|
||||
}
|
||||
@ -578,7 +578,7 @@ pub fn (fs FlagParser) usage() string {
|
||||
|
||||
// find_existing_flag looks up the given flag by name, and returns
|
||||
// it, if it was found in the FlagParser. If it was not, it returns an error.
|
||||
fn (mut fs FlagParser) find_existing_flag(fname string) ?Flag {
|
||||
fn (mut fs FlagParser) find_existing_flag(fname string) !Flag {
|
||||
for f in fs.flags {
|
||||
if f.name == fname {
|
||||
return f
|
||||
@ -614,7 +614,7 @@ fn (mut fs FlagParser) handle_builtin_options() {
|
||||
// The remaining arguments are returned in the same order they are
|
||||
// defined on the command line. If additional flags are found, i.e.
|
||||
// (things starting with '--' or '-'), it returns an error.
|
||||
pub fn (mut fs FlagParser) finalize() ?[]string {
|
||||
pub fn (mut fs FlagParser) finalize() ![]string {
|
||||
fs.handle_builtin_options()
|
||||
mut remaining := fs.args.clone()
|
||||
if !fs.allow_unknown_args {
|
||||
|
@ -153,9 +153,9 @@ fn test_finalize_returns_error_for_unknown_flags_short() {
|
||||
assert finalized.len < 0 // expect error to be returned
|
||||
}
|
||||
|
||||
fn test_allow_to_build_usage_message() ? {
|
||||
fn test_allow_to_build_usage_message() {
|
||||
mut fp := flag.new_flag_parser([])
|
||||
fp.limit_free_args(1, 4)?
|
||||
fp.limit_free_args(1, 4)!
|
||||
fp.application('flag_tool')
|
||||
fp.version('v0.0.0')
|
||||
fp.description('some short information about this tool')
|
||||
@ -194,9 +194,9 @@ fn test_if_no_options_given_usage_message_does_not_contain_options() {
|
||||
assert !fp.usage().contains('Options:')
|
||||
}
|
||||
|
||||
fn test_free_args_could_be_limited() ? {
|
||||
fn test_free_args_could_be_limited() {
|
||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||
fp1.limit_free_args(1, 4)?
|
||||
fp1.limit_free_args(1, 4)!
|
||||
args := fp1.finalize() or {
|
||||
assert false
|
||||
return
|
||||
@ -206,9 +206,9 @@ fn test_free_args_could_be_limited() ? {
|
||||
assert args[2] == 'c'
|
||||
}
|
||||
|
||||
fn test_error_for_to_few_free_args() ? {
|
||||
fn test_error_for_to_few_free_args() {
|
||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||
fp1.limit_free_args(5, 6)?
|
||||
fp1.limit_free_args(5, 6)!
|
||||
args := fp1.finalize() or {
|
||||
assert err.msg().starts_with('Expected at least 5 arguments')
|
||||
return
|
||||
@ -216,9 +216,9 @@ fn test_error_for_to_few_free_args() ? {
|
||||
assert args.len < 0 // expect an error and need to use args
|
||||
}
|
||||
|
||||
fn test_error_for_to_much_free_args() ? {
|
||||
fn test_error_for_to_much_free_args() {
|
||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||
fp1.limit_free_args(1, 2)?
|
||||
fp1.limit_free_args(1, 2)!
|
||||
args := fp1.finalize() or {
|
||||
assert err.msg().starts_with('Expected at most 2 arguments')
|
||||
return
|
||||
@ -226,9 +226,9 @@ fn test_error_for_to_much_free_args() ? {
|
||||
assert args.len < 0 // expect an error and need to use args
|
||||
}
|
||||
|
||||
fn test_could_expect_no_free_args() ? {
|
||||
fn test_could_expect_no_free_args() {
|
||||
mut fp1 := flag.new_flag_parser(['a'])
|
||||
fp1.limit_free_args(0, 0)?
|
||||
fp1.limit_free_args(0, 0)!
|
||||
args := fp1.finalize() or {
|
||||
assert err.msg().starts_with('Expected no arguments')
|
||||
return
|
||||
@ -383,7 +383,7 @@ fn test_optional_flags() {
|
||||
assert b == 'some_default_value'
|
||||
}
|
||||
|
||||
fn test_dashdash_acts_as_parser_full_stop() ? {
|
||||
fn test_dashdash_acts_as_parser_full_stop() {
|
||||
mut fp := flag.new_flag_parser(['-b', '5', '--', '-d', '-x', '-b', '4', '-a', '-c', 'hello',
|
||||
'some', 'other', 'parameters'])
|
||||
a := fp.bool_opt('a-bool-flag', `a`, '') or { false }
|
||||
@ -392,17 +392,17 @@ fn test_dashdash_acts_as_parser_full_stop() ? {
|
||||
assert a == false
|
||||
assert b == 5
|
||||
assert c == 'default'
|
||||
args := fp.finalize()?
|
||||
args := fp.finalize()!
|
||||
assert args.len > 0
|
||||
assert args[0] != '--'
|
||||
assert args == ['-d', '-x', '-b', '4', '-a', '-c', 'hello', 'some', 'other', 'parameters']
|
||||
}
|
||||
|
||||
fn test_dashdash_acts_as_parser_full_stop_dashdash_at_end() ? {
|
||||
fn test_dashdash_acts_as_parser_full_stop_dashdash_at_end() {
|
||||
mut fp := flag.new_flag_parser(['-b', '5', '-b', '4', 'other', 'params', '--'])
|
||||
b := fp.int_multi('an-int-flag', `b`, '')
|
||||
assert b == [5, 4]
|
||||
args := fp.finalize()?
|
||||
args := fp.finalize()!
|
||||
assert args.len > 0
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,9 @@ pub fn (r BufferedReader) end_of_stream() bool {
|
||||
// read_line attempts to read a line from the buffered reader
|
||||
// it will read until it finds a new line character (\n) or
|
||||
// the end of stream
|
||||
pub fn (mut r BufferedReader) read_line() ?string {
|
||||
pub fn (mut r BufferedReader) read_line() !string {
|
||||
if r.end_of_stream {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
mut line := []u8{}
|
||||
for {
|
||||
@ -119,7 +119,7 @@ pub fn (mut r BufferedReader) read_line() ?string {
|
||||
// We are at the end of the stream
|
||||
if line.len == 0 {
|
||||
// we had nothing so return nothing
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
return line.bytestr()
|
||||
}
|
||||
@ -144,5 +144,5 @@ pub fn (mut r BufferedReader) read_line() ?string {
|
||||
line << r.buf[r.offset..i]
|
||||
r.offset = i
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ const (
|
||||
buf_max_len = 1024
|
||||
)
|
||||
|
||||
pub fn cp(mut src Reader, mut dst Writer) ? {
|
||||
pub fn cp(mut src Reader, mut dst Writer) ! {
|
||||
mut buf := []u8{len: io.buf_max_len}
|
||||
for {
|
||||
len := src.read(mut buf) or { break }
|
||||
|
@ -1,13 +1,13 @@
|
||||
import io
|
||||
import os
|
||||
|
||||
fn test_cp() ? {
|
||||
fn test_cp() {
|
||||
mut f := os.open(@FILE) or { panic(err) }
|
||||
defer {
|
||||
f.close()
|
||||
}
|
||||
mut r := io.new_buffered_reader(reader: f)
|
||||
mut stdout := os.stdout()
|
||||
io.cp(mut r, mut stdout)?
|
||||
io.cp(mut r, mut stdout)!
|
||||
assert true
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ fn (mut b Buf) read(mut buf []u8) !int {
|
||||
return n
|
||||
}
|
||||
|
||||
fn (mut w Writ) write(buf []u8) ?int {
|
||||
fn (mut w Writ) write(buf []u8) !int {
|
||||
if buf.len <= 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
w.bytes << buf
|
||||
return buf.len
|
||||
|
@ -22,9 +22,9 @@ pub mut:
|
||||
// written. If any writer fails to write the full length an error is returned
|
||||
// and writing to other writers stops. If any writer returns an error the error
|
||||
// is returned immediately and writing to other writers stops.
|
||||
pub fn (mut m MultiWriter) write(buf []u8) ?int {
|
||||
pub fn (mut m MultiWriter) write(buf []u8) !int {
|
||||
for mut w in m.writers {
|
||||
n := w.write(buf)?
|
||||
n := w.write(buf)!
|
||||
if n != buf.len {
|
||||
return error('io: incomplete write to writer of MultiWriter')
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ pub mut:
|
||||
bytes []u8
|
||||
}
|
||||
|
||||
fn (mut w TestWriter) write(buf []u8) ?int {
|
||||
fn (mut w TestWriter) write(buf []u8) !int {
|
||||
w.bytes << buf
|
||||
return buf.len
|
||||
}
|
||||
@ -53,7 +53,7 @@ pub mut:
|
||||
bytes []u8
|
||||
}
|
||||
|
||||
fn (mut w TestIncompleteWriter) write(buf []u8) ?int {
|
||||
fn (mut w TestIncompleteWriter) write(buf []u8) !int {
|
||||
b := buf[..buf.len - 1]
|
||||
w.bytes << b
|
||||
return b.len
|
||||
@ -61,6 +61,6 @@ fn (mut w TestIncompleteWriter) write(buf []u8) ?int {
|
||||
|
||||
struct TestErrorWriter {}
|
||||
|
||||
fn (mut w TestErrorWriter) write(buf []u8) ?int {
|
||||
fn (mut w TestErrorWriter) write(buf []u8) !int {
|
||||
return error('error writer errored')
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ mut:
|
||||
|
||||
// read_all reads all bytes from a reader until either a 0 length read
|
||||
// or if read_to_end_of_stream is true then the end of the stream (`none`)
|
||||
pub fn read_all(config ReadAllConfig) ?[]u8 {
|
||||
pub fn read_all(config ReadAllConfig) ![]u8 {
|
||||
mut r := config.reader
|
||||
read_till_eof := config.read_to_end_of_stream
|
||||
|
||||
@ -65,11 +65,11 @@ pub fn read_all(config ReadAllConfig) ?[]u8 {
|
||||
|
||||
// read_any reads any available bytes from a reader
|
||||
// (until the reader returns a read of 0 length)
|
||||
pub fn read_any(mut r Reader) ?[]u8 {
|
||||
pub fn read_any(mut r Reader) ![]u8 {
|
||||
mut b := []u8{len: io.read_all_len}
|
||||
mut read := 0
|
||||
for {
|
||||
new_read := r.read(mut b[read..]) or { return none }
|
||||
new_read := r.read(mut b[read..]) or { return error('none') }
|
||||
read += new_read
|
||||
if new_read == 0 {
|
||||
break
|
||||
@ -83,5 +83,5 @@ pub fn read_any(mut r Reader) ?[]u8 {
|
||||
|
||||
// RandomReader represents a stream of data that can be read from at a random location
|
||||
pub interface RandomReader {
|
||||
read_from(pos u64, mut buf []u8) ?int
|
||||
read_from(pos u64, mut buf []u8) !int
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn (mut r ReaderWriterImpl) read(mut buf []u8) !int {
|
||||
return r.r.read(mut buf)
|
||||
}
|
||||
|
||||
pub fn (mut r ReaderWriterImpl) write(buf []u8) ?int {
|
||||
pub fn (mut r ReaderWriterImpl) write(buf []u8) !int {
|
||||
return r.w.write(buf)
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ pub struct TempFileOptions {
|
||||
}
|
||||
|
||||
// temp_file returns an uniquely named, open, writable, `os.File` and it's path
|
||||
pub fn temp_file(tfo TempFileOptions) ?(os.File, string) {
|
||||
pub fn temp_file(tfo TempFileOptions) !(os.File, string) {
|
||||
mut d := tfo.path
|
||||
if d == '' {
|
||||
d = os.temp_dir()
|
||||
@ -47,7 +47,7 @@ pub struct TempDirOptions {
|
||||
}
|
||||
|
||||
// temp_dir returns an uniquely named, writable, directory path
|
||||
pub fn temp_dir(tdo TempFileOptions) ?string {
|
||||
pub fn temp_dir(tdo TempFileOptions) !string {
|
||||
mut d := tdo.path
|
||||
if d == '' {
|
||||
d = os.temp_dir()
|
||||
|
@ -3,11 +3,11 @@ module io
|
||||
// Writer represents a stream of data that can be wrote to
|
||||
pub interface Writer {
|
||||
mut:
|
||||
write(buf []u8) ?int
|
||||
write(buf []u8) !int
|
||||
}
|
||||
|
||||
// RandomWriter represents a stream of data that can be wrote to
|
||||
// at a random pos
|
||||
pub interface RandomWriter {
|
||||
write_to(pos u64, buf []u8) ?int
|
||||
write_to(pos u64, buf []u8) !int
|
||||
}
|
||||
|
@ -44,15 +44,15 @@ fn new_ip(port u16, addr [4]u8) Addr {
|
||||
return a
|
||||
}
|
||||
|
||||
fn temp_unix() ?Addr {
|
||||
fn temp_unix() !Addr {
|
||||
// create a temp file to get a filename
|
||||
// close it
|
||||
// remove it
|
||||
// then reuse the filename
|
||||
mut file, filename := util.temp_file()?
|
||||
mut file, filename := util.temp_file()!
|
||||
file.close()
|
||||
os.rm(filename)?
|
||||
addrs := resolve_addrs(filename, .unix, .udp)?
|
||||
os.rm(filename)!
|
||||
addrs := resolve_addrs(filename, .unix, .udp)!
|
||||
return addrs[0]
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ fn (a Addr) len() u32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_addrs(addr string, family AddrFamily, @type SocketType) ?[]Addr {
|
||||
pub fn resolve_addrs(addr string, family AddrFamily, @type SocketType) ![]Addr {
|
||||
match family {
|
||||
.ip, .ip6, .unspec {
|
||||
return resolve_ipaddrs(addr, family, @type)
|
||||
@ -143,9 +143,9 @@ pub fn resolve_addrs(addr string, family AddrFamily, @type SocketType) ?[]Addr {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_addrs_fuzzy(addr string, @type SocketType) ?[]Addr {
|
||||
pub fn resolve_addrs_fuzzy(addr string, @type SocketType) ![]Addr {
|
||||
if addr.len == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// Use a small heuristic to figure out what address family this is
|
||||
@ -160,8 +160,8 @@ pub fn resolve_addrs_fuzzy(addr string, @type SocketType) ?[]Addr {
|
||||
return resolve_addrs(addr, .unix, @type)
|
||||
}
|
||||
|
||||
pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ?[]Addr {
|
||||
address, port := split_address(addr)?
|
||||
pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr {
|
||||
address, port := split_address(addr)!
|
||||
|
||||
if addr[0] == `:` {
|
||||
match family {
|
||||
@ -191,10 +191,10 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ?[]Addr {
|
||||
|
||||
// This might look silly but is recommended by MSDN
|
||||
$if windows {
|
||||
socket_error(0 - C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results))?
|
||||
socket_error(0 - C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results))!
|
||||
} $else {
|
||||
x := C.getaddrinfo(&char(address.str), &char(sport.str), &hints, &results)
|
||||
wrap_error(x)?
|
||||
wrap_error(x)!
|
||||
}
|
||||
|
||||
defer {
|
||||
|
@ -17,18 +17,18 @@ pub const no_timeout = time.Duration(0)
|
||||
pub const infinite_timeout = time.infinite
|
||||
|
||||
// Shutdown shutsdown a socket and closes it
|
||||
fn shutdown(handle int) ? {
|
||||
fn shutdown(handle int) ! {
|
||||
$if windows {
|
||||
C.shutdown(handle, C.SD_BOTH)
|
||||
socket_error(C.closesocket(handle))?
|
||||
socket_error(C.closesocket(handle))!
|
||||
} $else {
|
||||
C.shutdown(handle, C.SHUT_RDWR)
|
||||
socket_error(C.close(handle))?
|
||||
socket_error(C.close(handle))!
|
||||
}
|
||||
}
|
||||
|
||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||
fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||
set := C.fd_set{}
|
||||
|
||||
C.FD_ZERO(&set)
|
||||
@ -52,13 +52,13 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
|
||||
match test {
|
||||
.read {
|
||||
socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.write {
|
||||
socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.except {
|
||||
socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))?
|
||||
socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn select_deadline(handle int, test Select, deadline time.Time) ?bool {
|
||||
fn select_deadline(handle int, test Select, deadline time.Time) !bool {
|
||||
// if we have a 0 deadline here then the timeout that was passed was infinite...
|
||||
infinite := deadline.unix_time() == 0
|
||||
for infinite || time.now() <= deadline {
|
||||
@ -89,7 +89,7 @@ fn select_deadline(handle int, test Select, deadline time.Time) ?bool {
|
||||
}
|
||||
|
||||
// wait_for_common wraps the common wait code
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ! {
|
||||
// Convert timeouts to deadlines
|
||||
real_deadline := if timeout == net.infinite_timeout {
|
||||
time.unix(0)
|
||||
@ -104,7 +104,7 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
|
||||
time.now().add(timeout)
|
||||
}
|
||||
|
||||
ready := select_deadline(handle, test, real_deadline)?
|
||||
ready := select_deadline(handle, test, real_deadline)!
|
||||
|
||||
if ready {
|
||||
return
|
||||
@ -114,11 +114,11 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
|
||||
}
|
||||
|
||||
// wait_for_write waits for a write io operation to be available
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ! {
|
||||
return wait_for_common(handle, deadline, timeout, .write)
|
||||
}
|
||||
|
||||
// wait_for_read waits for a read io operation to be available
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ! {
|
||||
return wait_for_common(handle, deadline, timeout, .read)
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ pub const (
|
||||
err_connection_refused = error_with_code('net: connection refused', errors_base + 10)
|
||||
)
|
||||
|
||||
pub fn socket_error_message(potential_code int, s string) ?int {
|
||||
pub fn socket_error_message(potential_code int, s string) !int {
|
||||
return socket_error(potential_code) or { return error('$err.msg(); $s') }
|
||||
}
|
||||
|
||||
pub fn socket_error(potential_code int) ?int {
|
||||
pub fn socket_error(potential_code int) !int {
|
||||
$if windows {
|
||||
if potential_code < 0 {
|
||||
last_error_int := C.WSAGetLastError()
|
||||
@ -43,7 +43,7 @@ pub fn socket_error(potential_code int) ?int {
|
||||
return potential_code
|
||||
}
|
||||
|
||||
pub fn wrap_error(error_code int) ? {
|
||||
pub fn wrap_error(error_code int) ! {
|
||||
if error_code == 0 {
|
||||
return
|
||||
}
|
||||
@ -59,17 +59,17 @@ pub fn wrap_error(error_code int) ? {
|
||||
// connection termination and returns none
|
||||
// e.g. res := wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))?
|
||||
[inline]
|
||||
fn wrap_read_result(result int) ?int {
|
||||
fn wrap_read_result(result int) !int {
|
||||
if result == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn wrap_write_result(result int) ?int {
|
||||
fn wrap_write_result(result int) !int {
|
||||
if result == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ mut:
|
||||
port int
|
||||
}
|
||||
|
||||
fn (mut dtp DTP) read() ?[]u8 {
|
||||
fn (mut dtp DTP) read() ![]u8 {
|
||||
mut data := []u8{}
|
||||
mut buf := []u8{len: 1024}
|
||||
for {
|
||||
@ -75,15 +75,15 @@ pub fn new() FTP {
|
||||
return f
|
||||
}
|
||||
|
||||
fn (mut zftp FTP) write(data string) ?int {
|
||||
fn (mut zftp FTP) write(data string) !int {
|
||||
$if debug {
|
||||
println('FTP.v >>> $data')
|
||||
}
|
||||
return zftp.conn.write('$data\r\n'.bytes())
|
||||
}
|
||||
|
||||
fn (mut zftp FTP) read() ?(int, string) {
|
||||
mut data := zftp.reader.read_line()?
|
||||
fn (mut zftp FTP) read() !(int, string) {
|
||||
mut data := zftp.reader.read_line()!
|
||||
$if debug {
|
||||
println('FTP.v <<< $data')
|
||||
}
|
||||
@ -93,7 +93,7 @@ fn (mut zftp FTP) read() ?(int, string) {
|
||||
code := data[..3].int()
|
||||
if data[3] == `-` {
|
||||
for {
|
||||
data = zftp.reader.read_line()?
|
||||
data = zftp.reader.read_line()!
|
||||
if data[..3].int() == code && data[3] != `-` {
|
||||
break
|
||||
}
|
||||
@ -103,10 +103,10 @@ fn (mut zftp FTP) read() ?(int, string) {
|
||||
}
|
||||
|
||||
// connect establishes an FTP connection to the host at `ip` port 21.
|
||||
pub fn (mut zftp FTP) connect(ip string) ?bool {
|
||||
zftp.conn = net.dial_tcp('$ip:21')?
|
||||
pub fn (mut zftp FTP) connect(ip string) !bool {
|
||||
zftp.conn = net.dial_tcp('$ip:21')!
|
||||
zftp.reader = io.new_buffered_reader(reader: zftp.conn)
|
||||
code, _ := zftp.read()?
|
||||
code, _ := zftp.read()!
|
||||
if code == ftp.connected {
|
||||
return true
|
||||
}
|
||||
@ -114,14 +114,14 @@ pub fn (mut zftp FTP) connect(ip string) ?bool {
|
||||
}
|
||||
|
||||
// login sends the "USER `user`" and "PASS `passwd`" commands to the remote host.
|
||||
pub fn (mut zftp FTP) login(user string, passwd string) ?bool {
|
||||
pub fn (mut zftp FTP) login(user string, passwd string) !bool {
|
||||
zftp.write('USER $user') or {
|
||||
$if debug {
|
||||
println('ERROR sending user')
|
||||
}
|
||||
return false
|
||||
}
|
||||
mut code, _ := zftp.read()?
|
||||
mut code, _ := zftp.read()!
|
||||
if code == ftp.logged_in {
|
||||
return true
|
||||
}
|
||||
@ -134,7 +134,7 @@ pub fn (mut zftp FTP) login(user string, passwd string) ?bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
code, _ = zftp.read()?
|
||||
code, _ = zftp.read()!
|
||||
if code == ftp.logged_in {
|
||||
return true
|
||||
}
|
||||
@ -142,15 +142,15 @@ pub fn (mut zftp FTP) login(user string, passwd string) ?bool {
|
||||
}
|
||||
|
||||
// close closes the FTP connection.
|
||||
pub fn (mut zftp FTP) close() ? {
|
||||
zftp.write('QUIT')?
|
||||
zftp.conn.close()?
|
||||
pub fn (mut zftp FTP) close() ! {
|
||||
zftp.write('QUIT')!
|
||||
zftp.conn.close()!
|
||||
}
|
||||
|
||||
// pwd returns the current working directory on the remote host for the logged in user.
|
||||
pub fn (mut zftp FTP) pwd() ?string {
|
||||
zftp.write('PWD')?
|
||||
_, data := zftp.read()?
|
||||
pub fn (mut zftp FTP) pwd() !string {
|
||||
zftp.write('PWD')!
|
||||
_, data := zftp.read()!
|
||||
spl := data.split('"') // "
|
||||
if spl.len >= 2 {
|
||||
return spl[1]
|
||||
@ -159,9 +159,9 @@ pub fn (mut zftp FTP) pwd() ?string {
|
||||
}
|
||||
|
||||
// cd changes the current working directory to the specified remote directory `dir`.
|
||||
pub fn (mut zftp FTP) cd(dir string) ? {
|
||||
pub fn (mut zftp FTP) cd(dir string) ! {
|
||||
zftp.write('CWD $dir') or { return }
|
||||
mut code, mut data := zftp.read()?
|
||||
mut code, mut data := zftp.read()!
|
||||
match int(code) {
|
||||
ftp.denied {
|
||||
$if debug {
|
||||
@ -169,7 +169,7 @@ pub fn (mut zftp FTP) cd(dir string) ? {
|
||||
}
|
||||
}
|
||||
ftp.complete {
|
||||
code, data = zftp.read()?
|
||||
code, data = zftp.read()!
|
||||
}
|
||||
else {}
|
||||
}
|
||||
@ -178,7 +178,7 @@ pub fn (mut zftp FTP) cd(dir string) ? {
|
||||
}
|
||||
}
|
||||
|
||||
fn new_dtp(msg string) ?&DTP {
|
||||
fn new_dtp(msg string) !&DTP {
|
||||
if !is_dtp_message_valid(msg) {
|
||||
return error('Bad message')
|
||||
}
|
||||
@ -194,32 +194,32 @@ fn new_dtp(msg string) ?&DTP {
|
||||
return dtp
|
||||
}
|
||||
|
||||
fn (mut zftp FTP) pasv() ?&DTP {
|
||||
zftp.write('PASV')?
|
||||
code, data := zftp.read()?
|
||||
fn (mut zftp FTP) pasv() !&DTP {
|
||||
zftp.write('PASV')!
|
||||
code, data := zftp.read()!
|
||||
$if debug {
|
||||
println('pass: $data')
|
||||
}
|
||||
if code != ftp.passive_mode {
|
||||
return error('pasive mode not allowed')
|
||||
}
|
||||
dtp := new_dtp(data)?
|
||||
dtp := new_dtp(data)!
|
||||
return dtp
|
||||
}
|
||||
|
||||
// dir returns a list of the files in the current working directory.
|
||||
pub fn (mut zftp FTP) dir() ?[]string {
|
||||
pub fn (mut zftp FTP) dir() ![]string {
|
||||
mut dtp := zftp.pasv() or { return error('Cannot establish data connection') }
|
||||
zftp.write('LIST')?
|
||||
code, _ := zftp.read()?
|
||||
zftp.write('LIST')!
|
||||
code, _ := zftp.read()!
|
||||
if code == ftp.denied {
|
||||
return error('`LIST` denied')
|
||||
}
|
||||
if code != ftp.open_data_connection {
|
||||
return error('Data channel empty')
|
||||
}
|
||||
list_dir := dtp.read()?
|
||||
result, _ := zftp.read()?
|
||||
list_dir := dtp.read()!
|
||||
result, _ := zftp.read()!
|
||||
if result != ftp.close_data_connection {
|
||||
println('`LIST` not ok')
|
||||
}
|
||||
@ -235,17 +235,17 @@ pub fn (mut zftp FTP) dir() ?[]string {
|
||||
}
|
||||
|
||||
// get retrieves `file` from the remote host.
|
||||
pub fn (mut zftp FTP) get(file string) ?[]u8 {
|
||||
pub fn (mut zftp FTP) get(file string) ![]u8 {
|
||||
mut dtp := zftp.pasv() or { return error('Cannot stablish data connection') }
|
||||
zftp.write('RETR $file')?
|
||||
code, _ := zftp.read()?
|
||||
zftp.write('RETR $file')!
|
||||
code, _ := zftp.read()!
|
||||
if code == ftp.denied {
|
||||
return error('Permission denied')
|
||||
}
|
||||
if code != ftp.open_data_connection {
|
||||
return error('Data connection not ready')
|
||||
}
|
||||
blob := dtp.read()?
|
||||
blob := dtp.read()!
|
||||
dtp.close()
|
||||
return blob
|
||||
}
|
||||
|
@ -11,17 +11,17 @@ fn test_ftp_cleint() {
|
||||
ftp_client_test_inside() or { panic(err) }
|
||||
}
|
||||
|
||||
fn ftp_client_test_inside() ? {
|
||||
fn ftp_client_test_inside() ! {
|
||||
mut zftp := ftp.new()
|
||||
// eprintln(zftp)
|
||||
defer {
|
||||
zftp.close() or { panic(err) }
|
||||
}
|
||||
connect_result := zftp.connect('ftp.redhat.com')?
|
||||
connect_result := zftp.connect('ftp.redhat.com')!
|
||||
assert connect_result
|
||||
login_result := zftp.login('ftp', 'ftp')?
|
||||
login_result := zftp.login('ftp', 'ftp')!
|
||||
assert login_result
|
||||
pwd := zftp.pwd()?
|
||||
pwd := zftp.pwd()!
|
||||
assert pwd.len > 0
|
||||
zftp.cd('/') or {
|
||||
assert false
|
||||
|
@ -6,14 +6,14 @@ module http
|
||||
import net.ssl
|
||||
import strings
|
||||
|
||||
fn (req &Request) ssl_do(port int, method Method, host_name string, path string) ?Response {
|
||||
fn (req &Request) ssl_do(port int, method Method, host_name string, path string) !Response {
|
||||
mut ssl_conn := ssl.new_ssl_conn(
|
||||
verify: req.verify
|
||||
cert: req.cert
|
||||
cert_key: req.cert_key
|
||||
validate: req.validate
|
||||
in_memory_verification: req.in_memory_verification
|
||||
)?
|
||||
)!
|
||||
ssl_conn.dial(host_name, port) or { return err }
|
||||
|
||||
req_headers := req.build_request_headers(method, host_name, path)
|
||||
@ -38,7 +38,7 @@ fn (req &Request) ssl_do(port int, method Method, host_name string, path string)
|
||||
}
|
||||
unsafe { content.write_ptr(bp, len) }
|
||||
}
|
||||
ssl_conn.shutdown()?
|
||||
ssl_conn.shutdown()!
|
||||
response_text := content.str()
|
||||
$if trace_http_response ? {
|
||||
eprintln('< $response_text')
|
||||
|
@ -13,7 +13,7 @@ $if gcboehm ? {
|
||||
|
||||
fn C.new_tls_context() C.TlsContext
|
||||
|
||||
fn (req &Request) ssl_do(port int, method Method, host_name string, path string) ?Response {
|
||||
fn (req &Request) ssl_do(port int, method Method, host_name string, path string) !Response {
|
||||
mut ctx := C.new_tls_context()
|
||||
C.vschannel_init(&ctx)
|
||||
mut buff := unsafe { malloc_noscan(C.vsc_init_resp_buff_size) }
|
||||
|
@ -294,7 +294,7 @@ pub fn is_cookie_domain_name(_s string) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
fn parse_cookie_value(_raw string, allow_double_quote bool) ?string {
|
||||
fn parse_cookie_value(_raw string, allow_double_quote bool) !string {
|
||||
mut raw := _raw
|
||||
// Strip the quotes, if present
|
||||
if allow_double_quote && raw.len > 1 && raw[0] == `"` && raw[raw.len - 1] == `"` {
|
||||
@ -320,7 +320,7 @@ fn is_cookie_name_valid(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
fn parse_cookie(line string) ?Cookie {
|
||||
fn parse_cookie(line string) !Cookie {
|
||||
mut parts := line.trim_space().split(';')
|
||||
if parts.len == 1 && parts[0] == '' {
|
||||
return error('malformed cookie')
|
||||
|
@ -7,7 +7,7 @@ import os
|
||||
|
||||
// download_file retrieves a document from the URL `url`,
|
||||
// and saves it in the output file path `out_file_path`.
|
||||
pub fn download_file(url string, out_file_path string) ? {
|
||||
pub fn download_file(url string, out_file_path string) ! {
|
||||
$if debug_http ? {
|
||||
println('http.download_file url=$url out_file_path=$out_file_path')
|
||||
}
|
||||
@ -18,7 +18,7 @@ pub fn download_file(url string, out_file_path string) ? {
|
||||
$if debug_http ? {
|
||||
println('http.download_file saving $s.body.len bytes')
|
||||
}
|
||||
os.write_file(out_file_path, s.body)?
|
||||
os.write_file(out_file_path, s.body)!
|
||||
}
|
||||
|
||||
// TODO: implement download_file_with_progress
|
||||
|
@ -363,9 +363,9 @@ pub fn new_header_from_map(kvs map[CommonHeader]string) Header {
|
||||
}
|
||||
|
||||
// new_custom_header_from_map creates a Header from string key value pairs
|
||||
pub fn new_custom_header_from_map(kvs map[string]string) ?Header {
|
||||
pub fn new_custom_header_from_map(kvs map[string]string) !Header {
|
||||
mut h := new_header()
|
||||
h.add_custom_map(kvs)?
|
||||
h.add_custom_map(kvs)!
|
||||
return h
|
||||
}
|
||||
|
||||
@ -378,8 +378,8 @@ pub fn (mut h Header) add(key CommonHeader, value string) {
|
||||
|
||||
// add_custom appends a value to a custom header key. This function will
|
||||
// return an error if the key contains invalid header characters.
|
||||
pub fn (mut h Header) add_custom(key string, value string) ? {
|
||||
is_valid(key)?
|
||||
pub fn (mut h Header) add_custom(key string, value string) ! {
|
||||
is_valid(key)!
|
||||
h.data[key] << value
|
||||
h.add_key(key)
|
||||
}
|
||||
@ -392,9 +392,9 @@ pub fn (mut h Header) add_map(kvs map[CommonHeader]string) {
|
||||
}
|
||||
|
||||
// add_custom_map appends the value for each custom header key.
|
||||
pub fn (mut h Header) add_custom_map(kvs map[string]string) ? {
|
||||
pub fn (mut h Header) add_custom_map(kvs map[string]string) ! {
|
||||
for k, v in kvs {
|
||||
h.add_custom(k, v)?
|
||||
h.add_custom(k, v)!
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,8 +410,8 @@ pub fn (mut h Header) set(key CommonHeader, value string) {
|
||||
// function will clear any other values that exist for the header. This
|
||||
// function will return an error if the key contains invalid header
|
||||
// characters.
|
||||
pub fn (mut h Header) set_custom(key string, value string) ? {
|
||||
is_valid(key)?
|
||||
pub fn (mut h Header) set_custom(key string, value string) ! {
|
||||
is_valid(key)!
|
||||
h.data[key] = [value]
|
||||
h.add_key(key)
|
||||
}
|
||||
@ -479,37 +479,37 @@ pub fn (h Header) contains_custom(key string, flags HeaderQueryConfig) bool {
|
||||
|
||||
// get gets the first value for the CommonHeader, or none if the key
|
||||
// does not exist.
|
||||
pub fn (h Header) get(key CommonHeader) ?string {
|
||||
pub fn (h Header) get(key CommonHeader) !string {
|
||||
return h.get_custom(key.str())
|
||||
}
|
||||
|
||||
// get_custom gets the first value for the custom header, or none if
|
||||
// the key does not exist.
|
||||
pub fn (h Header) get_custom(key string, flags HeaderQueryConfig) ?string {
|
||||
pub fn (h Header) get_custom(key string, flags HeaderQueryConfig) !string {
|
||||
mut data_key := key
|
||||
if !flags.exact {
|
||||
// get the first key from key metadata
|
||||
k := key.to_lower()
|
||||
if h.keys[k].len == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
data_key = h.keys[k][0]
|
||||
}
|
||||
if h.data[data_key].len == 0 {
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
return h.data[data_key][0]
|
||||
}
|
||||
|
||||
// starting_with gets the first header starting with key, or none if
|
||||
// the key does not exist.
|
||||
pub fn (h Header) starting_with(key string) ?string {
|
||||
pub fn (h Header) starting_with(key string) !string {
|
||||
for k, _ in h.data {
|
||||
if k.starts_with(key) {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// values gets all values for the CommonHeader.
|
||||
@ -642,7 +642,7 @@ pub fn (err HeaderKeyError) code() int {
|
||||
}
|
||||
|
||||
// is_valid checks if the header token contains all valid bytes
|
||||
fn is_valid(header string) ? {
|
||||
fn is_valid(header string) ! {
|
||||
for _, c in header {
|
||||
if int(c) >= 128 || !is_token(c) {
|
||||
return IError(HeaderKeyError{
|
||||
@ -676,7 +676,7 @@ pub fn (h Header) str() string {
|
||||
}
|
||||
|
||||
// parse_headers parses a newline delimited string into a Header struct
|
||||
fn parse_headers(s string) ?Header {
|
||||
fn parse_headers(s string) !Header {
|
||||
mut h := new_header()
|
||||
mut last_key := ''
|
||||
mut last_value := ''
|
||||
@ -689,15 +689,15 @@ fn parse_headers(s string) ?Header {
|
||||
last_value += ' ${line.trim(' \t')}'
|
||||
continue
|
||||
} else if last_key != '' {
|
||||
h.add_custom(last_key, last_value)?
|
||||
h.add_custom(last_key, last_value)!
|
||||
}
|
||||
last_key, last_value = parse_header(line)?
|
||||
last_key, last_value = parse_header(line)!
|
||||
}
|
||||
h.add_custom(last_key, last_value)?
|
||||
h.add_custom(last_key, last_value)!
|
||||
return h
|
||||
}
|
||||
|
||||
fn parse_header(s string) ?(string, string) {
|
||||
fn parse_header(s string) !(string, string) {
|
||||
if !s.contains(':') {
|
||||
return error('missing colon in header')
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ pub mut:
|
||||
allow_redirect bool = true // whether to allow redirect
|
||||
}
|
||||
|
||||
pub fn new_request(method Method, url_ string, data string) ?Request {
|
||||
pub fn new_request(method Method, url_ string, data string) !Request {
|
||||
url := if method == .get && !url_.contains('?') { url_ + '?' + data } else { url_ }
|
||||
// println('new req() method=$method url="$url" dta="$data"')
|
||||
return Request{
|
||||
@ -47,12 +47,12 @@ pub fn new_request(method Method, url_ string, data string) ?Request {
|
||||
}
|
||||
|
||||
// get sends a GET HTTP request to the URL
|
||||
pub fn get(url string) ?Response {
|
||||
pub fn get(url string) !Response {
|
||||
return fetch(method: .get, url: url)
|
||||
}
|
||||
|
||||
// post sends a POST HTTP request to the URL with a string data
|
||||
pub fn post(url string, data string) ?Response {
|
||||
pub fn post(url string, data string) !Response {
|
||||
return fetch(
|
||||
method: .post
|
||||
url: url
|
||||
@ -62,7 +62,7 @@ pub fn post(url string, data string) ?Response {
|
||||
}
|
||||
|
||||
// post_json sends a POST HTTP request to the URL with a JSON data
|
||||
pub fn post_json(url string, data string) ?Response {
|
||||
pub fn post_json(url string, data string) !Response {
|
||||
return fetch(
|
||||
method: .post
|
||||
url: url
|
||||
@ -72,7 +72,7 @@ pub fn post_json(url string, data string) ?Response {
|
||||
}
|
||||
|
||||
// post_form sends a POST HTTP request to the URL with X-WWW-FORM-URLENCODED data
|
||||
pub fn post_form(url string, data map[string]string) ?Response {
|
||||
pub fn post_form(url string, data map[string]string) !Response {
|
||||
return fetch(
|
||||
method: .post
|
||||
url: url
|
||||
@ -90,7 +90,7 @@ pub mut:
|
||||
}
|
||||
|
||||
// post_multipart_form sends a POST HTTP request to the URL with multipart form data
|
||||
pub fn post_multipart_form(url string, conf PostMultipartFormConfig) ?Response {
|
||||
pub fn post_multipart_form(url string, conf PostMultipartFormConfig) !Response {
|
||||
body, boundary := multipart_form_body(conf.form, conf.files)
|
||||
mut header := conf.header
|
||||
header.set(.content_type, 'multipart/form-data; boundary="$boundary"')
|
||||
@ -103,7 +103,7 @@ pub fn post_multipart_form(url string, conf PostMultipartFormConfig) ?Response {
|
||||
}
|
||||
|
||||
// put sends a PUT HTTP request to the URL with a string data
|
||||
pub fn put(url string, data string) ?Response {
|
||||
pub fn put(url string, data string) !Response {
|
||||
return fetch(
|
||||
method: .put
|
||||
url: url
|
||||
@ -113,7 +113,7 @@ pub fn put(url string, data string) ?Response {
|
||||
}
|
||||
|
||||
// patch sends a PATCH HTTP request to the URL with a string data
|
||||
pub fn patch(url string, data string) ?Response {
|
||||
pub fn patch(url string, data string) !Response {
|
||||
return fetch(
|
||||
method: .patch
|
||||
url: url
|
||||
@ -123,17 +123,17 @@ pub fn patch(url string, data string) ?Response {
|
||||
}
|
||||
|
||||
// head sends a HEAD HTTP request to the URL
|
||||
pub fn head(url string) ?Response {
|
||||
pub fn head(url string) !Response {
|
||||
return fetch(method: .head, url: url)
|
||||
}
|
||||
|
||||
// delete sends a DELETE HTTP request to the URL
|
||||
pub fn delete(url string) ?Response {
|
||||
pub fn delete(url string) !Response {
|
||||
return fetch(method: .delete, url: url)
|
||||
}
|
||||
|
||||
// fetch sends an HTTP request to the URL with the given method and configurations
|
||||
pub fn fetch(config FetchConfig) ?Response {
|
||||
pub fn fetch(config FetchConfig) !Response {
|
||||
if config.url == '' {
|
||||
return error('http.fetch: empty url')
|
||||
}
|
||||
@ -154,7 +154,7 @@ pub fn fetch(config FetchConfig) ?Response {
|
||||
in_memory_verification: config.in_memory_verification
|
||||
allow_redirect: config.allow_redirect
|
||||
}
|
||||
res := req.do()?
|
||||
res := req.do()!
|
||||
return res
|
||||
}
|
||||
|
||||
@ -176,14 +176,14 @@ pub fn url_encode_form_data(data map[string]string) string {
|
||||
}
|
||||
|
||||
[deprecated: 'use fetch()']
|
||||
fn fetch_with_method(method Method, _config FetchConfig) ?Response {
|
||||
fn fetch_with_method(method Method, _config FetchConfig) !Response {
|
||||
mut config := _config
|
||||
config.method = method
|
||||
return fetch(config)
|
||||
}
|
||||
|
||||
fn build_url_from_fetch(config FetchConfig) ?string {
|
||||
mut url := urllib.parse(config.url)?
|
||||
fn build_url_from_fetch(config FetchConfig) !string {
|
||||
mut url := urllib.parse(config.url)!
|
||||
if config.params.len == 0 {
|
||||
return url.str()
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ struct HttpbinResponseBody {
|
||||
url string
|
||||
}
|
||||
|
||||
fn http_fetch_mock(_methods []string, _config FetchConfig) ?[]Response {
|
||||
fn http_fetch_mock(_methods []string, _config FetchConfig) ![]Response {
|
||||
url := 'https://httpbin.org/'
|
||||
methods := if _methods.len == 0 { ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'] } else { _methods }
|
||||
mut config := _config
|
||||
@ -23,7 +23,7 @@ fn http_fetch_mock(_methods []string, _config FetchConfig) ?[]Response {
|
||||
for method in methods {
|
||||
lmethod := method.to_lower()
|
||||
config.method = method_from_str(method)
|
||||
res := fetch(FetchConfig{ ...config, url: url + lmethod })?
|
||||
res := fetch(FetchConfig{ ...config, url: url + lmethod })!
|
||||
// TODO
|
||||
// body := json.decode(HttpbinResponseBody,res.body)?
|
||||
result << res
|
||||
@ -75,12 +75,12 @@ fn test_http_fetch_with_params() {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_http_fetch_with_headers() ? {
|
||||
fn test_http_fetch_with_headers() ! {
|
||||
$if !network ? {
|
||||
return
|
||||
}
|
||||
mut header := new_header()
|
||||
header.add_custom('Test-Header', 'hello world')?
|
||||
header.add_custom('Test-Header', 'hello world')!
|
||||
responses := http_fetch_mock([],
|
||||
header: header
|
||||
) or { panic(err) }
|
||||
|
@ -48,12 +48,12 @@ pub fn (mut req Request) add_header(key CommonHeader, val string) {
|
||||
|
||||
// add_custom_header adds the key and value of an HTTP request header
|
||||
// This method may fail if the key contains characters that are not permitted
|
||||
pub fn (mut req Request) add_custom_header(key string, val string) ? {
|
||||
pub fn (mut req Request) add_custom_header(key string, val string) ! {
|
||||
return req.header.add_custom(key, val)
|
||||
}
|
||||
|
||||
// do will send the HTTP request and returns `http.Response` as soon as the response is recevied
|
||||
pub fn (req &Request) do() ?Response {
|
||||
pub fn (req &Request) do() !Response {
|
||||
mut url := urllib.parse(req.url) or { return error('http.Request.do: invalid url $req.url') }
|
||||
mut rurl := url
|
||||
mut resp := Response{}
|
||||
@ -62,7 +62,7 @@ pub fn (req &Request) do() ?Response {
|
||||
if no_redirects == max_redirects {
|
||||
return error('http.request.do: maximum number of redirects reached ($max_redirects)')
|
||||
}
|
||||
qresp := req.method_and_url_to_response(req.method, rurl)?
|
||||
qresp := req.method_and_url_to_response(req.method, rurl)!
|
||||
resp = qresp
|
||||
if !req.allow_redirect {
|
||||
break
|
||||
@ -88,7 +88,7 @@ pub fn (req &Request) do() ?Response {
|
||||
return resp
|
||||
}
|
||||
|
||||
fn (req &Request) method_and_url_to_response(method Method, url urllib.URL) ?Response {
|
||||
fn (req &Request) method_and_url_to_response(method Method, url urllib.URL) !Response {
|
||||
host_name := url.hostname()
|
||||
scheme := url.scheme
|
||||
p := url.escaped_path().trim_left('/')
|
||||
@ -105,11 +105,11 @@ fn (req &Request) method_and_url_to_response(method Method, url urllib.URL) ?Res
|
||||
// println('fetch $method, $scheme, $host_name, $nport, $path ')
|
||||
if scheme == 'https' {
|
||||
// println('ssl_do( $nport, $method, $host_name, $path )')
|
||||
res := req.ssl_do(nport, method, host_name, path)?
|
||||
res := req.ssl_do(nport, method, host_name, path)!
|
||||
return res
|
||||
} else if scheme == 'http' {
|
||||
// println('http_do( $nport, $method, $host_name, $path )')
|
||||
res := req.http_do('$host_name:$nport', method, path)?
|
||||
res := req.http_do('$host_name:$nport', method, path)!
|
||||
return res
|
||||
}
|
||||
return error('http.request.method_and_url_to_response: unsupported scheme: "$scheme"')
|
||||
@ -151,19 +151,19 @@ fn (req &Request) build_request_cookies_header() string {
|
||||
return 'Cookie: ' + cookie.join('; ') + '\r\n'
|
||||
}
|
||||
|
||||
fn (req &Request) http_do(host string, method Method, path string) ?Response {
|
||||
host_name, _ := net.split_address(host)?
|
||||
fn (req &Request) http_do(host string, method Method, path string) !Response {
|
||||
host_name, _ := net.split_address(host)!
|
||||
s := req.build_request_headers(method, host_name, path)
|
||||
mut client := net.dial_tcp(host)?
|
||||
mut client := net.dial_tcp(host)!
|
||||
client.set_read_timeout(req.read_timeout)
|
||||
client.set_write_timeout(req.write_timeout)
|
||||
// TODO this really needs to be exposed somehow
|
||||
client.write(s.bytes())?
|
||||
client.write(s.bytes())!
|
||||
$if trace_http_request ? {
|
||||
eprintln('> $s')
|
||||
}
|
||||
mut bytes := io.read_all(reader: client)?
|
||||
client.close()?
|
||||
mut bytes := io.read_all(reader: client)!
|
||||
client.close()!
|
||||
response_text := bytes.bytestr()
|
||||
$if trace_http_response ? {
|
||||
eprintln('< $response_text')
|
||||
@ -178,8 +178,8 @@ pub fn (req &Request) referer() string {
|
||||
|
||||
// parse_request parses a raw HTTP request into a Request object.
|
||||
// See also: `parse_request_head`, which parses only the headers.
|
||||
pub fn parse_request(mut reader io.BufferedReader) ?Request {
|
||||
mut request := parse_request_head(mut reader)?
|
||||
pub fn parse_request(mut reader io.BufferedReader) !Request {
|
||||
mut request := parse_request_head(mut reader)!
|
||||
|
||||
// body
|
||||
mut body := []u8{}
|
||||
@ -199,18 +199,18 @@ pub fn parse_request(mut reader io.BufferedReader) ?Request {
|
||||
}
|
||||
|
||||
// parse_request_head parses *only* the header of a raw HTTP request into a Request object
|
||||
pub fn parse_request_head(mut reader io.BufferedReader) ?Request {
|
||||
pub fn parse_request_head(mut reader io.BufferedReader) !Request {
|
||||
// request line
|
||||
mut line := reader.read_line()?
|
||||
method, target, version := parse_request_line(line)?
|
||||
mut line := reader.read_line()!
|
||||
method, target, version := parse_request_line(line)!
|
||||
|
||||
// headers
|
||||
mut header := new_header()
|
||||
line = reader.read_line()?
|
||||
line = reader.read_line()!
|
||||
for line != '' {
|
||||
key, value := parse_header(line)?
|
||||
header.add_custom(key, value)?
|
||||
line = reader.read_line()?
|
||||
key, value := parse_header(line)!
|
||||
header.add_custom(key, value)!
|
||||
line = reader.read_line()!
|
||||
}
|
||||
header.coerce(canonicalize: true)
|
||||
|
||||
@ -228,13 +228,13 @@ pub fn parse_request_head(mut reader io.BufferedReader) ?Request {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_request_line(s string) ?(Method, urllib.URL, Version) {
|
||||
fn parse_request_line(s string) !(Method, urllib.URL, Version) {
|
||||
words := s.split(' ')
|
||||
if words.len != 3 {
|
||||
return error('malformed request line')
|
||||
}
|
||||
method := method_from_str(words[0])
|
||||
target := urllib.parse(words[1])?
|
||||
target := urllib.parse(words[1])!
|
||||
version := version_from_str(words[2])
|
||||
if version == .unknown {
|
||||
return error('unsupported version')
|
||||
|
@ -178,7 +178,7 @@ fn test_parse_large_body() {
|
||||
body := 'A'.repeat(101) // greater than max_bytes
|
||||
req := 'GET / HTTP/1.1\r\nContent-Length: $body.len\r\n\r\n$body'
|
||||
mut reader_ := reader(req)
|
||||
result := parse_request(mut reader_)?
|
||||
result := parse_request(mut reader_)!
|
||||
assert result.data.len == body.len
|
||||
assert result.data == body
|
||||
}
|
||||
|
@ -35,11 +35,11 @@ pub fn (resp Response) bytestr() string {
|
||||
}
|
||||
|
||||
// Parse a raw HTTP response into a Response object
|
||||
pub fn parse_response(resp string) ?Response {
|
||||
version, status_code, status_msg := parse_status_line(resp.all_before('\n'))?
|
||||
pub fn parse_response(resp string) !Response {
|
||||
version, status_code, status_msg := parse_status_line(resp.all_before('\n'))!
|
||||
// Build resp header map and separate the body
|
||||
start_idx, end_idx := find_headers_range(resp)?
|
||||
header := parse_headers(resp.substr(start_idx, end_idx))?
|
||||
start_idx, end_idx := find_headers_range(resp)!
|
||||
header := parse_headers(resp.substr(start_idx, end_idx))!
|
||||
mut body := resp.substr(end_idx, resp.len)
|
||||
if header.get(.transfer_encoding) or { '' } == 'chunked' {
|
||||
body = chunked.decode(body)
|
||||
@ -56,7 +56,7 @@ pub fn parse_response(resp string) ?Response {
|
||||
|
||||
// parse_status_line parses the first HTTP response line into the HTTP
|
||||
// version, status code, and reason phrase
|
||||
fn parse_status_line(line string) ?(string, int, string) {
|
||||
fn parse_status_line(line string) !(string, int, string) {
|
||||
if line.len < 5 || line[..5].to_lower() != 'http/' {
|
||||
return error('response does not start with HTTP/')
|
||||
}
|
||||
@ -73,7 +73,7 @@ fn parse_status_line(line string) ?(string, int, string) {
|
||||
for digit in digits {
|
||||
strconv.atoi(digit) or { return error('HTTP version must contain only integers') }
|
||||
}
|
||||
return version, strconv.atoi(data[1])?, data[2]
|
||||
return version, strconv.atoi(data[1])!, data[2]
|
||||
}
|
||||
|
||||
// cookies parses the Set-Cookie headers into Cookie objects
|
||||
@ -138,7 +138,7 @@ pub fn new_response(conf ResponseConfig) Response {
|
||||
// index of the headers in the string, including the trailing newlines. This
|
||||
// helper function expects the first line in `data` to be the HTTP status line
|
||||
// (HTTP/1.1 200 OK).
|
||||
fn find_headers_range(data string) ?(int, int) {
|
||||
fn find_headers_range(data string) !(int, int) {
|
||||
start_idx := data.index('\n') or { return error('no start index found') } + 1
|
||||
mut count := 0
|
||||
for i := start_idx; i < data.len; i++ {
|
||||
|
@ -26,7 +26,7 @@ fn test_response_bytestr() {
|
||||
// check_headers is a helper function for asserting all expected headers
|
||||
// are found because rendered header order is not guaranteed. The check
|
||||
// is O(n^2) which is fine for small lists.
|
||||
fn check_headers(expected []string, found []string) ? {
|
||||
fn check_headers(expected []string, found []string) ! {
|
||||
assert expected.len == found.len
|
||||
for header in expected {
|
||||
if !found.contains(header) {
|
||||
|
@ -34,11 +34,14 @@ pub mut:
|
||||
accept_timeout time.Duration = 30 * time.second
|
||||
}
|
||||
|
||||
pub fn (mut s Server) listen_and_serve() ? {
|
||||
pub fn (mut s Server) listen_and_serve() {
|
||||
if s.handler is DebugHandler {
|
||||
eprintln('Server handler not set, using debug handler')
|
||||
}
|
||||
s.listener = net.listen_tcp(.ip6, ':$s.port')?
|
||||
s.listener = net.listen_tcp(.ip6, ':$s.port') or {
|
||||
eprintln('Listening on :$s.port failed')
|
||||
return
|
||||
}
|
||||
s.listener.set_accept_timeout(s.accept_timeout)
|
||||
eprintln('Listening on :$s.port')
|
||||
s.state = .running
|
||||
|
@ -11,7 +11,7 @@ fn test_server_stop() {
|
||||
server.stop()
|
||||
assert server.status() == .stopped
|
||||
assert watch.elapsed() < 100 * time.millisecond
|
||||
t.wait()?
|
||||
t.wait()
|
||||
assert watch.elapsed() < 999 * time.millisecond
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ fn test_server_close() {
|
||||
server.close()
|
||||
assert server.status() == .closed
|
||||
assert watch.elapsed() < 100 * time.millisecond
|
||||
t.wait()?
|
||||
t.wait()
|
||||
assert watch.elapsed() < 999 * time.millisecond
|
||||
}
|
||||
|
||||
@ -71,19 +71,19 @@ fn test_server_custom_handler() {
|
||||
for server.status() != .running {
|
||||
time.sleep(10 * time.millisecond)
|
||||
}
|
||||
x := http.fetch(url: 'http://localhost:$cport/endpoint?abc=xyz', data: 'my data')?
|
||||
x := http.fetch(url: 'http://localhost:$cport/endpoint?abc=xyz', data: 'my data')!
|
||||
assert x.body == 'my data, /endpoint?abc=xyz'
|
||||
assert x.status_code == 200
|
||||
assert x.http_version == '1.1'
|
||||
y := http.fetch(url: 'http://localhost:$cport/another/endpoint', data: 'abcde')?
|
||||
y := http.fetch(url: 'http://localhost:$cport/another/endpoint', data: 'abcde')!
|
||||
assert y.body == 'abcde, /another/endpoint'
|
||||
assert y.status_code == 200
|
||||
assert y.status() == .ok
|
||||
assert y.http_version == '1.1'
|
||||
//
|
||||
http.fetch(url: 'http://localhost:$cport/something/else')?
|
||||
http.fetch(url: 'http://localhost:$cport/something/else')!
|
||||
server.stop()
|
||||
t.wait()?
|
||||
t.wait()
|
||||
assert handler.counter == 3
|
||||
assert handler.oks == 2
|
||||
assert handler.not_founds == 1
|
||||
|
@ -52,7 +52,7 @@ pub struct SSLConnectConfig {
|
||||
}
|
||||
|
||||
// new_ssl_conn returns a new SSLConn with the given config.
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) ?&SSLConn {
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) !&SSLConn {
|
||||
mut conn := &SSLConn{
|
||||
config: config
|
||||
}
|
||||
@ -68,7 +68,7 @@ enum Select {
|
||||
}
|
||||
|
||||
// shutdown terminates the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) shutdown() ? {
|
||||
pub fn (mut s SSLConn) shutdown() ! {
|
||||
if !s.opened {
|
||||
return error('ssl connection not open')
|
||||
}
|
||||
@ -82,16 +82,16 @@ pub fn (mut s SSLConn) shutdown() ? {
|
||||
if s.owns_socket {
|
||||
$if windows {
|
||||
C.shutdown(s.handle, C.SD_BOTH)
|
||||
net.socket_error(C.closesocket(s.handle))?
|
||||
net.socket_error(C.closesocket(s.handle))!
|
||||
} $else {
|
||||
C.shutdown(s.handle, C.SHUT_RDWR)
|
||||
net.socket_error(C.close(s.handle))?
|
||||
net.socket_error(C.close(s.handle))!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// connect to server using mbedtls
|
||||
fn (mut s SSLConn) init() ? {
|
||||
fn (mut s SSLConn) init() ! {
|
||||
C.mbedtls_net_init(&s.server_fd)
|
||||
C.mbedtls_ssl_init(&s.ssl)
|
||||
C.mbedtls_ssl_config_init(&s.conf)
|
||||
@ -157,7 +157,7 @@ fn (mut s SSLConn) init() ? {
|
||||
}
|
||||
|
||||
// connect sets up an ssl connection on an existing TCP connection
|
||||
pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ? {
|
||||
pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ! {
|
||||
if s.opened {
|
||||
return error('ssl connection already open')
|
||||
}
|
||||
@ -183,7 +183,7 @@ pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ? {
|
||||
}
|
||||
|
||||
// dial opens an ssl connection on hostname:port
|
||||
pub fn (mut s SSLConn) dial(hostname string, port int) ? {
|
||||
pub fn (mut s SSLConn) dial(hostname string, port int) ! {
|
||||
s.owns_socket = true
|
||||
if s.opened {
|
||||
return error('ssl connection already open')
|
||||
@ -216,7 +216,7 @@ pub fn (mut s SSLConn) dial(hostname string, port int) ? {
|
||||
}
|
||||
|
||||
// socket_read_into_ptr reads `len` bytes into `buf`
|
||||
pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) ?int {
|
||||
pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) !int {
|
||||
mut res := 0
|
||||
for {
|
||||
res = C.mbedtls_ssl_read(&s.ssl, buf_ptr, len)
|
||||
@ -227,13 +227,13 @@ pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) ?int {
|
||||
} else {
|
||||
match res {
|
||||
C.MBEDTLS_ERR_SSL_WANT_READ {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if !ready {
|
||||
return net.err_timed_out
|
||||
}
|
||||
}
|
||||
C.MBEDTLS_ERR_SSL_WANT_WRITE {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if !ready {
|
||||
return net.err_timed_out
|
||||
}
|
||||
@ -257,7 +257,7 @@ pub fn (mut s SSLConn) read(mut buffer []u8) !int {
|
||||
}
|
||||
|
||||
// write_ptr writes `len` bytes from `bytes` to the ssl connection
|
||||
pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) !int {
|
||||
unsafe {
|
||||
mut ptr_base := bytes
|
||||
mut total_sent := 0
|
||||
@ -269,7 +269,7 @@ pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
match sent {
|
||||
C.MBEDTLS_ERR_SSL_WANT_READ {
|
||||
for {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -278,7 +278,7 @@ pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
}
|
||||
C.MBEDTLS_ERR_SSL_WANT_WRITE {
|
||||
for {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -297,12 +297,12 @@ pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
}
|
||||
|
||||
// write writes data from `bytes` to the ssl connection
|
||||
pub fn (mut s SSLConn) write(bytes []u8) ?int {
|
||||
pub fn (mut s SSLConn) write(bytes []u8) !int {
|
||||
return s.write_ptr(&u8(bytes.data), bytes.len)
|
||||
}
|
||||
|
||||
// write_string writes a string to the ssl connection
|
||||
pub fn (mut s SSLConn) write_string(str string) ?int {
|
||||
pub fn (mut s SSLConn) write_string(str string) !int {
|
||||
return s.write_ptr(str.str, str.len)
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ This is basically a copy of Emily socket implementation of select.
|
||||
*/
|
||||
|
||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||
fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||
set := C.fd_set{}
|
||||
|
||||
C.FD_ZERO(&set)
|
||||
@ -336,13 +336,13 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
|
||||
match test {
|
||||
.read {
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.write {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.except {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
module openssl
|
||||
|
||||
// ssl_error returns non error ssl code or error if unrecoverable and we should panic
|
||||
fn ssl_error(ret int, ssl voidptr) ?SSLError {
|
||||
fn ssl_error(ret int, ssl voidptr) !SSLError {
|
||||
res := C.SSL_get_error(ssl, ret)
|
||||
match unsafe { SSLError(res) } {
|
||||
.ssl_error_syscall {
|
||||
|
@ -28,7 +28,7 @@ pub struct SSLConnectConfig {
|
||||
}
|
||||
|
||||
// new_ssl_conn instance an new SSLCon struct
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) ?&SSLConn {
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) !&SSLConn {
|
||||
mut conn := &SSLConn{
|
||||
config: config
|
||||
sslctx: 0
|
||||
@ -47,7 +47,7 @@ enum Select {
|
||||
}
|
||||
|
||||
// shutdown closes the ssl connection and does cleanup
|
||||
pub fn (mut s SSLConn) shutdown() ? {
|
||||
pub fn (mut s SSLConn) shutdown() ! {
|
||||
if s.ssl != 0 {
|
||||
mut res := 0
|
||||
for {
|
||||
@ -100,15 +100,15 @@ pub fn (mut s SSLConn) shutdown() ? {
|
||||
if s.owns_socket {
|
||||
$if windows {
|
||||
C.shutdown(s.handle, C.SD_BOTH)
|
||||
net.socket_error(C.closesocket(s.handle))?
|
||||
net.socket_error(C.closesocket(s.handle))!
|
||||
} $else {
|
||||
C.shutdown(s.handle, C.SHUT_RDWR)
|
||||
net.socket_error(C.close(s.handle))?
|
||||
net.socket_error(C.close(s.handle))!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut s SSLConn) init() ? {
|
||||
fn (mut s SSLConn) init() ! {
|
||||
s.sslctx = unsafe { C.SSL_CTX_new(C.SSLv23_client_method()) }
|
||||
if s.sslctx == 0 {
|
||||
return error("Couldn't get ssl context")
|
||||
@ -136,13 +136,13 @@ fn (mut s SSLConn) init() ? {
|
||||
cert = os.temp_dir() + '/v_cert' + now
|
||||
cert_key = os.temp_dir() + '/v_cert_key' + now
|
||||
if s.config.verify != '' {
|
||||
os.write_file(verify, s.config.verify)?
|
||||
os.write_file(verify, s.config.verify)!
|
||||
}
|
||||
if s.config.cert != '' {
|
||||
os.write_file(cert, s.config.cert)?
|
||||
os.write_file(cert, s.config.cert)!
|
||||
}
|
||||
if s.config.cert_key != '' {
|
||||
os.write_file(cert_key, s.config.cert_key)?
|
||||
os.write_file(cert_key, s.config.cert_key)!
|
||||
}
|
||||
}
|
||||
if s.config.verify != '' {
|
||||
@ -175,7 +175,7 @@ fn (mut s SSLConn) init() ? {
|
||||
}
|
||||
|
||||
// connect to server using OpenSSL
|
||||
pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ? {
|
||||
pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ! {
|
||||
s.handle = tcp_conn.sock.handle
|
||||
s.duration = tcp_conn.read_timeout()
|
||||
|
||||
@ -192,7 +192,7 @@ pub fn (mut s SSLConn) connect(mut tcp_conn net.TcpConn, hostname string) ? {
|
||||
}
|
||||
|
||||
// dial opens an ssl connection on hostname:port
|
||||
pub fn (mut s SSLConn) dial(hostname string, port int) ? {
|
||||
pub fn (mut s SSLConn) dial(hostname string, port int) ! {
|
||||
s.owns_socket = true
|
||||
mut tcp_conn := net.dial_tcp('$hostname:$port') or { return err }
|
||||
$if macos {
|
||||
@ -201,14 +201,14 @@ pub fn (mut s SSLConn) dial(hostname string, port int) ? {
|
||||
s.connect(mut tcp_conn, hostname) or { return err }
|
||||
}
|
||||
|
||||
fn (mut s SSLConn) complete_connect() ? {
|
||||
fn (mut s SSLConn) complete_connect() ! {
|
||||
for {
|
||||
mut res := C.SSL_connect(voidptr(s.ssl))
|
||||
if res != 1 {
|
||||
err_res := ssl_error(res, s.ssl)?
|
||||
err_res := ssl_error(res, s.ssl)!
|
||||
if err_res == .ssl_error_want_read {
|
||||
for {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -216,7 +216,7 @@ fn (mut s SSLConn) complete_connect() ? {
|
||||
continue
|
||||
} else if err_res == .ssl_error_want_write {
|
||||
for {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -232,10 +232,10 @@ fn (mut s SSLConn) complete_connect() ? {
|
||||
for {
|
||||
mut res := C.SSL_do_handshake(voidptr(s.ssl))
|
||||
if res != 1 {
|
||||
err_res := ssl_error(res, s.ssl)?
|
||||
err_res := ssl_error(res, s.ssl)!
|
||||
if err_res == .ssl_error_want_read {
|
||||
for {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -243,7 +243,7 @@ fn (mut s SSLConn) complete_connect() ? {
|
||||
continue
|
||||
} else if err_res == .ssl_error_want_write {
|
||||
for {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -267,7 +267,7 @@ fn (mut s SSLConn) complete_connect() ? {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) ?int {
|
||||
pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) !int {
|
||||
mut res := 0
|
||||
for {
|
||||
res = C.SSL_read(voidptr(s.ssl), buf_ptr, len)
|
||||
@ -276,16 +276,16 @@ pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr &u8, len int) ?int {
|
||||
} else if res == 0 {
|
||||
return IError(io.Eof{})
|
||||
} else {
|
||||
err_res := ssl_error(res, s.ssl)?
|
||||
err_res := ssl_error(res, s.ssl)!
|
||||
match err_res {
|
||||
.ssl_error_want_read {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if !ready {
|
||||
return net.err_timed_out
|
||||
}
|
||||
}
|
||||
.ssl_error_want_write {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if !ready {
|
||||
return net.err_timed_out
|
||||
}
|
||||
@ -308,7 +308,7 @@ pub fn (mut s SSLConn) read(mut buffer []u8) !int {
|
||||
}
|
||||
|
||||
// write_ptr writes `len` bytes from `bytes` to the ssl connection
|
||||
pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) !int {
|
||||
unsafe {
|
||||
mut ptr_base := bytes
|
||||
mut total_sent := 0
|
||||
@ -317,17 +317,17 @@ pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
remaining := len - total_sent
|
||||
mut sent := C.SSL_write(voidptr(s.ssl), ptr, remaining)
|
||||
if sent <= 0 {
|
||||
err_res := ssl_error(sent, s.ssl)?
|
||||
err_res := ssl_error(sent, s.ssl)!
|
||||
if err_res == .ssl_error_want_read {
|
||||
for {
|
||||
ready := @select(s.handle, .read, s.duration)?
|
||||
ready := @select(s.handle, .read, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if err_res == .ssl_error_want_write {
|
||||
for {
|
||||
ready := @select(s.handle, .write, s.duration)?
|
||||
ready := @select(s.handle, .write, s.duration)!
|
||||
if ready {
|
||||
break
|
||||
}
|
||||
@ -345,12 +345,12 @@ pub fn (mut s SSLConn) write_ptr(bytes &u8, len int) ?int {
|
||||
}
|
||||
|
||||
// write writes data from `bytes` to the ssl connection
|
||||
pub fn (mut s SSLConn) write(bytes []u8) ?int {
|
||||
pub fn (mut s SSLConn) write(bytes []u8) !int {
|
||||
return s.write_ptr(&u8(bytes.data), bytes.len)
|
||||
}
|
||||
|
||||
// write_string writes a string to the ssl connection
|
||||
pub fn (mut s SSLConn) write_string(str string) ?int {
|
||||
pub fn (mut s SSLConn) write_string(str string) !int {
|
||||
return s.write_ptr(str.str, str.len)
|
||||
}
|
||||
|
||||
@ -364,7 +364,7 @@ This is basically a copy of Emily socket implementation of select.
|
||||
// }
|
||||
|
||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||
fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||
set := C.fd_set{}
|
||||
|
||||
C.FD_ZERO(&set)
|
||||
@ -387,13 +387,13 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
|
||||
match test {
|
||||
.read {
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.write {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.except {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ pub struct Mail {
|
||||
}
|
||||
|
||||
// new_client returns a new SMTP client and connects to it
|
||||
pub fn new_client(config Client) ?&Client {
|
||||
pub fn new_client(config Client) !&Client {
|
||||
if config.ssl && config.starttls {
|
||||
return error('Can not use both implicit SSL and STARTTLS')
|
||||
}
|
||||
@ -67,12 +67,12 @@ pub fn new_client(config Client) ?&Client {
|
||||
mut c := &Client{
|
||||
...config
|
||||
}
|
||||
c.reconnect()?
|
||||
c.reconnect()!
|
||||
return c
|
||||
}
|
||||
|
||||
// reconnect reconnects to the SMTP server if the connection was closed
|
||||
pub fn (mut c Client) reconnect() ? {
|
||||
pub fn (mut c Client) reconnect() ! {
|
||||
if c.is_open {
|
||||
return error('Already connected to server')
|
||||
}
|
||||
@ -81,7 +81,7 @@ pub fn (mut c Client) reconnect() ? {
|
||||
c.conn = conn
|
||||
|
||||
if c.ssl {
|
||||
c.connect_ssl()?
|
||||
c.connect_ssl()!
|
||||
} else {
|
||||
c.reader = io.new_buffered_reader(reader: c.conn)
|
||||
}
|
||||
@ -98,7 +98,7 @@ pub fn (mut c Client) reconnect() ? {
|
||||
}
|
||||
|
||||
// send sends an email
|
||||
pub fn (mut c Client) send(config Mail) ? {
|
||||
pub fn (mut c Client) send(config Mail) ! {
|
||||
if !c.is_open {
|
||||
return error('Disconnected from server')
|
||||
}
|
||||
@ -113,20 +113,20 @@ pub fn (mut c Client) send(config Mail) ? {
|
||||
}
|
||||
|
||||
// quit closes the connection to the server
|
||||
pub fn (mut c Client) quit() ? {
|
||||
c.send_str('QUIT\r\n')?
|
||||
c.expect_reply(.close)?
|
||||
pub fn (mut c Client) quit() ! {
|
||||
c.send_str('QUIT\r\n')!
|
||||
c.expect_reply(.close)!
|
||||
if c.encrypted {
|
||||
c.ssl_conn.shutdown()?
|
||||
c.ssl_conn.shutdown()!
|
||||
} else {
|
||||
c.conn.close()?
|
||||
c.conn.close()!
|
||||
}
|
||||
c.is_open = false
|
||||
c.encrypted = false
|
||||
}
|
||||
|
||||
fn (mut c Client) connect_ssl() ? {
|
||||
c.ssl_conn = ssl.new_ssl_conn()?
|
||||
fn (mut c Client) connect_ssl() ! {
|
||||
c.ssl_conn = ssl.new_ssl_conn()!
|
||||
c.ssl_conn.connect(mut c.conn, c.server) or {
|
||||
return error('Connecting to server using OpenSSL failed: $err')
|
||||
}
|
||||
@ -136,10 +136,10 @@ fn (mut c Client) connect_ssl() ? {
|
||||
}
|
||||
|
||||
// expect_reply checks if the SMTP server replied with the expected reply code
|
||||
fn (mut c Client) expect_reply(expected ReplyCode) ? {
|
||||
fn (mut c Client) expect_reply(expected ReplyCode) ! {
|
||||
mut str := ''
|
||||
for {
|
||||
str = c.reader.read_line()?
|
||||
str = c.reader.read_line()!
|
||||
if str.len < 4 {
|
||||
return error('Invalid SMTP response: $str')
|
||||
}
|
||||
@ -167,7 +167,7 @@ fn (mut c Client) expect_reply(expected ReplyCode) ? {
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Client) send_str(s string) ? {
|
||||
fn (mut c Client) send_str(s string) ! {
|
||||
$if smtp_debug ? {
|
||||
eprintln('\n\n[SEND START]')
|
||||
eprint(s.trim_space())
|
||||
@ -175,27 +175,27 @@ fn (mut c Client) send_str(s string) ? {
|
||||
}
|
||||
|
||||
if c.encrypted {
|
||||
c.ssl_conn.write(s.bytes())?
|
||||
c.ssl_conn.write(s.bytes())!
|
||||
} else {
|
||||
c.conn.write(s.bytes())?
|
||||
c.conn.write(s.bytes())!
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Client) send_ehlo() ? {
|
||||
c.send_str('EHLO $c.server\r\n')?
|
||||
c.expect_reply(.action_ok)?
|
||||
fn (mut c Client) send_ehlo() ! {
|
||||
c.send_str('EHLO $c.server\r\n')!
|
||||
c.expect_reply(.action_ok)!
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Client) send_starttls() ? {
|
||||
c.send_str('STARTTLS\r\n')?
|
||||
c.expect_reply(.ready)?
|
||||
c.connect_ssl()?
|
||||
fn (mut c Client) send_starttls() ! {
|
||||
c.send_str('STARTTLS\r\n')!
|
||||
c.expect_reply(.ready)!
|
||||
c.connect_ssl()!
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Client) send_auth() ? {
|
||||
fn (mut c Client) send_auth() ! {
|
||||
if c.username.len == 0 {
|
||||
return
|
||||
}
|
||||
@ -206,28 +206,28 @@ fn (mut c Client) send_auth() ? {
|
||||
sb.write_string(c.password)
|
||||
a := sb.str()
|
||||
auth := 'AUTH PLAIN ${base64.encode_str(a)}\r\n'
|
||||
c.send_str(auth)?
|
||||
c.expect_reply(.auth_ok)?
|
||||
c.send_str(auth)!
|
||||
c.expect_reply(.auth_ok)!
|
||||
}
|
||||
|
||||
fn (mut c Client) send_mailfrom(from string) ? {
|
||||
c.send_str('MAIL FROM: <$from>\r\n')?
|
||||
c.expect_reply(.action_ok)?
|
||||
fn (mut c Client) send_mailfrom(from string) ! {
|
||||
c.send_str('MAIL FROM: <$from>\r\n')!
|
||||
c.expect_reply(.action_ok)!
|
||||
}
|
||||
|
||||
fn (mut c Client) send_mailto(to string) ? {
|
||||
fn (mut c Client) send_mailto(to string) ! {
|
||||
for rcpt in to.split(';') {
|
||||
c.send_str('RCPT TO: <$rcpt>\r\n')?
|
||||
c.expect_reply(.action_ok)?
|
||||
c.send_str('RCPT TO: <$rcpt>\r\n')!
|
||||
c.expect_reply(.action_ok)!
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Client) send_data() ? {
|
||||
c.send_str('DATA\r\n')?
|
||||
c.expect_reply(.mail_start)?
|
||||
fn (mut c Client) send_data() ! {
|
||||
c.send_str('DATA\r\n')!
|
||||
c.expect_reply(.mail_start)!
|
||||
}
|
||||
|
||||
fn (mut c Client) send_body(cfg Mail) ? {
|
||||
fn (mut c Client) send_body(cfg Mail) ! {
|
||||
is_html := cfg.body_type == .html
|
||||
date := cfg.date.custom_format('ddd, D MMM YYYY HH:mm ZZ')
|
||||
nonascii_subject := cfg.subject.bytes().any(it < u8(` `) || it > u8(`~`))
|
||||
@ -253,6 +253,6 @@ fn (mut c Client) send_body(cfg Mail) ? {
|
||||
sb.write_string('\r\n\r\n')
|
||||
sb.write_string(base64.encode_str(cfg.body))
|
||||
sb.write_string('\r\n.\r\n')
|
||||
c.send_str(sb.str())?
|
||||
c.expect_reply(.action_ok)?
|
||||
c.send_str(sb.str())!
|
||||
c.expect_reply(.action_ok)!
|
||||
}
|
||||
|
@ -6,6 +6,6 @@ pub:
|
||||
}
|
||||
|
||||
// address gets the address of a socket
|
||||
pub fn (s &Socket) address() ?Addr {
|
||||
pub fn (s &Socket) address() !Addr {
|
||||
return addr_from_socket_handle(s.handle)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub struct SSLConnectConfig {
|
||||
}
|
||||
|
||||
// new_ssl_conn returns a new SSLConn with the given config.
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) ?&SSLConn {
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) !&SSLConn {
|
||||
c := openssl.new_ssl_conn(config.SSLConnectConfig) or { return err }
|
||||
return &SSLConn{c}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub struct SSLConnectConfig {
|
||||
}
|
||||
|
||||
// new_ssl_conn returns a new SSLConn with the given config.
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) ?&SSLConn {
|
||||
pub fn new_ssl_conn(config SSLConnectConfig) !&SSLConn {
|
||||
c := mbedtls.new_ssl_conn(config.SSLConnectConfig) or { return err }
|
||||
return &SSLConn{c}
|
||||
}
|
||||
|
120
vlib/net/tcp.v
120
vlib/net/tcp.v
@ -21,7 +21,7 @@ mut:
|
||||
is_blocking bool
|
||||
}
|
||||
|
||||
pub fn dial_tcp(address string) ?&TcpConn {
|
||||
pub fn dial_tcp(address string) !&TcpConn {
|
||||
addrs := resolve_addrs_fuzzy(address, .tcp) or {
|
||||
return error('$err.msg(); could not resolve address $address in dial_tcp')
|
||||
}
|
||||
@ -64,7 +64,7 @@ pub fn dial_tcp(address string) ?&TcpConn {
|
||||
}
|
||||
|
||||
// bind local address and dial.
|
||||
pub fn dial_tcp_with_bind(saddr string, laddr string) ?&TcpConn {
|
||||
pub fn dial_tcp_with_bind(saddr string, laddr string) !&TcpConn {
|
||||
addrs := resolve_addrs_fuzzy(saddr, .tcp) or {
|
||||
return error('$err.msg(); could not resolve address $saddr in dial_tcp_with_bind')
|
||||
}
|
||||
@ -94,15 +94,15 @@ pub fn dial_tcp_with_bind(saddr string, laddr string) ?&TcpConn {
|
||||
return error('dial_tcp_with_bind failed for address $saddr')
|
||||
}
|
||||
|
||||
pub fn (mut c TcpConn) close() ? {
|
||||
pub fn (mut c TcpConn) close() ! {
|
||||
$if trace_tcp ? {
|
||||
eprintln(' TcpConn.close | c.sock.handle: ${c.sock.handle:6}')
|
||||
}
|
||||
c.sock.close()?
|
||||
c.sock.close()!
|
||||
}
|
||||
|
||||
pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) ?int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))?
|
||||
pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) !int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))!
|
||||
$if trace_tcp ? {
|
||||
eprintln('<<< TcpConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
@ -115,8 +115,8 @@ pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) ?int {
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_read()?
|
||||
res = wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))?
|
||||
c.wait_for_read()!
|
||||
res = wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))!
|
||||
$if trace_tcp ? {
|
||||
eprintln('<<< TcpConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
@ -128,9 +128,9 @@ pub fn (c TcpConn) read_ptr(buf_ptr &u8, len int) ?int {
|
||||
}
|
||||
return socket_error(res)
|
||||
} else {
|
||||
wrap_error(code)?
|
||||
wrap_error(code)!
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (c TcpConn) read(mut buf []u8) !int {
|
||||
@ -142,15 +142,15 @@ pub fn (c TcpConn) read(mut buf []u8) !int {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c TcpConn) read_deadline() ?time.Time {
|
||||
pub fn (mut c TcpConn) read_deadline() !time.Time {
|
||||
if c.read_deadline.unix == 0 {
|
||||
return c.read_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// write_ptr blocks and attempts to write all data
|
||||
pub fn (mut c TcpConn) write_ptr(b &u8, len int) ?int {
|
||||
pub fn (mut c TcpConn) write_ptr(b &u8, len int) !int {
|
||||
$if trace_tcp ? {
|
||||
eprintln(
|
||||
'>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
@ -173,10 +173,10 @@ pub fn (mut c TcpConn) write_ptr(b &u8, len int) ?int {
|
||||
if sent < 0 {
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_write()?
|
||||
c.wait_for_write()!
|
||||
continue
|
||||
} else {
|
||||
wrap_error(code)?
|
||||
wrap_error(code)!
|
||||
}
|
||||
}
|
||||
total_sent += sent
|
||||
@ -186,12 +186,12 @@ pub fn (mut c TcpConn) write_ptr(b &u8, len int) ?int {
|
||||
}
|
||||
|
||||
// write blocks and attempts to write all data
|
||||
pub fn (mut c TcpConn) write(bytes []u8) ?int {
|
||||
pub fn (mut c TcpConn) write(bytes []u8) !int {
|
||||
return c.write_ptr(bytes.data, bytes.len)
|
||||
}
|
||||
|
||||
// write_string blocks and attempts to write all data
|
||||
pub fn (mut c TcpConn) write_string(s string) ?int {
|
||||
pub fn (mut c TcpConn) write_string(s string) !int {
|
||||
return c.write_ptr(s.str, s.len)
|
||||
}
|
||||
|
||||
@ -199,11 +199,11 @@ pub fn (mut c TcpConn) set_read_deadline(deadline time.Time) {
|
||||
c.read_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (mut c TcpConn) write_deadline() ?time.Time {
|
||||
pub fn (mut c TcpConn) write_deadline() !time.Time {
|
||||
if c.write_deadline.unix == 0 {
|
||||
return c.write_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (mut c TcpConn) set_write_deadline(deadline time.Time) {
|
||||
@ -227,31 +227,31 @@ pub fn (mut c TcpConn) set_write_timeout(t time.Duration) {
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (c TcpConn) wait_for_read() ? {
|
||||
pub fn (c TcpConn) wait_for_read() ! {
|
||||
return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c TcpConn) wait_for_write() ? {
|
||||
pub fn (mut c TcpConn) wait_for_write() ! {
|
||||
return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout)
|
||||
}
|
||||
|
||||
pub fn (c &TcpConn) peer_addr() ?Addr {
|
||||
pub fn (c &TcpConn) peer_addr() !Addr {
|
||||
mut addr := Addr{
|
||||
addr: AddrData{
|
||||
Ip6: Ip6{}
|
||||
}
|
||||
}
|
||||
mut size := sizeof(Addr)
|
||||
socket_error_message(C.getpeername(c.sock.handle, voidptr(&addr), &size), 'peer_addr failed')?
|
||||
socket_error_message(C.getpeername(c.sock.handle, voidptr(&addr), &size), 'peer_addr failed')!
|
||||
return addr
|
||||
}
|
||||
|
||||
pub fn (c &TcpConn) peer_ip() ?string {
|
||||
return c.peer_addr()?.str()
|
||||
pub fn (c &TcpConn) peer_ip() !string {
|
||||
return c.peer_addr()!.str()
|
||||
}
|
||||
|
||||
pub fn (c &TcpConn) addr() ?Addr {
|
||||
pub fn (c &TcpConn) addr() !Addr {
|
||||
return c.sock.address()
|
||||
}
|
||||
|
||||
@ -268,7 +268,7 @@ mut:
|
||||
accept_deadline time.Time
|
||||
}
|
||||
|
||||
pub fn listen_tcp(family AddrFamily, saddr string) ?&TcpListener {
|
||||
pub fn listen_tcp(family AddrFamily, saddr string) !&TcpListener {
|
||||
s := new_tcp_socket(family) or { return error('$err.msg(); could not create new socket') }
|
||||
|
||||
addrs := resolve_addrs(saddr, family, .tcp) or {
|
||||
@ -280,8 +280,8 @@ pub fn listen_tcp(family AddrFamily, saddr string) ?&TcpListener {
|
||||
|
||||
// cast to the correct type
|
||||
alen := addr.len()
|
||||
socket_error_message(C.bind(s.handle, voidptr(&addr), alen), 'binding to $saddr failed')?
|
||||
socket_error_message(C.listen(s.handle, 128), 'listening on $saddr failed')?
|
||||
socket_error_message(C.bind(s.handle, voidptr(&addr), alen), 'binding to $saddr failed')!
|
||||
socket_error_message(C.listen(s.handle, 128), 'listening on $saddr failed')!
|
||||
return &TcpListener{
|
||||
sock: s
|
||||
accept_deadline: no_deadline
|
||||
@ -289,19 +289,19 @@ pub fn listen_tcp(family AddrFamily, saddr string) ?&TcpListener {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l TcpListener) accept() ?&TcpConn {
|
||||
pub fn (mut l TcpListener) accept() !&TcpConn {
|
||||
$if trace_tcp ? {
|
||||
eprintln(' TcpListener.accept | l.sock.handle: ${l.sock.handle:6}')
|
||||
}
|
||||
mut new_handle := C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle <= 0 {
|
||||
l.wait_for_accept()?
|
||||
l.wait_for_accept()!
|
||||
new_handle = C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle == -1 || new_handle == 0 {
|
||||
return error('accept failed')
|
||||
}
|
||||
}
|
||||
new_sock := tcp_socket_from_handle(new_handle)?
|
||||
new_sock := tcp_socket_from_handle(new_handle)!
|
||||
$if trace_tcp ? {
|
||||
eprintln(' TcpListener.accept | << new_sock.handle: ${new_sock.handle:6}')
|
||||
}
|
||||
@ -312,7 +312,7 @@ pub fn (mut l TcpListener) accept() ?&TcpConn {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &TcpListener) accept_deadline() ?time.Time {
|
||||
pub fn (c &TcpListener) accept_deadline() !time.Time {
|
||||
if c.accept_deadline.unix != 0 {
|
||||
return c.accept_deadline
|
||||
}
|
||||
@ -331,15 +331,15 @@ pub fn (mut c TcpListener) set_accept_timeout(t time.Duration) {
|
||||
c.accept_timeout = t
|
||||
}
|
||||
|
||||
pub fn (mut c TcpListener) wait_for_accept() ? {
|
||||
pub fn (mut c TcpListener) wait_for_accept() ! {
|
||||
return wait_for_read(c.sock.handle, c.accept_deadline, c.accept_timeout)
|
||||
}
|
||||
|
||||
pub fn (mut c TcpListener) close() ? {
|
||||
c.sock.close()?
|
||||
pub fn (mut c TcpListener) close() ! {
|
||||
c.sock.close()!
|
||||
}
|
||||
|
||||
pub fn (c &TcpListener) addr() ?Addr {
|
||||
pub fn (c &TcpListener) addr() !Addr {
|
||||
return c.sock.address()
|
||||
}
|
||||
|
||||
@ -347,8 +347,8 @@ struct TcpSocket {
|
||||
Socket
|
||||
}
|
||||
|
||||
fn new_tcp_socket(family AddrFamily) ?TcpSocket {
|
||||
handle := socket_error(C.socket(family, SocketType.tcp, 0))?
|
||||
fn new_tcp_socket(family AddrFamily) !TcpSocket {
|
||||
handle := socket_error(C.socket(family, SocketType.tcp, 0))!
|
||||
mut s := TcpSocket{
|
||||
handle: handle
|
||||
}
|
||||
@ -362,20 +362,20 @@ fn new_tcp_socket(family AddrFamily) ?TcpSocket {
|
||||
|
||||
// TODO(emily):
|
||||
// Move this to its own function on the socket
|
||||
s.set_option_int(.reuse_addr, 1)?
|
||||
s.set_option_int(.reuse_addr, 1)!
|
||||
|
||||
$if !net_blocking_sockets ? {
|
||||
$if windows {
|
||||
t := u32(1) // true
|
||||
socket_error(C.ioctlsocket(handle, fionbio, &t))?
|
||||
socket_error(C.ioctlsocket(handle, fionbio, &t))!
|
||||
} $else {
|
||||
socket_error(C.fcntl(handle, C.F_SETFL, C.fcntl(handle, C.F_GETFL) | C.O_NONBLOCK))?
|
||||
socket_error(C.fcntl(handle, C.F_SETFL, C.fcntl(handle, C.F_GETFL) | C.O_NONBLOCK))!
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
fn tcp_socket_from_handle(sockfd int) ?TcpSocket {
|
||||
fn tcp_socket_from_handle(sockfd int) !TcpSocket {
|
||||
mut s := TcpSocket{
|
||||
handle: sockfd
|
||||
}
|
||||
@ -383,22 +383,22 @@ fn tcp_socket_from_handle(sockfd int) ?TcpSocket {
|
||||
eprintln(' tcp_socket_from_handle | s.handle: ${s.handle:6}')
|
||||
}
|
||||
// s.set_option_bool(.reuse_addr, true)?
|
||||
s.set_option_int(.reuse_addr, 1)?
|
||||
s.set_option_int(.reuse_addr, 1)!
|
||||
s.set_dualstack(true) or {
|
||||
// Not ipv6, we dont care
|
||||
}
|
||||
$if !net_blocking_sockets ? {
|
||||
$if windows {
|
||||
t := u32(1) // true
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t))?
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t))!
|
||||
} $else {
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))?
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))!
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
pub fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) ? {
|
||||
pub fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) ! {
|
||||
// TODO reenable when this `in` operation works again
|
||||
// if opt !in opts_can_set {
|
||||
// return err_option_not_settable
|
||||
@ -407,21 +407,21 @@ pub fn (mut s TcpSocket) set_option_bool(opt SocketOption, value bool) ? {
|
||||
// return err_option_wrong_type
|
||||
// }
|
||||
x := int(value)
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &x, sizeof(int)))?
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &x, sizeof(int)))!
|
||||
}
|
||||
|
||||
pub fn (mut s TcpSocket) set_dualstack(on bool) ? {
|
||||
pub fn (mut s TcpSocket) set_dualstack(on bool) ! {
|
||||
x := int(!on)
|
||||
socket_error(C.setsockopt(s.handle, C.IPPROTO_IPV6, int(SocketOption.ipv6_only), &x,
|
||||
sizeof(int)))?
|
||||
sizeof(int)))!
|
||||
}
|
||||
|
||||
pub fn (mut s TcpSocket) set_option_int(opt SocketOption, value int) ? {
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &value, sizeof(int)))?
|
||||
pub fn (mut s TcpSocket) set_option_int(opt SocketOption, value int) ! {
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &value, sizeof(int)))!
|
||||
}
|
||||
|
||||
// bind a local rddress for TcpSocket
|
||||
pub fn (mut s TcpSocket) bind(addr string) ? {
|
||||
pub fn (mut s TcpSocket) bind(addr string) ! {
|
||||
addrs := resolve_addrs(addr, AddrFamily.ip, .tcp) or {
|
||||
return error('$err.msg(); could not resolve address $addr')
|
||||
}
|
||||
@ -436,11 +436,11 @@ pub fn (mut s TcpSocket) bind(addr string) ? {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut s TcpSocket) close() ? {
|
||||
fn (mut s TcpSocket) close() ! {
|
||||
return shutdown(s.handle)
|
||||
}
|
||||
|
||||
fn (mut s TcpSocket) @select(test Select, timeout time.Duration) ?bool {
|
||||
fn (mut s TcpSocket) @select(test Select, timeout time.Duration) !bool {
|
||||
return @select(s.handle, test, timeout)
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ const (
|
||||
connect_timeout = 5 * time.second
|
||||
)
|
||||
|
||||
fn (mut s TcpSocket) connect(a Addr) ? {
|
||||
fn (mut s TcpSocket) connect(a Addr) ! {
|
||||
$if !net_blocking_sockets ? {
|
||||
res := C.connect(s.handle, voidptr(&a), a.len())
|
||||
if res == 0 {
|
||||
@ -467,7 +467,7 @@ fn (mut s TcpSocket) connect(a Addr) ? {
|
||||
// determine whether connect() completed successfully (SO_ERROR is zero) or
|
||||
// unsuccessfully (SO_ERROR is one of the usual error codes listed here,
|
||||
// ex‐ plaining the reason for the failure).
|
||||
write_result := s.@select(.write, net.connect_timeout)?
|
||||
write_result := s.@select(.write, net.connect_timeout)!
|
||||
err := 0
|
||||
len := sizeof(err)
|
||||
xyz := C.getsockopt(s.handle, C.SOL_SOCKET, C.SO_ERROR, &err, &len)
|
||||
@ -476,17 +476,17 @@ fn (mut s TcpSocket) connect(a Addr) ? {
|
||||
}
|
||||
if write_result {
|
||||
if xyz == 0 {
|
||||
wrap_error(err)?
|
||||
wrap_error(err)!
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
return err_timed_out
|
||||
}
|
||||
wrap_error(ecode)?
|
||||
wrap_error(ecode)!
|
||||
return
|
||||
} $else {
|
||||
x := C.connect(s.handle, voidptr(&a), a.len())
|
||||
socket_error(x)?
|
||||
socket_error(x)!
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,14 @@ pub fn (mut con TcpConn) get_blocking() bool {
|
||||
// when state is true, or non blocking (false).
|
||||
// The default for `net` tcp connections is the non blocking mode.
|
||||
// Calling .read_line will set the connection to blocking mode.
|
||||
pub fn (mut con TcpConn) set_blocking(state bool) ? {
|
||||
pub fn (mut con TcpConn) set_blocking(state bool) ! {
|
||||
con.is_blocking = state
|
||||
$if windows {
|
||||
mut t := u32(0)
|
||||
if !con.is_blocking {
|
||||
t = 1
|
||||
}
|
||||
socket_error(C.ioctlsocket(con.sock.handle, fionbio, &t))?
|
||||
socket_error(C.ioctlsocket(con.sock.handle, fionbio, &t))!
|
||||
} $else {
|
||||
mut flags := C.fcntl(con.sock.handle, C.F_GETFL, 0)
|
||||
if state {
|
||||
@ -37,7 +37,7 @@ pub fn (mut con TcpConn) set_blocking(state bool) ? {
|
||||
} else {
|
||||
flags |= C.O_NONBLOCK
|
||||
}
|
||||
socket_error(C.fcntl(con.sock.handle, C.F_SETFL, flags))?
|
||||
socket_error(C.fcntl(con.sock.handle, C.F_SETFL, flags))!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,8 @@ mut:
|
||||
write_timeout time.Duration
|
||||
}
|
||||
|
||||
pub fn dial_udp(raddr string) ?&UdpConn {
|
||||
addrs := resolve_addrs_fuzzy(raddr, .udp)?
|
||||
pub fn dial_udp(raddr string) !&UdpConn {
|
||||
addrs := resolve_addrs_fuzzy(raddr, .udp)!
|
||||
|
||||
for addr in addrs {
|
||||
// create a local socket for this
|
||||
@ -43,7 +43,7 @@ pub fn dial_udp(raddr string) ?&UdpConn {
|
||||
}
|
||||
}
|
||||
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// pub fn dial_udp(laddr string, raddr string) ?&UdpConn {
|
||||
@ -58,46 +58,46 @@ pub fn dial_udp(raddr string) ?&UdpConn {
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn (mut c UdpConn) write_ptr(b &u8, len int) ?int {
|
||||
pub fn (mut c UdpConn) write_ptr(b &u8, len int) !int {
|
||||
remote := c.sock.remote() or { return err_no_udp_remote }
|
||||
return c.write_to_ptr(remote, b, len)
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) write(buf []u8) ?int {
|
||||
pub fn (mut c UdpConn) write(buf []u8) !int {
|
||||
return c.write_ptr(buf.data, buf.len)
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) write_string(s string) ?int {
|
||||
pub fn (mut c UdpConn) write_string(s string) !int {
|
||||
return c.write_ptr(s.str, s.len)
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) write_to_ptr(addr Addr, b &u8, len int) ?int {
|
||||
pub fn (mut c UdpConn) write_to_ptr(addr Addr, b &u8, len int) !int {
|
||||
res := C.sendto(c.sock.handle, b, len, 0, voidptr(&addr), addr.len())
|
||||
if res >= 0 {
|
||||
return res
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_write()?
|
||||
socket_error(C.sendto(c.sock.handle, b, len, 0, voidptr(&addr), addr.len()))?
|
||||
c.wait_for_write()!
|
||||
socket_error(C.sendto(c.sock.handle, b, len, 0, voidptr(&addr), addr.len()))!
|
||||
} else {
|
||||
wrap_error(code)?
|
||||
wrap_error(code)!
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
// write_to blocks and writes the buf to the remote addr specified
|
||||
pub fn (mut c UdpConn) write_to(addr Addr, buf []u8) ?int {
|
||||
pub fn (mut c UdpConn) write_to(addr Addr, buf []u8) !int {
|
||||
return c.write_to_ptr(addr, buf.data, buf.len)
|
||||
}
|
||||
|
||||
// write_to_string blocks and writes the buf to the remote addr specified
|
||||
pub fn (mut c UdpConn) write_to_string(addr Addr, s string) ?int {
|
||||
pub fn (mut c UdpConn) write_to_string(addr Addr, s string) !int {
|
||||
return c.write_to_ptr(addr, s.str, s.len)
|
||||
}
|
||||
|
||||
// read reads from the socket into buf up to buf.len returning the number of bytes read
|
||||
pub fn (mut c UdpConn) read(mut buf []u8) ?(int, Addr) {
|
||||
pub fn (mut c UdpConn) read(mut buf []u8) !(int, Addr) {
|
||||
mut addr := Addr{
|
||||
addr: AddrData{
|
||||
Ip6: Ip6{}
|
||||
@ -105,40 +105,40 @@ pub fn (mut c UdpConn) read(mut buf []u8) ?(int, Addr) {
|
||||
}
|
||||
len := sizeof(Addr)
|
||||
mut res := wrap_read_result(C.recvfrom(c.sock.handle, voidptr(buf.data), buf.len,
|
||||
0, voidptr(&addr), &len))?
|
||||
0, voidptr(&addr), &len))!
|
||||
if res > 0 {
|
||||
return res, addr
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_read()?
|
||||
c.wait_for_read()!
|
||||
// same setup as in tcp
|
||||
res = wrap_read_result(C.recvfrom(c.sock.handle, voidptr(buf.data), buf.len, 0,
|
||||
voidptr(&addr), &len))?
|
||||
res2 := socket_error(res)?
|
||||
voidptr(&addr), &len))!
|
||||
res2 := socket_error(res)!
|
||||
return res2, addr
|
||||
} else {
|
||||
wrap_error(code)?
|
||||
wrap_error(code)!
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (c &UdpConn) read_deadline() ?time.Time {
|
||||
pub fn (c &UdpConn) read_deadline() !time.Time {
|
||||
if c.read_deadline.unix == 0 {
|
||||
return c.read_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) set_read_deadline(deadline time.Time) {
|
||||
c.read_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (c &UdpConn) write_deadline() ?time.Time {
|
||||
pub fn (c &UdpConn) write_deadline() !time.Time {
|
||||
if c.write_deadline.unix == 0 {
|
||||
return c.write_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) set_write_deadline(deadline time.Time) {
|
||||
@ -162,12 +162,12 @@ pub fn (mut c UdpConn) set_write_timeout(t time.Duration) {
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c UdpConn) wait_for_read() ? {
|
||||
pub fn (mut c UdpConn) wait_for_read() ! {
|
||||
return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c UdpConn) wait_for_write() ? {
|
||||
pub fn (mut c UdpConn) wait_for_write() ! {
|
||||
return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout)
|
||||
}
|
||||
|
||||
@ -176,27 +176,27 @@ pub fn (c &UdpConn) str() string {
|
||||
return 'UdpConn'
|
||||
}
|
||||
|
||||
pub fn (mut c UdpConn) close() ? {
|
||||
pub fn (mut c UdpConn) close() ! {
|
||||
return c.sock.close()
|
||||
}
|
||||
|
||||
pub fn listen_udp(laddr string) ?&UdpConn {
|
||||
addrs := resolve_addrs_fuzzy(laddr, .udp)?
|
||||
pub fn listen_udp(laddr string) !&UdpConn {
|
||||
addrs := resolve_addrs_fuzzy(laddr, .udp)!
|
||||
// TODO(emily):
|
||||
// here we are binding to the first address
|
||||
// and that is probably not ideal
|
||||
addr := addrs[0]
|
||||
return &UdpConn{
|
||||
sock: new_udp_socket(addr)?
|
||||
sock: new_udp_socket(addr)!
|
||||
read_timeout: net.udp_default_read_timeout
|
||||
write_timeout: net.udp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
fn new_udp_socket(local_addr Addr) ?&UdpSocket {
|
||||
fn new_udp_socket(local_addr Addr) !&UdpSocket {
|
||||
family := local_addr.family()
|
||||
|
||||
sockfd := socket_error(C.socket(family, SocketType.udp, 0))?
|
||||
sockfd := socket_error(C.socket(family, SocketType.udp, 0))!
|
||||
mut s := &UdpSocket{
|
||||
handle: sockfd
|
||||
l: local_addr
|
||||
@ -207,28 +207,28 @@ fn new_udp_socket(local_addr Addr) ?&UdpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
s.set_option_bool(.reuse_addr, true)?
|
||||
s.set_option_bool(.reuse_addr, true)!
|
||||
|
||||
if family == .ip6 {
|
||||
s.set_dualstack(true)?
|
||||
s.set_dualstack(true)!
|
||||
}
|
||||
|
||||
$if !net_blocking_sockets ? {
|
||||
// NOTE: refer to comments in tcp.v
|
||||
$if windows {
|
||||
t := u32(1) // true
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t))?
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t))!
|
||||
} $else {
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK))?
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK))!
|
||||
}
|
||||
}
|
||||
|
||||
// cast to the correct type
|
||||
socket_error(C.bind(s.handle, voidptr(&local_addr), local_addr.len()))?
|
||||
socket_error(C.bind(s.handle, voidptr(&local_addr), local_addr.len()))!
|
||||
return s
|
||||
}
|
||||
|
||||
fn new_udp_socket_for_remote(raddr Addr) ?&UdpSocket {
|
||||
fn new_udp_socket_for_remote(raddr Addr) !&UdpSocket {
|
||||
// Invent a sutible local address for this remote addr
|
||||
// Appease compiler
|
||||
mut addr := Addr{
|
||||
@ -246,20 +246,20 @@ fn new_udp_socket_for_remote(raddr Addr) ?&UdpSocket {
|
||||
addr = new_ip6(0, addr_ip6_any)
|
||||
}
|
||||
.unix {
|
||||
addr = temp_unix()?
|
||||
addr = temp_unix()!
|
||||
}
|
||||
else {
|
||||
panic('Invalid family')
|
||||
}
|
||||
}
|
||||
mut sock := new_udp_socket(addr)?
|
||||
mut sock := new_udp_socket(addr)!
|
||||
sock.has_r = true
|
||||
sock.r = raddr
|
||||
|
||||
return sock
|
||||
}
|
||||
|
||||
pub fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) ? {
|
||||
pub fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) ! {
|
||||
// TODO reenable when this `in` operation works again
|
||||
// if opt !in opts_can_set {
|
||||
// return err_option_not_settable
|
||||
@ -268,26 +268,26 @@ pub fn (mut s UdpSocket) set_option_bool(opt SocketOption, value bool) ? {
|
||||
// return err_option_wrong_type
|
||||
// }
|
||||
x := int(value)
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &x, sizeof(int)))?
|
||||
socket_error(C.setsockopt(s.handle, C.SOL_SOCKET, int(opt), &x, sizeof(int)))!
|
||||
}
|
||||
|
||||
pub fn (mut s UdpSocket) set_dualstack(on bool) ? {
|
||||
pub fn (mut s UdpSocket) set_dualstack(on bool) ! {
|
||||
x := int(!on)
|
||||
socket_error(C.setsockopt(s.handle, C.IPPROTO_IPV6, int(SocketOption.ipv6_only), &x,
|
||||
sizeof(int)))?
|
||||
sizeof(int)))!
|
||||
}
|
||||
|
||||
fn (mut s UdpSocket) close() ? {
|
||||
fn (mut s UdpSocket) close() ! {
|
||||
return shutdown(s.handle)
|
||||
}
|
||||
|
||||
fn (mut s UdpSocket) @select(test Select, timeout time.Duration) ?bool {
|
||||
fn (mut s UdpSocket) @select(test Select, timeout time.Duration) !bool {
|
||||
return @select(s.handle, test, timeout)
|
||||
}
|
||||
|
||||
fn (s &UdpSocket) remote() ?Addr {
|
||||
fn (s &UdpSocket) remote() !Addr {
|
||||
if s.has_r {
|
||||
return s.r
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fn echo_server(mut c net.UdpConn) {
|
||||
|
||||
const server_addr = '127.0.0.1:40003'
|
||||
|
||||
fn echo() ? {
|
||||
fn echo() ! {
|
||||
mut c := net.dial_udp(server_addr) or { panic('could not net.dial_udp: $err') }
|
||||
defer {
|
||||
c.close() or {}
|
||||
@ -48,7 +48,7 @@ fn echo() ? {
|
||||
|
||||
println('Got "$buf.bytestr()"')
|
||||
|
||||
c.close()?
|
||||
c.close()!
|
||||
}
|
||||
|
||||
fn test_udp() {
|
||||
|
@ -12,18 +12,18 @@ fn C.SUN_LEN(ptr &C.sockaddr_un) int
|
||||
fn C.strncpy(&char, &char, int)
|
||||
|
||||
// Shutdown shutsdown a socket and closes it
|
||||
fn shutdown(handle int) ? {
|
||||
fn shutdown(handle int) ! {
|
||||
$if windows {
|
||||
C.shutdown(handle, C.SD_BOTH)
|
||||
net.socket_error(C.closesocket(handle))?
|
||||
net.socket_error(C.closesocket(handle))!
|
||||
} $else {
|
||||
C.shutdown(handle, C.SHUT_RDWR)
|
||||
net.socket_error(C.close(handle))?
|
||||
net.socket_error(C.close(handle))!
|
||||
}
|
||||
}
|
||||
|
||||
// Select waits for an io operation (specified by parameter `test`) to be available
|
||||
fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||
set := C.fd_set{}
|
||||
|
||||
C.FD_ZERO(&set)
|
||||
@ -47,13 +47,13 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
|
||||
match test {
|
||||
.read {
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, &set, C.NULL, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.write {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, &set, C.NULL, timeval_timeout))!
|
||||
}
|
||||
.except {
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))?
|
||||
net.socket_error(C.@select(handle + 1, C.NULL, C.NULL, &set, timeval_timeout))!
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,13 +61,13 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
|
||||
}
|
||||
|
||||
// wait_for_common wraps the common wait code
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
|
||||
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ! {
|
||||
if deadline.unix == 0 {
|
||||
// do not accept negative timeout
|
||||
if timeout < 0 {
|
||||
return net.err_timed_out
|
||||
}
|
||||
ready := @select(handle, test, timeout)?
|
||||
ready := @select(handle, test, timeout)!
|
||||
if ready {
|
||||
return
|
||||
}
|
||||
@ -82,7 +82,7 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
|
||||
return net.err_timed_out
|
||||
}
|
||||
|
||||
ready := @select(handle, test, d_timeout)?
|
||||
ready := @select(handle, test, d_timeout)!
|
||||
if ready {
|
||||
return
|
||||
}
|
||||
@ -90,12 +90,12 @@ fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test S
|
||||
}
|
||||
|
||||
// wait_for_write waits for a write io operation to be available
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
fn wait_for_write(handle int, deadline time.Time, timeout time.Duration) ! {
|
||||
return wait_for_common(handle, deadline, timeout, .write)
|
||||
}
|
||||
|
||||
// wait_for_read waits for a read io operation to be available
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ? {
|
||||
fn wait_for_read(handle int, deadline time.Time, timeout time.Duration) ! {
|
||||
return wait_for_common(handle, deadline, timeout, .read)
|
||||
}
|
||||
|
||||
@ -120,9 +120,9 @@ const (
|
||||
)
|
||||
|
||||
[inline]
|
||||
fn wrap_read_result(result int) ?int {
|
||||
fn wrap_read_result(result int) !int {
|
||||
if result != 0 {
|
||||
return result
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
@ -40,23 +40,23 @@ fn error_code() int {
|
||||
return C.errno
|
||||
}
|
||||
|
||||
fn new_stream_socket() ?StreamSocket {
|
||||
sockfd := net.socket_error(C.socket(net.AddrFamily.unix, net.SocketType.tcp, 0))?
|
||||
fn new_stream_socket() !StreamSocket {
|
||||
sockfd := net.socket_error(C.socket(net.AddrFamily.unix, net.SocketType.tcp, 0))!
|
||||
mut s := StreamSocket{
|
||||
handle: sockfd
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) close() ? {
|
||||
fn (mut s StreamSocket) close() ! {
|
||||
return shutdown(s.handle)
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) @select(test Select, timeout time.Duration) ?bool {
|
||||
fn (mut s StreamSocket) @select(test Select, timeout time.Duration) !bool {
|
||||
return @select(s.handle, test, timeout)
|
||||
}
|
||||
|
||||
fn (mut s StreamSocket) connect(a string) ? {
|
||||
fn (mut s StreamSocket) connect(a string) ! {
|
||||
if a.len >= max_sun_path {
|
||||
return error('Socket path too long! Max length: ${max_sun_path - 1} chars.')
|
||||
}
|
||||
@ -73,12 +73,12 @@ fn (mut s StreamSocket) connect(a string) ? {
|
||||
return
|
||||
}
|
||||
_ := error_code()
|
||||
write_result := s.@select(.write, unix.connect_timeout)?
|
||||
write_result := s.@select(.write, unix.connect_timeout)!
|
||||
if write_result {
|
||||
// succeeded
|
||||
return
|
||||
}
|
||||
except_result := s.@select(.except, unix.connect_timeout)?
|
||||
except_result := s.@select(.except, unix.connect_timeout)!
|
||||
if except_result {
|
||||
return net.err_connect_failed
|
||||
}
|
||||
@ -86,11 +86,11 @@ fn (mut s StreamSocket) connect(a string) ? {
|
||||
return net.err_connect_timed_out
|
||||
}
|
||||
|
||||
pub fn listen_stream(sock string) ?&StreamListener {
|
||||
pub fn listen_stream(sock string) !&StreamListener {
|
||||
if sock.len >= max_sun_path {
|
||||
return error('Socket path too long! Max length: ${max_sun_path - 1} chars.')
|
||||
}
|
||||
mut s := new_stream_socket()?
|
||||
mut s := new_stream_socket()!
|
||||
s.path = sock
|
||||
mut addr := C.sockaddr_un{}
|
||||
unsafe { C.memset(&addr, 0, sizeof(C.sockaddr_un)) }
|
||||
@ -98,19 +98,19 @@ pub fn listen_stream(sock string) ?&StreamListener {
|
||||
unsafe { C.strncpy(&addr.sun_path[0], &char(sock.str), max_sun_path) }
|
||||
size := C.SUN_LEN(&addr)
|
||||
if os.exists(sock) {
|
||||
os.rm(sock)?
|
||||
os.rm(sock)!
|
||||
}
|
||||
net.socket_error(C.bind(s.handle, voidptr(&addr), size))?
|
||||
os.chmod(sock, 0o777)?
|
||||
net.socket_error(C.listen(s.handle, 128))?
|
||||
net.socket_error(C.bind(s.handle, voidptr(&addr), size))!
|
||||
os.chmod(sock, 0o777)!
|
||||
net.socket_error(C.listen(s.handle, 128))!
|
||||
return &StreamListener{
|
||||
sock: s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_stream(path string) ?&StreamConn {
|
||||
mut s := new_stream_socket()?
|
||||
s.connect(path)?
|
||||
pub fn connect_stream(path string) !&StreamConn {
|
||||
mut s := new_stream_socket()!
|
||||
s.connect(path)!
|
||||
return &StreamConn{
|
||||
sock: s
|
||||
read_timeout: unix.unix_default_read_timeout
|
||||
@ -118,10 +118,10 @@ pub fn connect_stream(path string) ?&StreamConn {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l StreamListener) accept() ?&StreamConn {
|
||||
pub fn (mut l StreamListener) accept() !&StreamConn {
|
||||
mut new_handle := C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle <= 0 {
|
||||
l.wait_for_accept()?
|
||||
l.wait_for_accept()!
|
||||
new_handle = C.accept(l.sock.handle, 0, 0)
|
||||
if new_handle == -1 || new_handle == 0 {
|
||||
return error('accept failed')
|
||||
@ -137,7 +137,7 @@ pub fn (mut l StreamListener) accept() ?&StreamConn {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &StreamListener) accept_deadline() ?time.Time {
|
||||
pub fn (c &StreamListener) accept_deadline() !time.Time {
|
||||
if c.accept_deadline.unix != 0 {
|
||||
return c.accept_deadline
|
||||
}
|
||||
@ -156,21 +156,21 @@ pub fn (mut c StreamListener) set_accept_timeout(t time.Duration) {
|
||||
c.accept_timeout = t
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) wait_for_accept() ? {
|
||||
pub fn (mut c StreamListener) wait_for_accept() ! {
|
||||
return wait_for_read(c.sock.handle, c.accept_deadline, c.accept_timeout)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamListener) close() ? {
|
||||
os.rm(c.sock.path)?
|
||||
c.sock.close()?
|
||||
pub fn (mut c StreamListener) close() ! {
|
||||
os.rm(c.sock.path)!
|
||||
c.sock.close()!
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) close() ? {
|
||||
c.sock.close()?
|
||||
pub fn (mut c StreamConn) close() ! {
|
||||
c.sock.close()!
|
||||
}
|
||||
|
||||
// write_ptr blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write_ptr(b &u8, len int) ?int {
|
||||
pub fn (mut c StreamConn) write_ptr(b &u8, len int) !int {
|
||||
$if trace_unix ? {
|
||||
eprintln(
|
||||
'>>> StreamConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
@ -186,10 +186,10 @@ pub fn (mut c StreamConn) write_ptr(b &u8, len int) ?int {
|
||||
if sent < 0 {
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_write()?
|
||||
c.wait_for_write()!
|
||||
continue
|
||||
} else {
|
||||
net.wrap_error(code)?
|
||||
net.wrap_error(code)!
|
||||
}
|
||||
}
|
||||
total_sent += sent
|
||||
@ -199,17 +199,17 @@ pub fn (mut c StreamConn) write_ptr(b &u8, len int) ?int {
|
||||
}
|
||||
|
||||
// write blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write(bytes []u8) ?int {
|
||||
pub fn (mut c StreamConn) write(bytes []u8) !int {
|
||||
return c.write_ptr(bytes.data, bytes.len)
|
||||
}
|
||||
|
||||
// write_string blocks and attempts to write all data
|
||||
pub fn (mut c StreamConn) write_string(s string) ?int {
|
||||
pub fn (mut c StreamConn) write_string(s string) !int {
|
||||
return c.write_ptr(s.str, s.len)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read_ptr(buf_ptr &u8, len int) ?int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))?
|
||||
pub fn (mut c StreamConn) read_ptr(buf_ptr &u8, len int) !int {
|
||||
mut res := wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))!
|
||||
$if trace_unix ? {
|
||||
eprintln('<<< StreamConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
@ -218,38 +218,38 @@ pub fn (mut c StreamConn) read_ptr(buf_ptr &u8, len int) ?int {
|
||||
}
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_read()?
|
||||
res = wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))?
|
||||
c.wait_for_read()!
|
||||
res = wrap_read_result(C.recv(c.sock.handle, voidptr(buf_ptr), len, 0))!
|
||||
$if trace_unix ? {
|
||||
eprintln('<<< StreamConn.read_ptr | c.sock.handle: $c.sock.handle | buf_ptr: ${ptr_str(buf_ptr)} len: $len | res: $res')
|
||||
}
|
||||
return net.socket_error(res)
|
||||
} else {
|
||||
net.wrap_error(code)?
|
||||
net.wrap_error(code)!
|
||||
}
|
||||
return net.socket_error(code)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read(mut buf []u8) ?int {
|
||||
pub fn (mut c StreamConn) read(mut buf []u8) !int {
|
||||
return c.read_ptr(buf.data, buf.len)
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) read_deadline() ?time.Time {
|
||||
pub fn (mut c StreamConn) read_deadline() !time.Time {
|
||||
if c.read_deadline.unix == 0 {
|
||||
return c.read_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_read_deadline(deadline time.Time) {
|
||||
c.read_deadline = deadline
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) write_deadline() ?time.Time {
|
||||
pub fn (mut c StreamConn) write_deadline() !time.Time {
|
||||
if c.write_deadline.unix == 0 {
|
||||
return c.write_deadline
|
||||
}
|
||||
return none
|
||||
return error('none')
|
||||
}
|
||||
|
||||
pub fn (mut c StreamConn) set_write_deadline(deadline time.Time) {
|
||||
@ -273,12 +273,12 @@ pub fn (mut c StreamConn) set_write_timeout(t time.Duration) {
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c StreamConn) wait_for_read() ? {
|
||||
pub fn (mut c StreamConn) wait_for_read() ! {
|
||||
return wait_for_read(c.sock.handle, c.read_deadline, c.read_timeout)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (mut c StreamConn) wait_for_write() ? {
|
||||
pub fn (mut c StreamConn) wait_for_write() ! {
|
||||
return wait_for_write(c.sock.handle, c.write_deadline, c.write_timeout)
|
||||
}
|
||||
|
||||
|
@ -27,22 +27,22 @@ fn handle_conn(mut c unix.StreamConn) {
|
||||
}
|
||||
}
|
||||
|
||||
fn echo_server(mut l unix.StreamListener) ? {
|
||||
fn echo_server(mut l unix.StreamListener) ! {
|
||||
for {
|
||||
mut new_conn := l.accept() or { continue }
|
||||
go handle_conn(mut new_conn)
|
||||
}
|
||||
}
|
||||
|
||||
fn echo() ? {
|
||||
mut c := unix.connect_stream(test_port)?
|
||||
fn echo() ! {
|
||||
mut c := unix.connect_stream(test_port)!
|
||||
defer {
|
||||
c.close() or {}
|
||||
}
|
||||
data := 'Hello from vlib/net!'
|
||||
c.write_string(data)?
|
||||
c.write_string(data)!
|
||||
mut buf := []u8{len: 4096}
|
||||
read := c.read(mut buf)?
|
||||
read := c.read(mut buf)!
|
||||
assert read == data.len
|
||||
for i := 0; i < read; i++ {
|
||||
assert buf[i] == data[i]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user