diff --git a/docker.v b/docker.v index 2963f0d..97cd24a 100644 --- a/docker.v +++ b/docker.v @@ -24,8 +24,8 @@ mut: } // new_conn creates a new connection to the Docker daemon. -pub fn new_conn() ?&DockerConn { - s := unix.connect_stream(docker.socket)? +pub fn new_conn() !&DockerConn { + s := unix.connect_stream(docker.socket)! d := &DockerConn{ socket: s @@ -36,27 +36,27 @@ pub fn new_conn() ?&DockerConn { } // close closes the underlying socket connection. -pub fn (mut d DockerConn) close() ? { - d.socket.close()? +pub fn (mut d DockerConn) close() ! { + d.socket.close()! } // send_request sends an HTTP request without body. -fn (mut d DockerConn) send_request(method http.Method, url_str string) ? { - url := urllib.parse('/$docker.api_version$url_str')? +fn (mut d DockerConn) send_request(method http.Method, url_str string) ! { + url := urllib.parse('/$docker.api_version$url_str')! req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n' - d.socket.write_string(req)? + d.socket.write_string(req)! // When starting a new request, the reader needs to be reset. d.reader = io.new_buffered_reader(reader: d.socket) } // send_request_with_body sends an HTTP request with the given body. -fn (mut d DockerConn) send_request_with_body(method http.Method, url_str string, content_type string, body string) ? { - url := urllib.parse('/$docker.api_version$url_str')? +fn (mut d DockerConn) send_request_with_body(method http.Method, url_str string, content_type string, body string) ! { + url := urllib.parse('/$docker.api_version$url_str')! req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Type: $content_type\nContent-Length: $body.len\n\n$body\n\n' - d.socket.write_string(req)? + d.socket.write_string(req)! // When starting a new request, the reader needs to be reset. d.reader = io.new_buffered_reader(reader: d.socket) @@ -64,7 +64,7 @@ fn (mut d DockerConn) send_request_with_body(method http.Method, url_str string, // send_request_with_json is a convenience wrapper around // send_request_with_body that encodes the input as JSON. -fn (mut d DockerConn) send_request_with_json(method http.Method, url_str string, data &T) ? { +fn (mut d DockerConn) send_request_with_json(method http.Method, url_str string, data &T) ! { body := json.encode(data) return d.send_request_with_body(method, url_str, 'application/json', body) @@ -74,17 +74,17 @@ fn (mut d DockerConn) send_request_with_json(method http.Method, url_str stri // '\r\n\r\n', after which it parses the response as an HTTP response. // Importantly, this function never consumes the reader past the HTTP // separator, so the body can be read fully later on. -fn (mut d DockerConn) read_response_head() ?http.Response { +fn (mut d DockerConn) read_response_head() !http.Response { mut res := []u8{} - util.read_until_separator(mut d.reader, mut res, docker.http_separator)? + util.read_until_separator(mut d.reader, mut res, docker.http_separator)! return http.parse_response(res.bytestr()) } // read_response_body reads `length` bytes from the stream. It can be used when // the response encoding isn't chunked to fully read it. -fn (mut d DockerConn) read_response_body(length int) ?string { +fn (mut d DockerConn) read_response_body(length int) !string { if length == 0 { return '' } @@ -96,7 +96,7 @@ fn (mut d DockerConn) read_response_body(length int) ?string { for builder.len < length { c = d.reader.read(mut buf) or { break } - builder.write(buf[..c])? + builder.write(buf[..c])! } return builder.str() @@ -105,34 +105,34 @@ fn (mut d DockerConn) read_response_body(length int) ?string { // read_response is a convenience function which always consumes the entire // response & returns it. It should only be used when we're certain that the // result isn't too large. -fn (mut d DockerConn) read_response() ?(http.Response, string) { - head := d.read_response_head()? +fn (mut d DockerConn) read_response() !(http.Response, string) { + head := d.read_response_head()! if head.header.get(http.CommonHeader.transfer_encoding) or { '' } == 'chunked' { mut builder := strings.new_builder(1024) mut body := d.get_chunked_response_reader() - util.reader_to_writer(mut body, mut builder)? + util.reader_to_writer(mut body, mut builder)! return head, builder.str() } - content_length := head.header.get(http.CommonHeader.content_length)?.int() - res := d.read_response_body(content_length)? + content_length := head.header.get(http.CommonHeader.content_length)!.int() + res := d.read_response_body(content_length)! return head, res } -fn (mut d DockerConn) read_json_response() ?T { - head, body := d.read_response()? +fn (mut d DockerConn) read_json_response() !T { + head, body := d.read_response()! if head.status_code < 200 || head.status_code > 300 { - data := json.decode(DockerError, body)? + data := json.decode(DockerError, body)! return docker_error(head.status_code, data.message) } - mut data := json.decode(T, body)? + mut data := json.decode(T, body)! //$for field in T.fields { //$if field.typ is time.Time { diff --git a/stream.v b/stream.v index 001f4b3..39ab42a 100644 --- a/stream.v +++ b/stream.v @@ -25,11 +25,11 @@ pub fn new_chunked_response_reader(reader io.BufferedReader) &ChunkedResponseRea } // read satisfies the io.Reader interface. -pub fn (mut r ChunkedResponseReader) read(mut buf []u8) ?int { +pub fn (mut r ChunkedResponseReader) read(mut buf []u8) !int { if r.bytes_left_in_chunk == 0 { // An io.BufferedReader always returns none if its stream has // ended. - r.bytes_left_in_chunk = r.read_chunk_size()? + r.bytes_left_in_chunk = r.read_chunk_size()! } mut c := 0 @@ -37,9 +37,9 @@ pub fn (mut r ChunkedResponseReader) read(mut buf []u8) ?int { // Make sure we don't read more than we can safely read. This is to avoid // the underlying reader from becoming out of sync with our parsing: if buf.len > r.bytes_left_in_chunk { - c = r.reader.read(mut buf[..r.bytes_left_in_chunk])? + c = r.reader.read(mut buf[..r.bytes_left_in_chunk])! } else { - c = r.reader.read(mut buf)? + c = r.reader.read(mut buf)! } r.bytes_left_in_chunk -= u64(c) @@ -50,21 +50,21 @@ pub fn (mut r ChunkedResponseReader) read(mut buf []u8) ?int { // read_chunk_size advances the reader & reads the size of the next HTTP chunk. // This function should only be called if the previous chunk has been // completely consumed. -fn (mut r ChunkedResponseReader) read_chunk_size() ?u64 { +fn (mut r ChunkedResponseReader) read_chunk_size() !u64 { if r.started { mut buf := []u8{len: 2} // Each chunk ends with a `\r\n` which we want to skip first - r.reader.read(mut buf)? + r.reader.read(mut buf)! } r.started = true mut res := []u8{} - util.read_until_separator(mut r.reader, mut res, http_chunk_separator)? + util.read_until_separator(mut r.reader, mut res, http_chunk_separator)! // The length of the next chunk is provided as a hexadecimal - mut num_data := hex.decode(res#[..-2].bytestr())? + mut num_data := hex.decode(res#[..-2].bytestr())! for num_data.len < 8 { num_data.insert(0, 0) @@ -75,7 +75,7 @@ fn (mut r ChunkedResponseReader) read_chunk_size() ?u64 { // This only occurs for the very last chunk, which always reports a size of // 0. if num == 0 { - return none + return error('end of stream') } return num @@ -100,17 +100,17 @@ pub fn new_stream_format_reader(reader ChunkedResponseReader) &StreamFormatReade } // read satisfies the io.Reader interface. -pub fn (mut r StreamFormatReader) read(mut buf []u8) ?int { +pub fn (mut r StreamFormatReader) read(mut buf []u8) !int { if r.bytes_left_in_chunk == 0 { - r.bytes_left_in_chunk = r.read_chunk_size()? + r.bytes_left_in_chunk = r.read_chunk_size()! } mut c := 0 if buf.len > r.bytes_left_in_chunk { - c = r.reader.read(mut buf[..r.bytes_left_in_chunk])? + c = r.reader.read(mut buf[..r.bytes_left_in_chunk])! } else { - c = r.reader.read(mut buf)? + c = r.reader.read(mut buf)! } r.bytes_left_in_chunk -= u32(c) @@ -120,15 +120,15 @@ pub fn (mut r StreamFormatReader) read(mut buf []u8) ?int { // read_chunk_size advances the reader & reads the header bytes for the length // of the next chunk. -fn (mut r StreamFormatReader) read_chunk_size() ?u32 { +fn (mut r StreamFormatReader) read_chunk_size() !u32 { mut buf := []u8{len: 8} - r.reader.read(mut buf)? + r.reader.read(mut buf)! num := binary.big_endian_u32(buf[4..]) if num == 0 { - return none + return error('end of stream') } return num diff --git a/util/util.v b/util/util.v index 412e39c..1181480 100644 --- a/util/util.v +++ b/util/util.v @@ -3,7 +3,7 @@ module util import io // reader_to_writer tries to consume the entire reader & write it to the writer. -pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ? { +pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! { mut buf := []u8{len: 10 * 1024} for { @@ -39,11 +39,11 @@ pub fn match_array_in_array(a1 []T, a2 []T) int { // read_until_separator consumes an io.Reader until it encounters some // separator array. The data read is stored inside the provided res array. -pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ? { +pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ! { mut buf := []u8{len: sep.len} for { - c := reader.read(mut buf)? + c := reader.read(mut buf)! res << buf[..c] match_len := match_array_in_array(buf[..c], sep) @@ -54,7 +54,7 @@ pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ? { if match_len > 0 { match_left := sep.len - match_len - c2 := reader.read(mut buf[..match_left])? + c2 := reader.read(mut buf[..match_left])! res << buf[..c2] if buf[..c2] == sep[match_len..] {