package obj import ( "fmt" "net/url" "strings" "time" ) type QURL struct { ID uint64 URL string Created time.Time IP []byte Browser string } 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 } 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") } if !u.IsAbs() { return fmt.Errorf("Relative URLs are not allowed") } return nil } 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 }