mirror of https://github.com/Xhofe/alist
36 lines
1.2 KiB
Go
36 lines
1.2 KiB
Go
![]() |
package utils
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
// here is some syntaxic sugar inspired by the Tomas Senart's video,
|
||
|
// it allows me to inline the Reader interface
|
||
|
type readerFunc func(p []byte) (n int, err error)
|
||
|
|
||
|
func (rf readerFunc) Read(p []byte) (n int, err error) { return rf(p) }
|
||
|
|
||
|
// CopyWithCtx slightly modified function signature:
|
||
|
// - context has been added in order to propagate cancelation
|
||
|
// - I do not return the number of bytes written, has it is not useful in my use case
|
||
|
func CopyWithCtx(ctx context.Context, out io.Writer, in io.Reader) error {
|
||
|
// Copy will call the Reader and Writer interface multiple time, in order
|
||
|
// to copy by chunk (avoiding loading the whole file in memory).
|
||
|
// I insert the ability to cancel before read time as it is the earliest
|
||
|
// possible in the call process.
|
||
|
_, err := io.Copy(out, readerFunc(func(p []byte) (int, error) {
|
||
|
// golang non-blocking channel: https://gobyexample.com/non-blocking-channel-operations
|
||
|
select {
|
||
|
// if context has been canceled
|
||
|
case <-ctx.Done():
|
||
|
// stop process and propagate "context canceled" error
|
||
|
return 0, ctx.Err()
|
||
|
default:
|
||
|
// otherwise just run default io.Reader implementation
|
||
|
return in.Read(p)
|
||
|
}
|
||
|
}))
|
||
|
return err
|
||
|
}
|