Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Allow Identify to take a nil io.Reader #370

Merged
merged 2 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions formats.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ func RegisterFormat(format Format) {
//
// If no matching formats were found, special error ErrNoMatch is returned.
//
// The returned io.Reader will always be non-nil and will read from the
// same point as the reader which was passed in; it should be used in place
// of the input stream after calling Identify() because it preserves and
// re-reads the bytes that were already read during the identification
// process.
// If stream is nil then it will only match on file name and the
// returned io.Reader will be nil.
//
// If stream is non-nil then the returned io.Reader will always be
// non-nil and will read from the same point as the reader which was
// passed in; it should be used in place of the input stream after
// calling Identify() because it preserves and re-reads the bytes that
// were already read during the identification process.
func Identify(filename string, stream io.Reader) (Format, io.Reader, error) {
var compression Compression
var archival Archival
Expand Down Expand Up @@ -98,15 +101,20 @@ func identifyOne(format Format, filename string, stream *rewindReader, comp Comp
// (yes, we have to make a new reader every time we do a match,
// because we reset/seek the stream each time and that can mess up
// the compression reader's state if we don't discard it also)
if comp != nil {
if comp != nil && stream != nil {
decompressedStream, openErr := comp.OpenReader(stream)
if openErr != nil {
return MatchResult{}, openErr
}
defer decompressedStream.Close()
mr, err = format.Match(filename, decompressedStream)
} else {
mr, err = format.Match(filename, stream)
// Make sure we pass a nil io.Reader not a *rewindReader(nil)
var r io.Reader
if stream != nil {
r = stream
}
mr, err = format.Match(filename, r)
}

// if the error is EOF, we can just ignore it.
Expand Down Expand Up @@ -267,13 +275,19 @@ type rewindReader struct {
}

func newRewindReader(r io.Reader) *rewindReader {
if r == nil {
return nil
}
return &rewindReader{
Reader: r,
buf: new(bytes.Buffer),
}
}

func (rr *rewindReader) Read(p []byte) (n int, err error) {
if rr == nil {
panic("internal error: reading from nil rewindReader")
}
// if there is a buffer we should read from, start
// with that; we only read from the underlying stream
// after the buffer has been "depleted"
Expand Down Expand Up @@ -312,6 +326,9 @@ func (rr *rewindReader) Read(p []byte) (n int, err error) {
// Read() to start reading from the beginning of the
// buffered bytes.
func (rr *rewindReader) rewind() {
if rr == nil {
return
}
rr.bufReader = bytes.NewReader(rr.buf.Bytes())
}

Expand All @@ -322,6 +339,9 @@ func (rr *rewindReader) rewind() {
// If the underlying reader implements io.Seeker, then the
// underlying reader will be used directly.
func (rr *rewindReader) reader() io.Reader {
if rr == nil {
return nil
}
if ras, ok := rr.Reader.(io.Seeker); ok {
if _, err := ras.Seek(0, io.SeekStart); err == nil {
return rr.Reader
Expand Down
8 changes: 5 additions & 3 deletions tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ func (t Tar) Match(filename string, stream io.Reader) (MatchResult, error) {
}

// match file header
r := tar.NewReader(stream)
_, err := r.Next()
mr.ByStream = err == nil
if stream != nil {
r := tar.NewReader(stream)
_, err := r.Next()
mr.ByStream = err == nil
}

return mr, nil
}
Expand Down