1package syntax
2
3import (
4 "errors"
5 "regexp"
6)
7
8// Represents an arbitrary URI in string format, as would pass Lexicon syntax validation.
9//
10// The syntax is minimal and permissive, designed for fast verification and exact-string passthrough, not schema-specific parsing or validation. For example, will not validate AT-URI or DID strings.
11//
12// Always use [ParseURI] instead of wrapping strings directly, especially when working with network input.
13type URI string
14
15func ParseURI(raw string) (URI, error) {
16 if raw == "" {
17 return "", errors.New("expected URI, got empty string")
18 }
19 if len(raw) > 8192 {
20 return "", errors.New("URI is too long (8192 chars max)")
21 }
22 var uriRegex = regexp.MustCompile(`^[a-z][a-z.-]{0,80}:[[:graph:]]+$`)
23 if !uriRegex.MatchString(raw) {
24 return "", errors.New("URI syntax didn't validate via regex")
25 }
26 return URI(raw), nil
27}
28
29func (u URI) String() string {
30 return string(u)
31}
32
33func (u URI) MarshalText() ([]byte, error) {
34 return []byte(u.String()), nil
35}
36
37func (u *URI) UnmarshalText(text []byte) error {
38 uri, err := ParseURI(string(text))
39 if err != nil {
40 return err
41 }
42 *u = uri
43 return nil
44}