...

Source file src/oras.land/oras-go/pkg/content/iowriter.go

Documentation: oras.land/oras-go/pkg/content

     1  /*
     2  Copyright The ORAS Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package content
    17  
    18  import (
    19  	"context"
    20  	"io"
    21  	"io/ioutil"
    22  
    23  	"github.com/containerd/containerd/content"
    24  	"github.com/opencontainers/go-digest"
    25  )
    26  
    27  // IoContentWriter writer that wraps an io.Writer, so the results can be streamed to
    28  // an open io.Writer. For example, can be used to pull a layer and write it to a file, or device.
    29  type IoContentWriter struct {
    30  	writer   io.Writer
    31  	digester digest.Digester
    32  	size     int64
    33  	hash     *digest.Digest
    34  }
    35  
    36  // NewIoContentWriter create a new IoContentWriter.
    37  //
    38  // By default, it calculates the hash when writing. If the option `skipHash` is true,
    39  // it will skip doing the hash. Skipping the hash is intended to be used only
    40  // if you are confident about the validity of the data being passed to the writer,
    41  // and wish to save on the hashing time.
    42  func NewIoContentWriter(writer io.Writer, opts ...WriterOpt) content.Writer {
    43  	w := writer
    44  	if w == nil {
    45  		w = ioutil.Discard
    46  	}
    47  	// process opts for default
    48  	wOpts := DefaultWriterOpts()
    49  	for _, opt := range opts {
    50  		if err := opt(&wOpts); err != nil {
    51  			return nil
    52  		}
    53  	}
    54  	ioc := &IoContentWriter{
    55  		writer:   w,
    56  		digester: digest.Canonical.Digester(),
    57  		// we take the OutputHash, since the InputHash goes to the passthrough writer,
    58  		// which then passes the processed output to us
    59  		hash: wOpts.OutputHash,
    60  	}
    61  	return NewPassthroughWriter(ioc, func(r io.Reader, w io.Writer, done chan<- error) {
    62  		// write out the data to the io writer
    63  		var (
    64  			err error
    65  		)
    66  		// we could use io.Copy, but calling it with the default blocksize is identical to
    67  		// io.CopyBuffer. Otherwise, we would need some way to let the user flag "I want to use
    68  		// io.Copy", when it should not matter to them
    69  		b := make([]byte, wOpts.Blocksize, wOpts.Blocksize)
    70  		_, err = io.CopyBuffer(w, r, b)
    71  		done <- err
    72  	}, opts...)
    73  }
    74  
    75  func (w *IoContentWriter) Write(p []byte) (n int, err error) {
    76  	n, err = w.writer.Write(p)
    77  	if err != nil {
    78  		return 0, err
    79  	}
    80  	w.size += int64(n)
    81  	if w.hash == nil {
    82  		w.digester.Hash().Write(p[:n])
    83  	}
    84  	return
    85  }
    86  
    87  func (w *IoContentWriter) Close() error {
    88  	return nil
    89  }
    90  
    91  // Digest may return empty digest or panics until committed.
    92  func (w *IoContentWriter) Digest() digest.Digest {
    93  	return w.digester.Digest()
    94  }
    95  
    96  // Commit commits the blob (but no roll-back is guaranteed on an error).
    97  // size and expected can be zero-value when unknown.
    98  // Commit always closes the writer, even on error.
    99  // ErrAlreadyExists aborts the writer.
   100  func (w *IoContentWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
   101  	return nil
   102  }
   103  
   104  // Status returns the current state of write
   105  func (w *IoContentWriter) Status() (content.Status, error) {
   106  	return content.Status{}, nil
   107  }
   108  
   109  // Truncate updates the size of the target blob
   110  func (w *IoContentWriter) Truncate(size int64) error {
   111  	return nil
   112  }
   113  

View as plain text