package content import ( "context" contentapi "github.com/containerd/containerd/api/services/content/v1" digest "github.com/opencontainers/go-digest" ) type remoteReader struct { client contentapi.Content_ReadClient extra []byte } func (rr *remoteReader) Read(p []byte) (n int, err error) { n += copy(p, rr.extra) if n >= len(p) { if n <= len(rr.extra) { rr.extra = rr.extra[n:] } else { rr.extra = rr.extra[:0] } return } rr.extra = rr.extra[:0] p = p[n:] for len(p) > 0 { var resp *contentapi.ReadContentResponse // fill our buffer up until we can fill p. resp, err = rr.client.Recv() if err != nil { return } copied := copy(p, resp.Data) n += copied p = p[copied:] if len(p) == 0 { rr.extra = append(rr.extra, resp.Data[copied:]...) } } return } func (rr *remoteReader) Close() error { return rr.client.CloseSend() } type remoteReaderAt struct { ctx context.Context digest digest.Digest client contentapi.ContentClient } func (ra *remoteReaderAt) ReadAt(p []byte, off int64) (n int, err error) { rr := &contentapi.ReadContentRequest{ Digest: ra.digest, Offset: off, Size_: int64(len(p)), } rc, err := ra.client.Read(ra.ctx, rr) if err != nil { return 0, err } for len(p) > 0 { var resp *contentapi.ReadContentResponse // fill our buffer up until we can fill p. resp, err = rc.Recv() if err != nil { return n, err } copied := copy(p, resp.Data) n += copied p = p[copied:] } return n, nil }