qurl/obj/qurl.go

90 lines
1.5 KiB
Go
Raw Normal View History

package obj
2018-11-11 16:56:30 -09:00
import (
"fmt"
"strings"
"time"
2018-11-17 07:47:39 -09:00
"net/url"
2018-11-11 16:56:30 -09:00
)
type QURL struct {
ID uint64
URL string
Created time.Time
IP []byte
Browser string
}
2018-11-17 07:47:39 -09:00
func (q *QURL) CheckValid() error {
if q == nil {
return fmt.Errorf("QURL is nil")
}
if q.URL == "" {
return fmt.Errorf("URL may not be empty")
}
u, err := url.Parse(q.URL)
if err != nil {
return err
}
2018-11-17 08:17:22 -09:00
if u.Scheme == "" {
return fmt.Errorf("URLs must begin with a scheme (e.g. https:)")
}
if u.Host == "" && u.RawQuery == "" && u.RawPath == "" && u.Fragment == "" {
return fmt.Errorf("URLs must contain a path, host, query or fragment element")
}
2018-11-17 07:47:39 -09:00
if !u.IsAbs() {
return fmt.Errorf("Relative URLs are not allowed")
}
return nil
}
2018-11-11 16:56:30 -09:00
const alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
const alphalen = uint64(len(alpha))
func ToString(v uint64) string {
var r strings.Builder
var i uint64
for i = v; i >= alphalen; i = (i / alphalen) - 1 {
r.WriteByte(alpha[i%alphalen])
}
r.WriteByte(alpha[i])
return r.String()
}
func FromString(s string) (uint64, error) {
var r uint64
vlen := uint64(len(s))
for i := uint64(0); i < vlen; i++ {
x := strings.IndexByte(alpha, s[i])
if x == -1 {
return 0, fmt.Errorf("Invalid character [%s]", s[i])
}
if i == 0 {
r += uint64(x)
} else {
r += (uint64(x+1) * pow(alphalen, i))
}
}
return r, nil
}
func pow(a, b uint64) uint64 {
p := uint64(1)
for b > 0 {
if b&1 != 0 {
p *= a
}
b >>= 1
a *= a
}
return p
}