// Copyright 2024 Matthew Rich . All rights reserved. package identity import ( "os" "fmt" "strings" "net/url" "feudal/sequence" ) var Serial sequence.Serial32 var spid uint64 var serial uint64 var hostname string type Addresser interface { Address() string } type Identifier interface { Addresser Instance() string Path() string Hostname() string String() string Parent() Identifier CreateChild(string) Identifier } type Id struct { parent Identifier Name string url *url.URL instance string } func init() { Serial = sequence.NewSerial32() spid = uint64(os.Getpid()) << 32 hostname, _ = os.Hostname() } func New(parent Identifier, name string) Identifier { url,_ := url.Parse(parent.Address()) url.Path += "/" + name i := &Id{ parent: parent, Name: name, url: url, instance: InstanceId() } return i } func NewRoot(name string) Identifier { return &Id{ parent: nil, Name: name, url: &url.URL{ Scheme: "feudal", User: url.User(name), Host: hostname, Path: "" }, instance: InstanceId() } } func NewFromAddress(address string) Identifier { id := &Id{ parent: nil, instance: InstanceId() } id.url,_ = url.Parse(address) elements := strings.Split(id.url.Path, "/") le := len(elements) if le == 0 { id.Name = id.url.User.Username() } else { id.Name = elements[le - 1] } return id } func InstanceId() string { return fmt.Sprintf("%x", spid | uint64(Serial())) } func (i *Id) Instance() string { return i.instance } func (i *Id) Path() string { return i.url.Path } func (i *Id) Hostname() string { return i.url.Hostname() } func (parent *Id) CreateChild(name string) Identifier { url,_ := url.Parse(parent.Address()) url.Path += "/" + name i := &Id{ parent: parent, Name: name, url: url, instance: InstanceId() } return i } func (i *Id) Parent() Identifier { return i.parent } func (i *Id) Elements() []string { return strings.Split(i.url.Path, "/") } func (i *Id) String() string { return i.Address() + "#" + i.instance } func (i *Id) Address() string { return i.url.String() }