From f97cf5b587aa803495dd28b889327baab066cef8 Mon Sep 17 00:00:00 2001
From: mpl <mathieu.lonjaret@gmail.com>
Date: Wed, 29 Oct 2014 00:30:02 +0100
Subject: [PATCH] third_party/goexif: bump to
 9fb3b23c1aaada5775178242884b75d4f4a330d3

Change-Id: I31f509f32ec6a2fe93cd78a9d09146b0bb6b302e
---
 .../github.com/rwcarlsen/goexif/exif/exif.go  | 88 +++++++++++++++++--
 1 file changed, 83 insertions(+), 5 deletions(-)

diff --git a/third_party/github.com/rwcarlsen/goexif/exif/exif.go b/third_party/github.com/rwcarlsen/goexif/exif/exif.go
index 5df619393..e8d08ecae 100644
--- a/third_party/github.com/rwcarlsen/goexif/exif/exif.go
+++ b/third_party/github.com/rwcarlsen/goexif/exif/exif.go
@@ -62,6 +62,69 @@ func RegisterParsers(ps ...Parser) {
 
 type parser struct{}
 
+type tiffErrors map[tiffError]string
+
+func (te tiffErrors) Error() string {
+	var allErrors []string
+	for k, v := range te {
+		allErrors = append(allErrors, fmt.Sprintf("%s: %v\n", stagePrefix[k], v))
+	}
+	return strings.Join(allErrors, "\n")
+}
+
+// IsCriticalError, given the error returned by Decode, reports whether the
+// returned *Exif may contain usable information.
+func IsCriticalError(err error) bool {
+	_, ok := err.(tiffErrors)
+	return !ok
+}
+
+// IsExifError reports whether the error happened while decoding the EXIF
+// sub-IFD.
+func IsExifError(err error) bool {
+	if te, ok := err.(tiffErrors); ok {
+		_, isExif := te[loadExif]
+		return isExif
+	}
+	return false
+}
+
+// IsGPSError reports whether the error happened while decoding the GPS sub-IFD.
+func IsGPSError(err error) bool {
+	if te, ok := err.(tiffErrors); ok {
+		_, isGPS := te[loadExif]
+		return isGPS
+	}
+	return false
+}
+
+// IsInteroperabilityError reports whether the error happened while decoding the
+// Interoperability sub-IFD.
+func IsInteroperabilityError(err error) bool {
+	if te, ok := err.(tiffErrors); ok {
+		_, isInterop := te[loadInteroperability]
+		return isInterop
+	}
+	return false
+}
+
+type tiffError int
+
+const (
+	loadExif tiffError = iota
+	loadGPS
+	loadInteroperability
+)
+
+var stagePrefix = map[tiffError]string{
+	loadExif:             "loading EXIF sub-IFD",
+	loadGPS:              "loading GPS sub-IFD",
+	loadInteroperability: "loading Interoperability sub-IFD",
+}
+
+// Parse reads data from the tiff data in x and populates the tags
+// in x. If parsing a sub-IFD fails, the error is recorded and
+// parsing continues with the remaining sub-IFDs.
 func (p *parser) Parse(x *Exif) error {
 	x.LoadTags(x.Tiff.Dirs[0], exifFields, false)
 
@@ -70,15 +133,23 @@ func (p *parser) Parse(x *Exif) error {
 		x.LoadTags(x.Tiff.Dirs[1], thumbnailFields, false)
 	}
 
+	te := make(tiffErrors)
+
 	// recurse into exif, gps, and interop sub-IFDs
 	if err := loadSubDir(x, ExifIFDPointer, exifFields); err != nil {
-		return err
+		te[loadExif] = err.Error()
 	}
 	if err := loadSubDir(x, GPSInfoIFDPointer, gpsFields); err != nil {
-		return err
+		te[loadGPS] = err.Error()
 	}
 
-	return loadSubDir(x, InteroperabilityIFDPointer, interopFields)
+	if err := loadSubDir(x, InteroperabilityIFDPointer, interopFields); err != nil {
+		te[loadInteroperability] = err.Error()
+	}
+	if len(te) > 0 {
+		return te
+	}
+	return nil
 }
 
 func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error {
@@ -95,11 +166,11 @@ func loadSubDir(x *Exif, ptr FieldName, fieldMap map[uint16]FieldName) error {
 
 	_, err = r.Seek(offset, 0)
 	if err != nil {
-		return errors.New("exif: seek to sub-IFD failed: " + err.Error())
+		return fmt.Errorf("exif: seek to sub-IFD %s failed: %v", ptr, err)
 	}
 	subDir, _, err := tiff.DecodeDir(r, x.Tiff.Order)
 	if err != nil {
-		return errors.New("exif: sub-IFD decode failed: " + err.Error())
+		return fmt.Errorf("exif: sub-IFD %s decode failed: %v", ptr, err)
 	}
 	x.LoadTags(subDir, fieldMap, false)
 	return nil
@@ -117,6 +188,8 @@ type Exif struct {
 // decoded, each registered parser is called (in order of registration). If
 // one parser returns an error, decoding terminates and the remaining
 // parsers are not called.
+// The error can be inspected with functions such as IsCriticalError to
+// determine whether the returned object might still be usable.
 func Decode(r io.Reader) (*Exif, error) {
 	// EXIF data in JPEG is stored in the APP1 marker. EXIF data uses the TIFF
 	// format to store data.
@@ -194,6 +267,11 @@ func Decode(r io.Reader) (*Exif, error) {
 
 	for i, p := range parsers {
 		if err := p.Parse(x); err != nil {
+			if _, ok := err.(tiffErrors); ok {
+				return x, err
+			}
+			// This should never happen, as Parse always returns a tiffError
+			// for now, but that could change.
 			return x, fmt.Errorf("exif: parser %v failed (%v)", i, err)
 		}
 	}