127 lines
2.0 KiB
Go
127 lines
2.0 KiB
Go
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
|
|
}
|