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

all: require calling optfn() ? / optfn() or {...} for fn optfn() ? {}

This commit is contained in:
Delyan Angelov
2021-01-26 16:43:10 +02:00
parent 97103f680a
commit e5a84719ca
90 changed files with 1994 additions and 1832 deletions

View File

@@ -36,7 +36,7 @@ pub fn socket_error(potential_code int) ?int {
pub fn wrap_error(error_code int) ? {
$if windows {
enum_error := wsa_error(error_code)
return error_with_code('socket error: $enum_error', error_code)
return error_with_code('net: socket error: $enum_error', error_code)
}
$else {
if error_code == 0 {

View File

@@ -36,7 +36,7 @@ const (
struct DTP {
mut:
conn net.TcpConn
conn &net.TcpConn
reader io.BufferedReader
ip string
port int
@@ -56,31 +56,31 @@ fn (mut dtp DTP) read() ?[]byte {
}
fn (mut dtp DTP) close() {
dtp.conn.close()
dtp.conn.close() or { panic(err) }
}
struct FTP {
mut:
conn net.TcpConn
conn &net.TcpConn
reader io.BufferedReader
buffer_size int
}
pub fn new() FTP {
mut f := FTP{}
mut f := FTP{ conn: 0 }
f.buffer_size = 1024
return f
}
fn (mut ftp FTP) write(data string) ? {
fn (mut zftp FTP) write(data string) ? {
$if debug {
println('FTP.v >>> $data')
}
ftp.conn.write('$data\r\n'.bytes()) ?
zftp.conn.write('$data\r\n'.bytes()) ?
}
fn (mut ftp FTP) read() ?(int, string) {
mut data := ftp.reader.read_line() ?
fn (mut zftp FTP) read() ?(int, string) {
mut data := zftp.reader.read_line() ?
$if debug {
println('FTP.v <<< $data')
}
@@ -90,7 +90,7 @@ fn (mut ftp FTP) read() ?(int, string) {
code := data[..3].int()
if data[3] == `-` {
for {
data = ftp.reader.read_line() ?
data = zftp.reader.read_line() ?
if data[..3].int() == code && data[3] != `-` {
break
}
@@ -99,51 +99,51 @@ fn (mut ftp FTP) read() ?(int, string) {
return code, data
}
pub fn (mut ftp FTP) connect(ip string) ?bool {
ftp.conn = net.dial_tcp('$ip:21') ?
ftp.reader = io.new_buffered_reader(reader: io.make_reader(ftp.conn))
code, _ := ftp.read() ?
if code == connected {
pub fn (mut zftp FTP) connect(ip string) ?bool {
zftp.conn = net.dial_tcp('$ip:21') ?
zftp.reader = io.new_buffered_reader(reader: io.make_reader(zftp.conn))
code, _ := zftp.read() ?
if code == ftp.connected {
return true
}
return false
}
pub fn (mut ftp FTP) login(user string, passwd string) ?bool {
ftp.write('USER $user') or {
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, _ := ftp.read() ?
if code == logged_in {
mut code, _ := zftp.read() ?
if code == ftp.logged_in {
return true
}
if code != specify_password {
if code != ftp.specify_password {
return false
}
ftp.write('PASS $passwd') or {
zftp.write('PASS $passwd') or {
$if debug {
println('ERROR sending password')
}
return false
}
code, _ = ftp.read() ?
if code == logged_in {
code, _ = zftp.read() ?
if code == ftp.logged_in {
return true
}
return false
}
pub fn (mut ftp FTP) close() ? {
ftp.write('QUIT') ?
ftp.conn.close()
pub fn (mut zftp FTP) close() ? {
zftp.write('QUIT') ?
zftp.conn.close() ?
}
pub fn (mut ftp FTP) pwd() ?string {
ftp.write('PWD') ?
_, data := ftp.read() ?
pub fn (mut zftp FTP) pwd() ?string {
zftp.write('PWD') ?
_, data := zftp.read() ?
spl := data.split('"') // "
if spl.len >= 2 {
return spl[1]
@@ -151,17 +151,17 @@ pub fn (mut ftp FTP) pwd() ?string {
return data
}
pub fn (mut ftp FTP) cd(dir string) ? {
ftp.write('CWD $dir') or { return }
mut code, mut data := ftp.read() ?
pub fn (mut zftp FTP) cd(dir string) ? {
zftp.write('CWD $dir') or { return }
mut code, mut data := zftp.read() ?
match int(code) {
denied {
ftp.denied {
$if debug {
println('CD $dir denied!')
}
}
complete {
code, data = ftp.read() ?
ftp.complete {
code, data = zftp.read() ?
}
else {}
}
@@ -178,6 +178,7 @@ fn new_dtp(msg string) ?&DTP {
mut dtp := &DTP{
ip: ip
port: port
conn: 0
}
conn := net.dial_tcp('$ip:$port') or { return error('Cannot connect to the data channel') }
dtp.conn = conn
@@ -185,32 +186,32 @@ fn new_dtp(msg string) ?&DTP {
return dtp
}
fn (mut ftp FTP) pasv() ?&DTP {
ftp.write('PASV') ?
code, data := ftp.read() ?
fn (mut zftp FTP) pasv() ?&DTP {
zftp.write('PASV') ?
code, data := zftp.read() ?
$if debug {
println('pass: $data')
}
if code != passive_mode {
if code != ftp.passive_mode {
return error('pasive mode not allowed')
}
dtp := new_dtp(data) ?
return dtp
}
pub fn (mut ftp FTP) dir() ?[]string {
mut dtp := ftp.pasv() or { return error('Cannot establish data connection') }
ftp.write('LIST') ?
code, _ := ftp.read() ?
if code == denied {
pub fn (mut zftp FTP) dir() ?[]string {
mut dtp := zftp.pasv() or { return error('Cannot establish data connection') }
zftp.write('LIST') ?
code, _ := zftp.read() ?
if code == ftp.denied {
return error('`LIST` denied')
}
if code != open_data_connection {
if code != ftp.open_data_connection {
return error('Data channel empty')
}
list_dir := dtp.read() ?
result, _ := ftp.read() ?
if result != close_data_connection {
result, _ := zftp.read() ?
if result != ftp.close_data_connection {
println('`LIST` not ok')
}
dtp.close()
@@ -225,14 +226,14 @@ pub fn (mut ftp FTP) dir() ?[]string {
return dir
}
pub fn (mut ftp FTP) get(file string) ?[]byte {
mut dtp := ftp.pasv() or { return error('Cannot stablish data connection') }
ftp.write('RETR $file') ?
code, _ := ftp.read() ?
if code == denied {
pub fn (mut zftp FTP) get(file string) ?[]byte {
mut dtp := zftp.pasv() or { return error('Cannot stablish data connection') }
zftp.write('RETR $file') ?
code, _ := zftp.read() ?
if code == ftp.denied {
return error('Permission denied')
}
if code != open_data_connection {
if code != ftp.open_data_connection {
return error('Data connection not ready')
}
blob := dtp.read() ?

View File

@@ -1,42 +1,49 @@
import net.ftp
// NB: this function makes network calls to external servers,
// that is why it is not a very good idea to run it in CI.
// If you want to run it manually, use `v -d network vlib/net/ftp/ftp_test.v`
fn ftp_client_test_inside() ? {
$if !network ? { return }
mut ftp := ftp.new()
defer {
ftp.close()
fn test_ftp_cleint() {
$if !network ? {
return
}
connect_result := ftp.connect('ftp.redhat.com')?
// NB: this function makes network calls to external servers,
// that is why it is not a very good idea to run it in CI.
// If you want to run it manually, use:
// `v -d network vlib/net/ftp/ftp_test.v`
ftp_client_test_inside() or { panic(err) }
}
fn ftp_client_test_inside() ? {
mut zftp := ftp.new()
// eprintln(zftp)
defer {
zftp.close() or { panic(err) }
}
connect_result := zftp.connect('ftp.redhat.com') ?
assert connect_result
login_result := ftp.login('ftp', 'ftp')?
login_result := zftp.login('ftp', 'ftp') ?
assert login_result
pwd := ftp.pwd()?
pwd := zftp.pwd() ?
assert pwd.len > 0
ftp.cd('/')
dir_list1 := ftp.dir() or {
zftp.cd('/') or {
assert false
return
}
dir_list1 := zftp.dir() or {
assert false
return
}
assert dir_list1.len > 0
ftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/')
dir_list2 := ftp.dir() or {
zftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/') or {
assert false
return
}
dir_list2 := zftp.dir() or {
assert false
return
}
assert dir_list2.len > 0
blob := ftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
blob := zftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
assert false
return
}
assert blob.len > 0
}
fn test_ftp_cleint() {
ftp_client_test_inside() or {
panic(err)
}
}

View File

@@ -5,13 +5,11 @@ module http
import os
pub fn download_file(url string, out string)? {
$if debug_http? {
pub fn download_file(url string, out string) ? {
$if debug_http ? {
println('download file url=$url out=$out')
}
s := get(url) or {
return error(err)
}
os.write_file(out, s.text)
s := get(url) or { return error(err) }
os.write_file(out, s.text) ?
// download_file_with_progress(url, out, empty, empty)
}

View File

@@ -67,33 +67,48 @@ pub fn get(url string) ?Response {
}
pub fn post(url string, data string) ?Response {
return fetch_with_method(.post, url, data: data, headers: {
'Content-Type': content_type_default
})
return fetch_with_method(.post, url,
data: data
headers: {
'Content-Type': http.content_type_default
}
)
}
pub fn post_json(url string, data string) ?Response {
return fetch_with_method(.post, url, data: data, headers: {
return fetch_with_method(.post, url,
data: data
headers: {
'Content-Type': 'application/json'
})
}
)
}
pub fn post_form(url string, data map[string]string) ?Response {
return fetch_with_method(.post, url, headers: {
return fetch_with_method(.post, url,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}, data: url_encode_form_data(data))
}
data: url_encode_form_data(data)
)
}
pub fn put(url string, data string) ?Response {
return fetch_with_method(.put, url, data: data, headers: {
'Content-Type': content_type_default
})
return fetch_with_method(.put, url,
data: data
headers: {
'Content-Type': http.content_type_default
}
)
}
pub fn patch(url string, data string) ?Response {
return fetch_with_method(.patch, url, data: data, headers: {
'Content-Type': content_type_default
})
return fetch_with_method(.patch, url,
data: data
headers: {
'Content-Type': http.content_type_default
}
)
}
pub fn head(url string) ?Response {
@@ -165,11 +180,11 @@ fn build_url_from_fetch(_url string, config FetchConfig) ?string {
}
fn (mut req Request) free() {
unsafe {req.headers.free()}
unsafe { req.headers.free() }
}
fn (mut resp Response) free() {
unsafe {resp.headers.free()}
unsafe { resp.headers.free() }
}
// add_header adds the key and value of an HTTP request header
@@ -199,8 +214,8 @@ pub fn (req &Request) do() ?Response {
mut resp := Response{}
mut no_redirects := 0
for {
if no_redirects == max_redirects {
return error('http.request.do: maximum number of redirects reached ($max_redirects)')
if no_redirects == http.max_redirects {
return error('http.request.do: maximum number of redirects reached ($http.max_redirects)')
}
qresp := req.method_and_url_to_response(req.method, rurl) ?
resp = qresp
@@ -366,7 +381,7 @@ fn (req &Request) http_do(host string, method Method, path string) ?Response {
// TODO this really needs to be exposed somehow
client.write(s.bytes()) ?
mut bytes := io.read_all(reader: client) ?
client.close()
client.close() ?
return parse_response(bytes.bytestr())
}

View File

@@ -96,8 +96,8 @@ 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)
c.send_str('QUIT\r\n') ?
c.expect_reply(.close) ?
c.conn.close() ?
c.is_open = false
}
@@ -166,7 +166,7 @@ fn (mut c Client) send_mailto(to string) ? {
fn (mut c Client) send_data() ? {
c.send_str('DATA\r\n') ?
c.expect_reply(.mail_start)
c.expect_reply(.mail_start) ?
}
fn (mut c Client) send_body(cfg Mail) ? {

View File

@@ -22,8 +22,8 @@ pub fn dial_tcp(address string) ?&TcpConn {
s.connect(address) ?
return &TcpConn{
sock: s
read_timeout: tcp_default_read_timeout
write_timeout: tcp_default_write_timeout
read_timeout: net.tcp_default_read_timeout
write_timeout: net.tcp_default_write_timeout
}
}
@@ -35,7 +35,8 @@ pub fn (mut c TcpConn) close() ? {
// write_ptr blocks and attempts to write all data
pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
$if trace_tcp ? {
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
eprintln(
'>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
unsafe { b.vstring_with_len(len) })
}
unsafe {
@@ -48,7 +49,7 @@ pub fn (mut c TcpConn) write_ptr(b byteptr, len 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) ?
@@ -164,9 +165,9 @@ pub fn (c &TcpConn) peer_ip() ?string {
return res
}
pub fn (c &TcpConn) str() string {
// TODO
return 'TcpConn {write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $c.sock}'
pub fn (c TcpConn) str() string {
s := c.sock.str().replace('\n', ' ').replace(' ', ' ')
return 'TcpConn{ write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $s }'
}
pub struct TcpListener {
@@ -213,8 +214,8 @@ pub fn (mut l TcpListener) accept() ?&TcpConn {
new_sock := tcp_socket_from_handle(new_handle) ?
return &TcpConn{
sock: new_sock
read_timeout: tcp_default_read_timeout
write_timeout: tcp_default_write_timeout
read_timeout: net.tcp_default_read_timeout
write_timeout: net.tcp_default_write_timeout
}
}
@@ -266,7 +267,7 @@ fn new_tcp_socket() ?TcpSocket {
t := true
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
}
@@ -281,7 +282,7 @@ fn tcp_socket_from_handle(sockfd int) ?TcpSocket {
t := true
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
}
@@ -322,12 +323,12 @@ fn (mut s TcpSocket) connect(a string) ? {
return none
}
_ := error_code()
write_result := s.@select(.write, connect_timeout) ?
write_result := s.@select(.write, net.connect_timeout) ?
if write_result {
// succeeded
return none
}
except_result := s.@select(.except, connect_timeout) ?
except_result := s.@select(.except, net.connect_timeout) ?
if except_result {
return err_connect_failed
}

View File

@@ -64,7 +64,10 @@ fn test_socket_write_and_read() {
message1 := 'a message 1'
socket.write_str(message1) or { assert false }
mut rbuf := []byte{len: message1.len}
client.read(mut rbuf)
client.read(mut rbuf) or {
assert false
return
}
line := rbuf.bytestr()
assert line == message1
}
@@ -127,8 +130,14 @@ fn test_socket_read_line_long_line_without_eol() {
cleanup(mut server, mut client, mut socket)
}
message := strings.repeat_string('123', 400)
socket.write_str(message)
socket.write_str('\n')
socket.write_str(message) or {
assert false
return
}
socket.write_str('\n') or {
assert false
return
}
line := reader.read_line() or {
assert false
return

View File

@@ -33,8 +33,8 @@ pub fn dial_udp(laddr string, raddr string) ?&UdpConn {
}
return &UdpConn{
sock: sock
read_timeout: udp_default_read_timeout
write_timeout: udp_default_write_timeout
read_timeout: net.udp_default_read_timeout
write_timeout: net.udp_default_write_timeout
}
}
@@ -162,8 +162,8 @@ pub fn listen_udp(port int) ?&UdpConn {
s := new_udp_socket(port) ?
return &UdpConn{
sock: s
read_timeout: udp_default_read_timeout
write_timeout: udp_default_write_timeout
read_timeout: net.udp_default_read_timeout
write_timeout: net.udp_default_write_timeout
}
}
@@ -183,7 +183,7 @@ fn new_udp_socket(local_port int) ?&UdpSocket {
t := true
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)) ?
}
// In UDP we always have to bind to a port
validate_port(local_port) ?

View File

@@ -53,8 +53,8 @@ fn should_escape(c byte, mode EncodingMode) bool {
// we could possibly allow, and parse will reject them if we
// escape them (because hosts can`t use %-encoding for
// ASCII bytes).
if c in
[`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
if
c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
return false
}
}
@@ -162,7 +162,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
if s.len > 3 {
s = s[..3]
}
return error(error_msg(err_msg_escape, s))
return error(error_msg(urllib.err_msg_escape, s))
}
// Per https://tools.ietf.org/html/rfc3986#page-21
// in the host component %-encoding can only be used
@@ -171,7 +171,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
// introduces %25 being allowed to escape a percent sign
// in IPv6 scoped-address literals. Yay.
if mode == .encode_host && unhex(s[i + 1]) < 8 && s[i..i + 3] != '%25' {
return error(error_msg(err_msg_escape, s[i..i + 3]))
return error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
}
if mode == .encode_zone {
// RFC 6874 says basically 'anything goes' for zone identifiers
@@ -183,7 +183,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
// But Windows puts spaces here! Yay.
v := ((unhex(s[i + 1]) << byte(4)) | unhex(s[i + 2]))
if s[i..i + 3] != '%25' && v != ` ` && should_escape(v, .encode_host) {
error(error_msg(err_msg_escape, s[i..i + 3]))
error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
}
}
i += 3
@@ -193,9 +193,8 @@ fn unescape(s_ string, mode EncodingMode) ?string {
i++
}
else {
if (mode == .encode_host ||
mode == .encode_zone) &&
s[i] < 0x80 && should_escape(s[i], mode) {
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80
&& should_escape(s[i], mode) {
error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
}
i++
@@ -429,11 +428,12 @@ fn split(s string, sep byte, cutc bool) (string, string) {
pub fn parse(rawurl string) ?URL {
// Cut off #frag
u, frag := split(rawurl, `#`, true)
mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) }
mut url := parse_url(u, false) or { return error(error_msg(urllib.err_msg_parse, u)) }
if frag == '' {
return url
}
f := unescape(frag, .encode_fragment) or { return error(error_msg(err_msg_parse, u)) }
f := unescape(frag, .encode_fragment) or { return error(error_msg(urllib.err_msg_parse,
u)) }
url.fragment = f
return url
}
@@ -570,7 +570,7 @@ fn parse_host(host string) ?string {
// parse an IP-Literal in RFC 3986 and RFC 6874.
// E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'.
mut i := host.last_index(']') or {
return error(error_msg("parse_host: missing \']\' in host", ''))
return error(error_msg("parse_host: missing ']' in host", ''))
}
mut colon_port := host[i + 1..]
if !valid_optional_port(colon_port) {
@@ -785,7 +785,7 @@ pub fn parse_query(query string) ?Values {
// but any errors will be silent
fn parse_query_silent(query string) Values {
mut m := new_values()
parse_query_values(mut m, query)
parse_query_values(mut m, query) or { }
return m
}
@@ -1029,7 +1029,8 @@ pub fn valid_userinfo(s string) bool {
continue
}
match r {
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` {
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`,
`@` {
continue
}
else {