128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
// Copyright 2020-2021 Buf Technologies, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package ioutilextended provides io utilities.
|
|
package ioutilextended
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"io/ioutil"
|
|
"sync"
|
|
|
|
"go.uber.org/multierr"
|
|
)
|
|
|
|
var (
|
|
// DiscardReader is an io.Reader in which all calls return 0 and io.EOF.
|
|
DiscardReader io.Reader = discardReader{}
|
|
// DiscardReadCloser is an io.ReadCloser in which all calls return 0 and io.EOF.
|
|
DiscardReadCloser io.ReadCloser = ioutil.NopCloser(DiscardReader)
|
|
// DiscardWriteCloser is a discard io.WriteCloser.
|
|
DiscardWriteCloser io.WriteCloser = NopWriteCloser(ioutil.Discard)
|
|
// NopCloser is a no-op closer.
|
|
NopCloser = nopCloser{}
|
|
)
|
|
|
|
// NopWriteCloser returns an io.WriteCloser with a no-op Close method wrapping the provided io.Writer.
|
|
func NopWriteCloser(writer io.Writer) io.WriteCloser {
|
|
return nopWriteCloser{Writer: writer}
|
|
}
|
|
|
|
// LockedWriter creates a locked Writer.
|
|
func LockedWriter(writer io.Writer) io.Writer {
|
|
return &lockedWriter{writer: writer}
|
|
}
|
|
|
|
// CompositeReadCloser returns a io.ReadCloser that is a composite of the Reader and Closer.
|
|
func CompositeReadCloser(reader io.Reader, closer io.Closer) io.ReadCloser {
|
|
return compositeReadCloser{Reader: reader, Closer: closer}
|
|
}
|
|
|
|
// CompositeWriteCloser returns a io.WriteCloser that is a composite of the Writer and Closer.
|
|
func CompositeWriteCloser(writer io.Writer, closer io.Closer) io.WriteCloser {
|
|
return compositeWriteCloser{Writer: writer, Closer: closer}
|
|
}
|
|
|
|
// ChainCloser chains the closers by calling them in order.
|
|
func ChainCloser(closers ...io.Closer) io.Closer {
|
|
return chainCloser{closers: closers}
|
|
}
|
|
|
|
// ReaderAtForReader converts an io.Reader to an io.ReaderAt.
|
|
func ReaderAtForReader(reader io.Reader) (io.ReaderAt, error) {
|
|
if readerAt, ok := reader.(io.ReaderAt); ok {
|
|
return readerAt, nil
|
|
}
|
|
data, err := ioutil.ReadAll(reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return bytes.NewReader(data), nil
|
|
}
|
|
|
|
type discardReader struct{}
|
|
|
|
func (discardReader) Read([]byte) (int, error) {
|
|
return 0, io.EOF
|
|
}
|
|
|
|
type nopWriteCloser struct {
|
|
io.Writer
|
|
}
|
|
|
|
func (nopWriteCloser) Close() error {
|
|
return nil
|
|
}
|
|
|
|
type nopCloser struct{}
|
|
|
|
func (nopCloser) Close() error {
|
|
return nil
|
|
}
|
|
|
|
type lockedWriter struct {
|
|
writer io.Writer
|
|
lock sync.Mutex
|
|
}
|
|
|
|
func (l *lockedWriter) Write(p []byte) (int, error) {
|
|
l.lock.Lock()
|
|
n, err := l.writer.Write(p)
|
|
l.lock.Unlock()
|
|
return n, err
|
|
}
|
|
|
|
type compositeReadCloser struct {
|
|
io.Reader
|
|
io.Closer
|
|
}
|
|
|
|
type compositeWriteCloser struct {
|
|
io.Writer
|
|
io.Closer
|
|
}
|
|
|
|
type chainCloser struct {
|
|
closers []io.Closer
|
|
}
|
|
|
|
func (c chainCloser) Close() error {
|
|
var err error
|
|
for _, closer := range c.closers {
|
|
err = multierr.Append(err, closer.Close())
|
|
}
|
|
return err
|
|
}
|