Migrate casemapMap to xirc

This commit is contained in:
Simon Ser 2023-03-01 13:52:33 +01:00
parent 2b7a83b676
commit ebd101820b
5 changed files with 94 additions and 96 deletions

View File

@ -348,7 +348,7 @@ type downstreamConn struct {
lastBatchRef uint64 lastBatchRef uint64
monitored casemapMap[struct{}] monitored xirc.CaseMappingMap[struct{}]
} }
func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn { func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn {
@ -362,7 +362,7 @@ func newDownstreamConn(srv *Server, ic ircConn, id uint64) *downstreamConn {
nickCM: "*", nickCM: "*",
username: "~u", username: "~u",
caps: xirc.NewCapRegistry(), caps: xirc.NewCapRegistry(),
monitored: newCasemapMap[struct{}](xirc.CaseMappingASCII), monitored: xirc.NewCaseMappingMap[struct{}](xirc.CaseMappingASCII),
registration: new(downstreamRegistration), registration: new(downstreamRegistration),
} }
if host, _, err := net.SplitHostPort(remoteAddr); err == nil { if host, _, err := net.SplitHostPort(remoteAddr); err == nil {
@ -2650,17 +2650,17 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
} }
uc.updateMonitor() uc.updateMonitor()
case "C": // clear case "C": // clear
dc.monitored = newCasemapMap[struct{}](uc.network.casemap) dc.monitored = xirc.NewCaseMappingMap[struct{}](uc.network.casemap)
uc.updateMonitor() uc.updateMonitor()
case "L": // list case "L": // list
// TODO: be less lazy and pack the list // TODO: be less lazy and pack the list
for _, entry := range dc.monitored.m { dc.monitored.ForEach(func(name string, _ struct{}) {
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(), Prefix: dc.srv.prefix(),
Command: irc.RPL_MONLIST, Command: irc.RPL_MONLIST,
Params: []string{dc.nick, entry.originalKey}, Params: []string{dc.nick, name},
})
}) })
}
dc.SendMessage(&irc.Message{ dc.SendMessage(&irc.Message{
Prefix: dc.srv.prefix(), Prefix: dc.srv.prefix(),
Command: irc.RPL_ENDOFMONLIST, Command: irc.RPL_ENDOFMONLIST,
@ -2668,9 +2668,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
}) })
case "S": // status case "S": // status
// TODO: be less lazy and pack the lists // TODO: be less lazy and pack the lists
for _, entry := range dc.monitored.m { dc.monitored.ForEach(func(target string, _ struct{}) {
target := entry.originalKey
cmd := irc.RPL_MONOFFLINE cmd := irc.RPL_MONOFFLINE
if online := uc.monitored.Get(target); online { if online := uc.monitored.Get(target); online {
cmd = irc.RPL_MONONLINE cmd = irc.RPL_MONONLINE
@ -2685,7 +2683,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc.
Command: cmd, Command: cmd,
Params: []string{dc.nick, target}, Params: []string{dc.nick, target},
}) })
} })
} }
case "CHATHISTORY": case "CHATHISTORY":
var subcommand string var subcommand string

68
irc.go
View File

