CopyWithCtx slightly modified function signature: - context has been added in order to propagate cancellation - I do not return the number of bytes written, has it is not useful in my use case
(ctx context.Context, out io.Writer, in io.Reader, size int64, progress func(percentage float64))
| 24 | // - context has been added in order to propagate cancellation |
| 25 | // - I do not return the number of bytes written, has it is not useful in my use case |
| 26 | func CopyWithCtx(ctx context.Context, out io.Writer, in io.Reader, size int64, progress func(percentage float64)) error { |
| 27 | // Copy will call the Reader and Writer interface multiple time, in order |
| 28 | // to copy by chunk (avoiding loading the whole file in memory). |
| 29 | // I insert the ability to cancel before read time as it is the earliest |
| 30 | // possible in the call process. |
| 31 | var finish int64 = 0 |
| 32 | s := size / 100 |
| 33 | _, err := CopyWithBuffer(out, readerFunc(func(p []byte) (int, error) { |
| 34 | // golang non-blocking channel: https://gobyexample.com/non-blocking-channel-operations |
| 35 | select { |
| 36 | // if context has been canceled |
| 37 | case <-ctx.Done(): |
| 38 | // stop process and propagate "context canceled" error |
| 39 | return 0, ctx.Err() |
| 40 | default: |
| 41 | // otherwise just run default io.Reader implementation |
| 42 | n, err := in.Read(p) |
| 43 | if s > 0 && (err == nil || err == io.EOF) { |
| 44 | finish += int64(n) |
| 45 | progress(float64(finish) / float64(s)) |
| 46 | } |
| 47 | return n, err |
| 48 | } |
| 49 | })) |
| 50 | return err |
| 51 | } |
| 52 | |
| 53 | type limitWriter struct { |
| 54 | w io.Writer |
no test coverage detected