func Decode(r io.Reader) (Image, string, error) {
os.File
などのio.Reader
インターフェースを実装している型の変数を引数に取る。
rr := asReader(r)
rを引数としてasReader()
が実行される。
asReader()
のなか
func asReader(r io.Reader) reader {
if rr, ok := r.(reader); ok {
return rr
}
型アサーション。reader
型にキャストできればそれを返す。
reader
型の定義は↓
type reader interface {
io.Reader
Peek(int) ([]byte, error)
}
return bufio.NewReader(r)
キャストできない場合はbufio.NewReader()
でbufio.Reader
にしを返す。
bufio.Reader
はメソッドにfunc (b *Reader) Peek(n int) ([]byte, error)
があるので、reader
型を実装していることになる。
f := sniff(rr)
func sniff(r reader) format {
for _, f := range formats {
b, err := r.Peek(len(f.magic))
if err == nil && match(f.magic, b) {
return f
}
}
formats
には登録が完了しているフォーマットのリストが入っている。
r.Peek(len(f.magic))
でフォーマットのマジックナンバーの長さ分のバイトを読み込む。
match(f.magic, b)
でフォーマットのマジックナンバーと読み込んだバイトが一致することをチェック。
trueであればそのままf
を返す。
if f.decode == nil {
return nil, "", ErrFormat
}
f := sniff(rr)
でフォーマットのチェックがエラーだった場合はErrFormat
を返す。
m, err := f.decode(rr)
各フォーマットのパッケージで実装されているdecode
メソッドによってデコードを実行する。