@ -218,74 +218,6 @@ func copyClientTags(tags irc.Tags) irc.Tags {
var stdCaseMapping = xirc.CaseMappingRFC1459 var stdCaseMapping = xirc.CaseMappingRFC1459
type casemapMap[V interface{}] struct {
m map[string]casemapEntry[V]
casemap xirc.CaseMapping
}
type casemapEntry[V interface{}] struct {
originalKey string
value V
}
func newCasemapMap[V interface{}](cm xirc.CaseMapping) casemapMap[V] {
return casemapMap[V]{
m: make(map[string]casemapEntry[V]),
casemap: cm,
}
}
func (cm *casemapMap[V]) Has(name string) bool {
_, ok := cm.m[cm.casemap(name)]
return ok
}
func (cm *casemapMap[V]) Len() int {
return len(cm.m)
}
func (cm *casemapMap[V]) Get(name string) V {
entry, ok := cm.m[cm.casemap(name)]
if !ok {
var v V
return v
}
return entry.value
}
func (cm *casemapMap[V]) Set(name string, value V) {
nameCM := cm.casemap(name)
entry, ok := cm.m[nameCM]
if !ok {
cm.m[nameCM] = casemapEntry[V]{
originalKey: name,
value: value,
}
return
}
entry.value = value
cm.m[nameCM] = entry
}
func (cm *casemapMap[V]) Del(name string) {
delete(cm.m, cm.casemap(name))
}
func (cm *casemapMap[V]) ForEach(f func(string, V)) {
for _, entry := range cm.m {
f(entry.originalKey, entry.value)
}
}
func (cm *casemapMap[V]) SetCaseMapping(newCasemap xirc.CaseMapping) {
cm.casemap = newCasemap
m := make(map[string]casemapEntry[V], len(cm.m))
for _, entry := range cm.m {
m[cm.casemap(entry.originalKey)] = entry
}
cm.m = m
}
func isWordBoundary(r rune) bool { func isWordBoundary(r rune) bool {
switch r { switch r {
case '-', '_', '|': // inspired from weechat.look.highlight_regex case '-', '_', '|': // inspired from weechat.look.highlight_regex

View File

@ -89,7 +89,7 @@ type upstreamChannel struct {
Status xirc.ChannelStatus Status xirc.ChannelStatus
modes channelModes modes channelModes
creationTime string creationTime string
Members casemapMap[*xirc.MembershipSet] Members xirc.CaseMappingMap[*xirc.MembershipSet]
complete bool complete bool
detachTimer *time.Timer detachTimer *time.Timer
} }
@ -208,14 +208,14 @@ type upstreamConn struct {
realname string realname string
hostname string hostname string
modes userModes modes userModes
channels casemapMap[*upstreamChannel] channels xirc.CaseMappingMap[*upstreamChannel]
users casemapMap[*upstreamUser] users xirc.CaseMappingMap[*upstreamUser]
caps xirc.CapRegistry caps xirc.CapRegistry
batches map[string]upstreamBatch batches map[string]upstreamBatch
away bool away bool
account string account string
nextLabelID uint64 nextLabelID uint64
monitored casemapMap[bool] monitored xirc.CaseMappingMap[bool]
saslClient sasl.Client saslClient sasl.Client
saslStarted bool saslStarted bool
@ -367,8 +367,8 @@ func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, er
conn: *newConn(network.user.srv, newNetIRCConn(netConn), &options), conn: *newConn(network.user.srv, newNetIRCConn(netConn), &options),
network: network, network: network,
user: network.user, user: network.user,
channels: newCasemapMap[*upstreamChannel](cm), channels: xirc.NewCaseMappingMap[*upstreamChannel](cm),
users: newCasemapMap[*upstreamUser](cm), users: xirc.NewCaseMappingMap[*upstreamUser](cm),
caps: xirc.NewCapRegistry(), caps: xirc.NewCapRegistry(),
batches: make(map[string]upstreamBatch), batches: make(map[string]upstreamBatch),
serverPrefix: &irc.Prefix{Name: "*"}, serverPrefix: &irc.Prefix{Name: "*"},
@ -377,7 +377,7 @@ func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, er
availableMemberships: stdMemberships, availableMemberships: stdMemberships,
isupport: make(map[string]*string), isupport: make(map[string]*string),
pendingCmds: make(map[string][]pendingUpstreamCommand), pendingCmds: make(map[string][]pendingUpstreamCommand),
monitored: newCasemapMap[bool](cm), monitored: xirc.NewCaseMappingMap[bool](cm),
hasDesiredNick: true, hasDesiredNick: true,
} }
return uc, nil return uc, nil
@ -1174,7 +1174,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
for _, ch := range strings.Split(channels, ",") { for _, ch := range strings.Split(channels, ",") {
if uc.isOurNick(msg.Prefix.Name) { if uc.isOurNick(msg.Prefix.Name) {
uc.logger.Printf("joined channel %q", ch) uc.logger.Printf("joined channel %q", ch)
members := newCasemapMap[*xirc.MembershipSet](uc.network.casemap) members := xirc.NewCaseMappingMap[*xirc.MembershipSet](uc.network.casemap)
uc.channels.Set(ch, &upstreamChannel{ uc.channels.Set(ch, &upstreamChannel{
Name: ch, Name: ch,
conn: uc, conn: uc,
@ -2259,10 +2259,10 @@ func (uc *upstreamConn) updateMonitor() {
var addList []string var addList []string
seen := make(map[string]struct{}) seen := make(map[string]struct{})
uc.forEachDownstream(func(dc *downstreamConn) { uc.forEachDownstream(func(dc *downstreamConn) {
for _, entry := range dc.monitored.m { dc.monitored.ForEach(func(target string, _ struct{}) {
targetCM := uc.network.casemap(entry.originalKey) targetCM := uc.network.casemap(target)
if targetCM == serviceNickCM { if targetCM == serviceNickCM {
continue return
} }
if !uc.monitored.Has(targetCM) { if !uc.monitored.Has(targetCM) {
if _, ok := add[targetCM]; !ok { if _, ok := add[targetCM]; !ok {
@ -2272,7 +2272,7 @@ func (uc *upstreamConn) updateMonitor() {
} else { } else {
seen[targetCM] = struct{}{} seen[targetCM] = struct{}{}
} }
} })
}) })
wantNick := database.GetNick(&uc.user.User, &uc.network.Network) wantNick := database.GetNick(&uc.user.User, &uc.network.Network)

12
user.go
View File

@ -93,11 +93,11 @@ type eventUserRun struct {
type deliveredClientMap map[string]string // client name -> msg ID type deliveredClientMap map[string]string // client name -> msg ID
type deliveredStore struct { type deliveredStore struct {
m casemapMap[deliveredClientMap] m xirc.CaseMappingMap[deliveredClientMap]
} }
func newDeliveredStore(cm xirc.CaseMapping) deliveredStore { func newDeliveredStore(cm xirc.CaseMapping) deliveredStore {
return deliveredStore{newCasemapMap[deliveredClientMap](cm)} return deliveredStore{xirc.NewCaseMappingMap[deliveredClientMap](cm)}
} }
func (ds deliveredStore) HasTarget(target string) bool { func (ds deliveredStore) HasTarget(target string) bool {
@ -147,9 +147,9 @@ type network struct {
stopped chan struct{} stopped chan struct{}
conn *upstreamConn conn *upstreamConn
channels casemapMap[*database.Channel] channels xirc.CaseMappingMap[*database.Channel]
delivered deliveredStore delivered deliveredStore
pushTargets casemapMap[time.Time] pushTargets xirc.CaseMappingMap[time.Time]
lastError error lastError error
casemap xirc.CaseMapping casemap xirc.CaseMapping
} }
@ -161,7 +161,7 @@ func newNetwork(user *user, record *database.Network, channels []database.Channe
// don't know which case-mapping will be used by the upstream server yet // don't know which case-mapping will be used by the upstream server yet
cm := xirc.CaseMappingNone cm := xirc.CaseMappingNone
m := newCasemapMap[*database.Channel](cm) m := xirc.NewCaseMappingMap[*database.Channel](cm)
for _, ch := range channels { for _, ch := range channels {
ch := ch ch := ch
m.Set(ch.Name, &ch) m.Set(ch.Name, &ch)
@ -174,7 +174,7 @@ func newNetwork(user *user, record *database.Network, channels []database.Channe
stopped: make(chan struct{}), stopped: make(chan struct{}),
channels: m, channels: m,
delivered: newDeliveredStore(cm), delivered: newDeliveredStore(cm),
pushTargets: newCasemapMap[time.Time](cm), pushTargets: xirc.NewCaseMappingMap[time.Time](cm),
casemap: stdCaseMapping, casemap: stdCaseMapping,
} }
} }

View File

@ -75,3 +75,71 @@ func ParseCaseMapping(s string) CaseMapping {
} }
return cm return cm
} }
type CaseMappingMap[V interface{}] struct {
m map[string]caseMappingEntry[V]
casemap CaseMapping
}
type caseMappingEntry[V interface{}] struct {
originalKey string
value V
}
func NewCaseMappingMap[V interface{}](cm CaseMapping) CaseMappingMap[V] {
return CaseMappingMap[V]{
m: make(map[string]caseMappingEntry[V]),
casemap: cm,
}
}
func (cmm *CaseMappingMap[V]) Has(name string) bool {
_, ok := cmm.m[cmm.casemap(name)]
return ok
}
func (cmm *CaseMappingMap[V]) Len() int {
return len(cmm.m)
}
func (cmm *CaseMappingMap[V]) Get(name string) V {
entry, ok := cmm.m[cmm.casemap(name)]
if !ok {
var v V
return v
}
return entry.value
}
func (cmm *CaseMappingMap[V]) Set(name string, value V) {
nameCM := cmm.casemap(name)
entry, ok := cmm.m[nameCM]
if !ok {
cmm.m[nameCM] = caseMappingEntry[V]{
originalKey: name,
value: value,
}
return
}
entry.value = value
cmm.m[nameCM] = entry
}
func (cmm *CaseMappingMap[V]) Del(name string) {
delete(cmm.m, cmm.casemap(name))
}
func (cmm *CaseMappingMap[V]) ForEach(f func(string, V)) {
for _, entry := range cmm.m {
f(entry.originalKey, entry.value)
}
}
func (cmm *CaseMappingMap[V]) SetCaseMapping(newCasemap CaseMapping) {
cmm.casemap = newCasemap
m := make(map[string]caseMappingEntry[V], len(cmm.m))
for _, entry := range cmm.m {
m[cmm.casemap(entry.originalKey)] = entry
}
cmm.m = m
}