Nick Cooper uploaded a change:
https://go-review.googlesource.com/7444
mime: add ExtensionByType method
Added the inverse of TypeByExtension for discovering an appropriate
extension for a given MIME type. In cases where there are multiple
such extensions, it opts for the shortest.
Change-Id: I6a80e1af3db5d45ad6a4c7ff4ccfdf6a4f424367
---
M src/mime/type.go
M src/mime/type_test.go
2 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/src/mime/type.go b/src/mime/type.go
index ffda1f0..428b899 100644
--- a/src/mime/type.go
+++ b/src/mime/type.go
@@ -24,7 +24,8 @@
".png": "image/png",
".xml": "text/xml; charset=utf-8",
}
- mimeTypes = clone(mimeTypesLower)
+ mimeTypes = clone(mimeTypesLower)
+ extensions = invert(mimeTypesLower)
)
func clone(m map[string]string) map[string]string {
@@ -34,6 +35,21 @@
if strings.ToLower(k) != k {
panic("keys in mimeTypesLower must be lowercase")
}
+ }
+ return m2
+}
+
+func invert(m map[string]string) map[string]string {
+ m2 := make(map[string]string, len(m))
+ for k, v := range m {
+ justType, _, err := ParseMediaType(v)
+ if err != nil {
+ panic(err)
+ }
+ if existing, ok := m2[justType]; ok && len(existing) < len(k) {
+ continue
+ }
+ m2[justType] = k
}
return m2
}
@@ -91,6 +107,23 @@
return mimeTypesLower[string(lower)]
}
+// ExtensionByType returns the shortest extension known to be associated
with
+// the MIME type typ. The returned extension will begin with a leading
dot, as
+// in ".htm". When typ has no associated extension, ExtensionByType
returns "".
+//
+// The built-in table is the same as used with TypeByExtension.
+func ExtensionByType(typ string) (string, error) {
+ justType, _, err := ParseMediaType(typ)
+ if err != nil {
+ return "", err
+ }
+
+ once.Do(initMime)
+ mimeLock.RLock()
+ defer mimeLock.RUnlock()
+ return extensions[justType], nil
+}
+
// AddExtensionType sets the MIME type associated with
// the extension ext to typ. The extension should begin with
// a leading dot, as in ".html".
@@ -103,7 +136,7 @@
}
func setExtensionType(extension, mimeType string) error {
- _, param, err := ParseMediaType(mimeType)
+ justType, param, err := ParseMediaType(mimeType)
if err != nil {
return err
}
@@ -116,6 +149,9 @@
mimeLock.Lock()
mimeTypes[extension] = mimeType
mimeTypesLower[extLower] = mimeType
+ if existing, ok := extensions[justType]; !ok || len(existing) >
len(extLower) {
+ extensions[justType] = extLower
+ }
mimeLock.Unlock()
return nil
}
diff --git a/src/mime/type_test.go b/src/mime/type_test.go
index d2d254a..93bb315 100644
--- a/src/mime/type_test.go
+++ b/src/mime/type_test.go
@@ -5,6 +5,7 @@
package mime
import (
+ "strings"
"testing"
)
@@ -43,6 +44,21 @@
}
}
+func TestExtensionByType(t *testing.T) {
+ for want, typ := range typeTests {
+ val, err := ExtensionByType(typ)
+ if err != nil {
+ t.Errorf("ExtensionByType(%q) gave error %q", typ, err)
+ continue
+ }
+ // We always expect lower case, test data includes upper-case.
+ want = strings.ToLower(want)
+ if val != want {
+ t.Errorf("ExtensionByType(%q) = %q, want %q", typ, val, want)
+ }
+ }
+}
+
func TestLookupMallocs(t *testing.T) {
n := testing.AllocsPerRun(10000, func() {
TypeByExtension(".html")
--
https://go-review.googlesource.com/7444