package ctxio import ( "context" "io" "sync" ) type ioSeekerWrapper struct { ctx context.Context mu sync.Mutex pos int64 size int64 r ReaderAt } func WrapIoReadSeeker(ctx context.Context, r ReaderAt, size int64) io.ReadSeeker { return &ioSeekerWrapper{ ctx: ctx, r: r, size: size, } } func (r *ioSeekerWrapper) Seek(offset int64, whence int) (int64, error) { r.mu.Lock() defer r.mu.Unlock() switch whence { case io.SeekStart: r.pos = offset case io.SeekCurrent: r.pos = r.pos + offset case io.SeekEnd: r.pos = r.size + offset } return r.pos, nil } func (r *ioSeekerWrapper) Read(p []byte) (int, error) { r.mu.Lock() defer r.mu.Unlock() n, err := r.r.ReadAt(r.ctx, p, r.pos) r.pos += int64(n) return n, err } var _ io.ReadSeekCloser = (*ioSeekerCloserWrapper)(nil) type ioSeekerCloserWrapper struct { ctx context.Context mu sync.Mutex pos int64 size int64 r FileReader } func IoReadSeekCloserWrapper(ctx context.Context, r FileReader, size int64) io.ReadSeekCloser { return &ioSeekerCloserWrapper{ ctx: ctx, r: r, size: size, } } func (r *ioSeekerCloserWrapper) Seek(offset int64, whence int) (int64, error) { r.mu.Lock() defer r.mu.Unlock() switch whence { case io.SeekStart: r.pos = offset case io.SeekCurrent: r.pos = r.pos + offset case io.SeekEnd: r.pos = r.size + offset } return r.pos, nil } func (r *ioSeekerCloserWrapper) Read(p []byte) (int, error) { r.mu.Lock() defer r.mu.Unlock() n, err := r.r.ReadAt(r.ctx, p, r.pos) r.pos += int64(n) return n, err } // Close implements io.ReadSeekCloser. func (r *ioSeekerCloserWrapper) Close() error { return r.r.Close(r.ctx) }