Skip to content

Commit

Permalink
Added a writer to allow users to easily tee a reader through this lib…
Browse files Browse the repository at this point in the history
…rary
  • Loading branch information
javiercbk committed Apr 6, 2019
1 parent 2248f2e commit f5b6ce9
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
39 changes: 39 additions & 0 deletions filetype_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package filetype

import (
"bytes"
"io"
"testing"

"github.com/h2non/filetype/types"
Expand Down Expand Up @@ -121,3 +123,40 @@ func TestGetType(t *testing.T) {
t.Fatalf("Type should not be supported")
}
}

func TestMatchWriter(t *testing.T) {
cases := []struct {
mime string
reader io.Reader
read int64
err error
}{
{"image/jpeg", bytes.NewReader([]byte{0xFF, 0xD8, 0xFF}), 3, nil},
{"image/png", bytes.NewReader([]byte{0x89, 0x50, 0x4E, 0x47}), 4, nil},
{types.Unknown.MIME.Value, bytes.NewReader([]byte{}), 0, ErrEmptyBuffer},
{types.Unknown.MIME.Value, nil, 0, ErrEmptyBuffer},
}
for _, test := range cases {
var w int64
var err error
var mimeType types.Type
mw := NewMatcherWriter()
if test.reader != nil {
w, err = io.Copy(mw, test.reader)
}
if err != nil {
t.Fatalf("Error matching %s error: %v", test.mime, err)
return
}
mimeType, err = mw.Match()
if err != test.err {
t.Fatalf("Invalid error match: %v, expected %s", err, test.err)
}
if mimeType.MIME.Value != test.mime {
t.Fatalf("Invalid mime match: %s, expected %s", mimeType.MIME.Value, test.mime)
}
if w != test.read {
t.Fatalf("Invalid read match: %d, expected %d", w, test.read)
}
}
}
45 changes: 45 additions & 0 deletions match.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package filetype

import (
"io"
"math"
"os"

"github.com/h2non/filetype/matchers"
Expand All @@ -17,6 +18,50 @@ var MatcherKeys = &matchers.MatcherKeys
// NewMatcher is an alias to matchers.NewMatcher
var NewMatcher = matchers.NewMatcher

const maxBufSize = 8192

// MatcherWriter is a matcher that coplies to the writer interface
type MatcherWriter struct {
buf []byte
}

func (mb *MatcherWriter) Write(p []byte) (n int, err error) {
incomingSize := len(p)
written := incomingSize
currentSize := len(mb.buf)
if currentSize < maxBufSize {
// write only when the current size of the buffer is less than the max buffer size
newSize := currentSize + incomingSize
written = maxBufSize - newSize
reSlice := p
if written < 0 {
// if the maxBufSize is exceeded by the new size, we need to do some re slicing
written = int(math.Abs(float64(written)))
reSlice = p[0:written]
} else {
// if the maxBufSize is not exceeded then we are going to write the whole buffer
written = incomingSize
}
mb.buf = append(mb.buf, reSlice...)
}
return written, nil
}

// Match calls the Match function with the inner buffer of the MatcherWriter
func (mb *MatcherWriter) Match() (types.Type, error) {
if mb.buf == nil {
return types.Unknown, ErrEmptyBuffer
}
return Match(mb.buf)
}

// NewMatcherWriter creates a matcher which is a io.Writer
func NewMatcherWriter() *MatcherWriter {
return &MatcherWriter{
buf: make([]byte, 0, maxBufSize),
}
}

// Match infers the file type of a given buffer inspecting its magic numbers signature
func Match(buf []byte) (types.Type, error) {
length := len(buf)
Expand Down

0 comments on commit f5b6ce9

Please sign in to comment.