protocol/aprs: refactored
This commit is contained in:
@@ -1,126 +1,82 @@
|
||||
package aprs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrAddressInvalid = errors.New(`aprs: invalid address`)
|
||||
)
|
||||
import "strings"
|
||||
|
||||
type Address struct {
|
||||
Call string `json:"call"`
|
||||
SSID string `json:"ssid,omitempty"`
|
||||
IsRepeated bool `json:"is_repeated,omitempty"`
|
||||
IsRepeated bool `json:"is_repeated"`
|
||||
}
|
||||
|
||||
func ParseAddress(s string) Address {
|
||||
r := strings.HasSuffix(s, "*")
|
||||
if r {
|
||||
s = strings.TrimSuffix(s, "*")
|
||||
}
|
||||
i := strings.IndexByte(s, '-')
|
||||
if i < 1 {
|
||||
return Address{
|
||||
Call: s,
|
||||
IsRepeated: r,
|
||||
}
|
||||
}
|
||||
return Address{
|
||||
Call: s[:i],
|
||||
SSID: s[i+1:],
|
||||
IsRepeated: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Address) EqualTo(b Address) bool {
|
||||
return a.Call == b.Call && a.SSID == b.SSID
|
||||
return strings.EqualFold(a.Call, b.Call) && a.SSID == b.SSID
|
||||
}
|
||||
|
||||
func (a Address) IsQConstruct() bool {
|
||||
return len(a.Call) == 3 && len(a.SSID) == 0 && a.Call[0] == 'q'
|
||||
}
|
||||
|
||||
func (a Address) Passcode() int16 {
|
||||
v := int16(0x73e2)
|
||||
for i, l := 0, len(a.Call); i < l; i = i + 2 {
|
||||
v ^= int16(a.Call[i]) << 8
|
||||
if i+1 < len(a.Call) {
|
||||
v ^= int16(a.Call[i+1])
|
||||
}
|
||||
}
|
||||
return v & 0x7fff
|
||||
}
|
||||
|
||||
func (a Address) String() string {
|
||||
var r = ""
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString(a.Call)
|
||||
if a.SSID != "" {
|
||||
b.WriteByte('-')
|
||||
b.WriteString(a.SSID)
|
||||
}
|
||||
if a.IsRepeated {
|
||||
r = "*"
|
||||
b.WriteByte('*')
|
||||
}
|
||||
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'
|
||||
return b.String()
|
||||
}
|
||||
|
||||
type Path []Address
|
||||
|
||||
func (p Path) String() string {
|
||||
var s = make([]string, len(p))
|
||||
for i, a := range p {
|
||||
s[i] = a.String()
|
||||
func (path Path) EqualTo(other Path) bool {
|
||||
if len(path) != len(other) {
|
||||
return false
|
||||
}
|
||||
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
|
||||
for i, a := range path {
|
||||
if !a.EqualTo(other[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return as, nil
|
||||
return true
|
||||
}
|
||||
|
||||
func (path Path) String() string {
|
||||
part := make([]string, len(path))
|
||||
for i, a := range path {
|
||||
part[i] = a.String()
|
||||
}
|
||||
return strings.Join(part, ",")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user