commit 652f7aa04033bb6091378168fb45ce6970f72473
parent 64f03254705d37d95ccde4040c9d5b07716b3bd4
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 2 Feb 2021 16:14:37 -0500
io::copy: use io::unsupported to force fallback
Diffstat:
3 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/io/copy.ha b/io/copy.ha
@@ -3,7 +3,13 @@
export fn copy(dest: *stream, src: *stream) (error | size) = {
match (dest.copier) {
null => void,
- c: *copier => return c(dest, src),
+ c: *copier => match (c(dest, src)) {
+ err: error => match (err) {
+ unsupported => void, // Use fallback
+ * => return err,
+ },
+ s: size => return s,
+ },
};
let w = 0z;
diff --git a/io/types.ha b/io/types.ha
@@ -53,6 +53,8 @@ export type closer = fn(s: *stream) void;
// with a stream which does not implement this (it falls back to calling read
// and write in a loop).
//
-// Returns the number of bytes copied, or an error if one occured. Does not
-// close either stream.
+// Returns the number of bytes copied, or an error if one occured. Do not close
+// either stream. If the operation is unsupported for this particular pair of
+// streams, return [io::unsupported] to have [io::copy] proceed with its
+// fallback implementation.
export type copier = fn(to: *stream, from: *stream) (size | error);
diff --git a/os/+linux/fdstream.ha b/os/+linux/fdstream.ha
@@ -91,7 +91,7 @@ def SENDFILE_MAX: size = 2147479552z;
fn fd_copy(_to: *io::stream, _from: *io::stream) (size | io::error) = {
if (!is_fdstream(_from)) {
- return copy_fallback(_to, _from);
+ return io::unsupported;
};
let to = _to: *fd_stream, from = _from: *fd_stream;
@@ -102,8 +102,10 @@ fn fd_copy(_to: *io::stream, _from: *io::stream) (size | io::error) = {
let n = match(rt::wrap_return(r)) {
err: rt::errno => switch (err) {
rt::EINVAL => {
- assert(sum == 0z);
- return copy_fallback(_to, _from);
+ if (sum == 0z) {
+ return io::unsupported;
+ };
+ return errno_to_io(err);
},
* => return errno_to_io(err),
},
@@ -119,9 +121,3 @@ fn fd_copy(_to: *io::stream, _from: *io::stream) (size | io::error) = {
};
return sum;
};
-
-fn copy_fallback(_to: *io::stream, _from: *io::stream) (size | io::error) = {
- let to = _to: *fd_stream, temp = *to;
- temp.stream.copier = null;
- return io::copy(&temp.stream, _from);
-};