package aprs import ( "encoding/json" "errors" "fmt" "strings" ) var ( ErrAddressInvalid = errors.New(`aprs: invalid address`) ) type Address struct { Call string `json:"call"` SSID string `json:"ssid,omitempty"` IsRepeated bool `json:"is_repeated,omitempty"` } func (a Address) EqualTo(b Address) bool { return a.Call == b.Call && a.SSID == b.SSID } func (a Address) String() string { var r = "" if a.IsRepeated { r = "*" } if a.SSID == "" { return a.Call + r } return fmt.Sprintf("%s-%s%s", a.Call, a.SSID, r) } func (a Address) Secret() int16 { var h = int16(0x73e2) var c = a.Call if len(c)%2 > 0 { c += "\x00" } for i := 0; i < len(c); i += 2 { h ^= int16(c[i]) << 8 h ^= int16(c[i+1]) } return h & 0x7fff } func (a Address) MarshalJSON() ([]byte, error) { return json.Marshal(a.String()) } func (a *Address) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { return err } p, err := ParseAddress(s) if err != nil { return err } a.Call = p.Call a.SSID = p.SSID a.IsRepeated = p.IsRepeated return nil } func ParseAddress(s string) (Address, error) { r := strings.HasSuffix(s, "*") if r { s = s[:len(s)-1] } p := strings.Split(s, "-") if len(p) == 0 || len(p) > 2 { return Address{}, ErrAddressInvalid } a := Address{Call: p[0], IsRepeated: r} if len(p) == 2 { a.SSID = p[1] } return a, nil } func MustParseAddress(s string) Address { a, err := ParseAddress(s) if err != nil { panic(err) } return a } func IsQConstruct(call string) bool { return len(call) == 3 && call[0] == 'q' } type Path []Address func (p Path) String() string { var s = make([]string, len(p)) for i, a := range p { s[i] = a.String() } return strings.Join(s, ",") } func ParsePath(p string) (Path, error) { ss := strings.Split(p, ",") if len(ss) == 0 { return nil, nil } var err error as := make(Path, len(ss)) for i, s := range ss { as[i], err = ParseAddress(s) if err != nil { return nil, err } } return as, nil }