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

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

This commit is contained in:
yuyi 2022-10-16 14:28:57 +08:00 committed by GitHub
parent 6e46933c55
commit f6844e9766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
187 changed files with 1885 additions and 1874 deletions

View File

@ -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

View File

@ -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(['<', '&lt;', '>', '&gt;'])
@ -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')
}

View File

@ -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

View File

@ -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).')

View File

@ -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:

View File

@ -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.')

View File

@ -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')
}

View File

@ -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 {

View File

@ -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)

View File

@ -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 {

View File

@ -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), '')

View File

@ -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() {

View File

@ -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() {

View File

@ -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')

View File

@ -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 {

View File

@ -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,

View File

@ -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()

View File

@ -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' }

View File

@ -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 {

View File

@ -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)!
}

View File

@ -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) {

View File

@ -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]

View File

@ -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)

View File

@ -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)

View File

@ -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.')

View File

@ -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)) {

View File

@ -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()
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
}

View File

@ -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()

View File

@ -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 {

View File

@ -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
}

View File

@ -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')
}

View File

@ -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 }

View File

@ -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
}

View File

@ -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

View File

@ -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')
}

View File

@ -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')
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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()

View File

@ -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
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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')

View File

@ -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) }

View File

@ -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')

View File

@ -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

View File

@ -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')
}

View File

@ -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()
}

View File

@ -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) }

View File

@ -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')

View File

@ -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
}

View File

@ -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++ {

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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))!
}
}

View File

@ -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 {

View File

@ -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))!
}
}

View File

@ -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)!
}

View File

@ -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)
}

View File

@ -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}
}

View File

@ -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}
}

View File

@ -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)!
}
}

View File

@ -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))!
}
}

View File

@ -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')
}

View File

@ -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() {

View File

@ -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')
}

View File

@ -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)
}

View File

@ -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