copy.ha (1389B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use errors; 5 6 // Copies data from one handle into another. If reading from the source file 7 // returns zero (underread), the copy is terminated and the amount of data 8 // copied is returned. Note that this function will never return if the source 9 // handle is infinite. 10 export fn copy(dest: handle, src: handle) (size | error) = { 11 match (dest) { 12 case let fd: file => 13 if (src is file) { 14 match (fd_copy(fd, src as file)) { 15 case let err: error => 16 if (!(err is errors::unsupported)) { 17 return err; 18 }; 19 // Use fallback 20 case let z: size => 21 return z; 22 }; 23 }; 24 return copy_fallback(dest, src); 25 case let st: *stream => 26 if (!(src is *stream)) { 27 return copy_fallback(dest, src); 28 }; 29 return copy_streams(st, src as *stream); 30 }; 31 }; 32 33 fn copy_streams(dest: *stream, src: *stream) (size | error) = { 34 match (dest.copier) { 35 case null => void; 36 case let c: *copier => 37 match (c(dest, src)) { 38 case let err: error => 39 match (err) { 40 case errors::unsupported => void; 41 case => 42 return err; 43 }; 44 case let s: size => 45 return s; 46 }; 47 }; 48 return copy_fallback(dest, src); 49 }; 50 51 fn copy_fallback(dest: handle, src: handle) (size | error) = { 52 let w = 0z; 53 let buf: [4096]u8 = [0...]; 54 55 for (let n => read(src, buf[..])?) { 56 w += writeall(dest, buf[..n])?; 57 }; 58 return w; 59 };