eclipse/lib/gitcache/url_ns.go

91 lines
1.7 KiB
Go

// Copyright (C) 2024 Umorpha Systems
// SPDX-License-Identifier: AGPL-3.0-or-later
package gitcache
import (
"strings"
)
func needsEscaped(b byte) bool {
switch {
case b == '!', // our own escape
// see: git-check-ref-format(1)
b <= ' ', b == '\x7F', // never: ASCII control characters
b == '~', b == '^', b == ':', // never: gitrevision meaning
b == '?', b == '*', b == '[', // never: refspec pattern
b == '\\', // never: backslash
b == '.', b == '@', b == '/': // sometimes: special rules
return true
default:
return false
}
}
func URL2NS(url string) (string, bool) {
url, ok := NormalizeURL(url)
if !ok {
return "", false
}
l := len(url)
for i := 0; i < len(url); i++ {
if needsEscaped(url[i]) {
l += 2
}
}
var ns strings.Builder
ns.Grow(l)
var buf [3]byte
buf[0] = '!'
const digits = "0123456789abcdef"
for i := 0; i < len(url); i++ {
b := url[i]
if needsEscaped(b) {
buf[1] = digits[b>>4]
buf[2] = digits[b&0xf]
ns.Write(buf[:])
} else {
ns.WriteByte(b)
}
}
return ns.String(), true
}
func hex2int(h byte) (byte, bool) {
switch {
case '0' <= h && h <= '9':
return h - '0', true
case 'a' <= h && h <= 'f':
return h - 'a' + 0xa, true
default:
return 0, false
}
}
func NS2URL(ns string) (string, bool) {
l := len(ns) - (strings.Count(ns, "!") * 2)
if l < 0 {
return "", false
}
var url strings.Builder
url.Grow(l)
for i := 0; i < len(ns); i++ {
b := ns[i]
if b == '!' {
if i+2 >= len(ns) {
return "", false
}
h, hOK := hex2int(ns[i+1])
l, lOK := hex2int(ns[i+2])
if !hOK || !lOK {
return "", false
}
b = h<<4 | l
i += 2
}
url.WriteByte(b)
}
return url.String(), true
}