package detector import ( "io" ) type ( Detector struct { io.Reader err error data []byte detectFunc func([]byte) string } errReader struct { data []byte err error offset int } ) const contentTypeDetectSize = 512 func newReader(data []byte, err error) *errReader { return &errReader{data: data, err: err} } func (r *errReader) Read(b []byte) (int, error) { if r.offset >= len(r.data) { return 0, io.EOF } n := copy(b, r.data[r.offset:]) r.offset += n if r.offset >= len(r.data) { return n, r.err } return n, nil } func NewDetector(reader io.Reader, detectFunc func([]byte) string) *Detector { return &Detector{ data: make([]byte, contentTypeDetectSize), Reader: reader, detectFunc: detectFunc, } } func (d *Detector) Detect() (string, error) { n, err := d.Reader.Read(d.data) if err != nil && err != io.EOF { d.err = err return "", err } d.data = d.data[:n] return d.detectFunc(d.data), nil } func (d *Detector) RestoredReader() io.Reader { return io.MultiReader(newReader(d.data, d.err), d.Reader) }