diff --git a/28-error-handling/04b-named-params/main.go b/28-error-handling/04b-named-params/main.go index 89963ec..917c562 100644 --- a/28-error-handling/04b-named-params/main.go +++ b/28-error-handling/04b-named-params/main.go @@ -12,6 +12,10 @@ import ( "os" "github.com/inancgumus/learngo/internal/magic" + // + // Use the following one for the panicking library: + // magic "github.com/inancgumus/learngo/internal/magicpanic" + // ) func main() { diff --git a/internal/magic/detect.go b/internal/magic/detect.go index 60d8dc3..59d22db 100644 --- a/internal/magic/detect.go +++ b/internal/magic/detect.go @@ -17,17 +17,12 @@ import ( // Detect returns the files that have a valid header (file signature). // A valid header is determined by the format. func Detect(format string, filenames []string) (valids []string, err error) { - defer func() { - if rerr := recover(); rerr != nil { - err = fmt.Errorf("cannot detect: %v", rerr) - } - }() - - return detect(format, filenames), nil -} - -func detect(format string, filenames []string) (valids []string) { header := headerOf(format) + if header == "unknown" { + err = fmt.Errorf("unknown format: %s", format) + return + } + buf := make([]byte, len(header)) for _, filename := range filenames { @@ -50,7 +45,8 @@ func headerOf(format string) string { return "\xff\xd8\xff" } // this should never occur - panic("unknown format: " + format) + // panic("unknown format: " + format) + return "unknown" } // read reads len(buf) bytes to buf from a file diff --git a/internal/magicpanic/detect.go b/internal/magicpanic/detect.go new file mode 100644 index 0000000..60d8dc3 --- /dev/null +++ b/internal/magicpanic/detect.go @@ -0,0 +1,75 @@ +// For more tutorials: https://blog.learngoprogramming.com +// +// Copyright © 2018 Inanc Gumus +// Learn Go Programming Course +// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ +// + +package magic + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// Detect returns the files that have a valid header (file signature). +// A valid header is determined by the format. +func Detect(format string, filenames []string) (valids []string, err error) { + defer func() { + if rerr := recover(); rerr != nil { + err = fmt.Errorf("cannot detect: %v", rerr) + } + }() + + return detect(format, filenames), nil +} + +func detect(format string, filenames []string) (valids []string) { + header := headerOf(format) + buf := make([]byte, len(header)) + + for _, filename := range filenames { + if read(filename, buf) != nil { + continue + } + + if bytes.Equal([]byte(header), buf) { + valids = append(valids, filename) + } + } + return +} + +func headerOf(format string) string { + switch format { + case "png": + return "\x89PNG\r\n\x1a\n" + case "jpg": + return "\xff\xd8\xff" + } + // this should never occur + panic("unknown format: " + format) +} + +// read reads len(buf) bytes to buf from a file +func read(filename string, buf []byte) error { + file, err := os.Open(filename) + if err != nil { + return err + } + defer file.Close() + + fi, err := file.Stat() + if err != nil { + return err + } + + if fi.Size() <= int64(len(buf)) { + return fmt.Errorf("file size < len(buf)") + } + + _, err = io.ReadFull(file, buf) + return err +}