1
0
mirror of https://github.com/golang/go synced 2024-11-22 09:14:40 -07:00

mime: range glob expansions in type_unix.go

This commit is contained in:
Nikola Jokic 2022-07-20 20:50:13 +02:00
parent 176b63e711
commit b41e88d296
2 changed files with 101 additions and 1 deletions

View File

@ -8,6 +8,7 @@ package mime
import (
"bufio"
"bytes"
"os"
"strings"
)
@ -49,7 +50,8 @@ func loadMimeGlobsFile(filename string) error {
}
extension := fields[2][1:]
if strings.ContainsAny(extension, "?*[") {
switch {
case strings.ContainsAny(extension, "?*"):
// Not a bare extension, but a glob. Ignore for now:
// - we do not have an implementation for this glob
// syntax (translation to path/filepath.Match could
@ -60,7 +62,15 @@ func loadMimeGlobsFile(filename string) error {
// - trying to match glob metacharacters literally is
// not useful
continue
case strings.Contains(extension, "["):
if extensions, ok := expand(extension); ok {
for i := range extensions {
setExtensionType(extensions[i], fields[1])
}
}
continue
}
if _, ok := mimeTypes.Load(extension); ok {
// We've already seen this extension.
// The file is in weight order, so we keep
@ -124,3 +134,78 @@ func initMimeForTests() map[string]string {
".png": "image/png",
}
}
func expand(glob string) ([]string, bool) {
runes := []rune(glob)
resultSize := 1
stringSize := 0
countLoop:
for i := 0; i < len(runes); i++ {
switch runes[i] {
case '[':
for j := i + 1; j < len(runes); j++ {
if runes[j] == ']' {
i = j
continue countLoop
}
if runes[j+1] == '-' {
if j+2 >= len(runes) {
return nil, false
}
resultSize *= int(runes[j+2]-runes[j]) + 1
stringSize++
j += 2
continue
}
resultSize++
stringSize++
}
default:
stringSize++
}
}
buffers := make([]bytes.Buffer, resultSize, resultSize)
for i := range buffers {
buffers[i].Grow(stringSize)
}
for i := 0; i < len(runes); i++ {
switch runes[i] {
case '[':
var expanded []rune
for j := i + 1; j < len(runes); j++ {
if runes[j] == ']' {
i = j
break
}
if runes[j+1] == '-' {
for k := runes[j]; k <= runes[j+2]; k++ {
expanded = append(expanded, k)
}
j += 2
continue
}
expanded = append(expanded, runes[j])
}
for j, k := 0, 0; j < resultSize; j, k = j+1, (k+1)%len(expanded) {
buffers[j].WriteRune(expanded[k])
}
default:
for j := 0; j < resultSize; j++ {
buffers[j].WriteRune(runes[i])
}
}
}
result := make([]string, 0, resultSize)
for i := 0; i < resultSize; i++ {
result = append(result, buffers[i].String())
}
return result, true
}

View File

@ -32,6 +32,9 @@ func TestTypeByExtensionUNIX(t *testing.T) {
".foo?ar": "",
".foo*r": "",
".foo[1-3]": "",
".foo1": "example/glob-range",
".foo2": "example/glob-range",
".foo3": "example/glob-range",
}
for ext, want := range typeTests {
@ -41,3 +44,15 @@ func TestTypeByExtensionUNIX(t *testing.T) {
}
}
}
func TestMimeExtension(t *testing.T) {
initMimeUnixTest(t)
exts, _ := ExtensionsByType("example/glob-range")
expected := []string{".foo1", ".foo2", ".foo3"}
for i := range exts {
if exts[i] != expected[i] {
t.Errorf("Want %q, got %q", expected[i], exts[i])
}
}
}