replace strings.Split(N) for strings.Cut() or alternatives
Go 1.18 and up now provides a strings.Cut() which is better suited for
splitting key/value pairs (and similar constructs), and performs better:
```go
func BenchmarkSplit(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_ = strings.SplitN(s, "=", 2)[0]
}
}
}
func BenchmarkCut(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_, _, _ = strings.Cut(s, "=")
}
}
}
```
BenchmarkSplit
BenchmarkSplit-10 8244206 128.0 ns/op 128 B/op 4 allocs/op
BenchmarkCut
BenchmarkCut-10 54411998 21.80 ns/op 0 B/op 0 allocs/op
While looking at occurrences of `strings.Split()`, I also updated some for alternatives,
or added some constraints; for cases where an specific number of items is expected, I used `strings.SplitN()`
with a suitable limit. This prevents (theoretical) unlimited splits.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@@ -38,7 +38,9 @@ const (
|
||||
MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json"
|
||||
MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json"
|
||||
MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
|
||||
|
||||
// Checkpoint/Restore Media Types
|
||||
|
||||
MediaTypeContainerd1Checkpoint = "application/vnd.containerd.container.criu.checkpoint.criu.tar"
|
||||
MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar"
|
||||
MediaTypeContainerd1Resource = "application/vnd.containerd.container.resource.tar"
|
||||
@@ -47,9 +49,12 @@ const (
|
||||
MediaTypeContainerd1CheckpointOptions = "application/vnd.containerd.container.checkpoint.options.v1+proto"
|
||||
MediaTypeContainerd1CheckpointRuntimeName = "application/vnd.containerd.container.checkpoint.runtime.name"
|
||||
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
|
||||
// Legacy Docker schema1 manifest
|
||||
|
||||
// MediaTypeDockerSchema1Manifest is the legacy Docker schema1 manifest
|
||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
// Encypted media types
|
||||
|
||||
// Encrypted media types
|
||||
|
||||
MediaTypeImageLayerEncrypted = ocispec.MediaTypeImageLayer + "+encrypted"
|
||||
MediaTypeImageLayerGzipEncrypted = ocispec.MediaTypeImageLayerGzip + "+encrypted"
|
||||
)
|
||||
@@ -93,16 +98,23 @@ func DiffCompression(ctx context.Context, mediaType string) (string, error) {
|
||||
|
||||
// parseMediaTypes splits the media type into the base type and
|
||||
// an array of sorted extensions
|
||||
func parseMediaTypes(mt string) (string, []string) {
|
||||
func parseMediaTypes(mt string) (mediaType string, suffixes []string) {
|
||||
if mt == "" {
|
||||
return "", []string{}
|
||||
}
|
||||
mediaType, ext, ok := strings.Cut(mt, "+")
|
||||
if !ok {
|
||||
return mediaType, []string{}
|
||||
}
|
||||
|
||||
s := strings.Split(mt, "+")
|
||||
ext := s[1:]
|
||||
sort.Strings(ext)
|
||||
|
||||
return s[0], ext
|
||||
// Splitting the extensions following the mediatype "(+)gzip+encrypted".
|
||||
// We expect this to be a limited list, so add an arbitrary limit (50).
|
||||
//
|
||||
// Note that DiffCompression is only using the last element, so perhaps we
|
||||
// should split on the last "+" only.
|
||||
suffixes = strings.SplitN(ext, "+", 50)
|
||||
sort.Strings(suffixes)
|
||||
return mediaType, suffixes
|
||||
}
|
||||
|
||||
// IsNonDistributable returns true if the media type is non-distributable.
|
||||
@@ -118,8 +130,7 @@ func IsLayerType(mt string) bool {
|
||||
}
|
||||
|
||||
// Parse Docker media types, strip off any + suffixes first
|
||||
base, _ := parseMediaTypes(mt)
|
||||
switch base {
|
||||
switch base, _ := parseMediaTypes(mt); base {
|
||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
|
||||
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip:
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user