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

68
irc.go
View file

@ -218,74 +218,6 @@ func copyClientTags(tags irc.Tags) irc.Tags {
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 {
switch r {
case '-', '_', '|': // inspired from weechat.look.highlight_regex

View file

@ -89,7 +89,7 @@ type upstreamChannel struct {
Status xirc.ChannelStatus
modes channelModes
creationTime string
Members casemapMap[*xirc.MembershipSet]
Members xirc.CaseMappingMap[*xirc.MembershipSet]
complete bool
detachTimer *time.Timer
}
@ -208,14 +208,14 @@ type upstreamConn struct {
realname string
hostname string
modes userModes
channels casemapMap[*upstreamChannel]
users casemapMap[*upstreamUser]
channels xirc.CaseMappingMap[*upstreamChannel]
users xirc.CaseMappingMap[*upstreamUser]
caps xirc.CapRegistry
batches map[string]upstreamBatch
away bool
account string
nextLabelID uint64
monitored casemapMap[bool]
monitored xirc.CaseMappingMap[bool]
saslClient sasl.Client
saslStarted bool
@ -367,8 +367,8 @@ func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, er
conn: *newConn(network.user.srv, newNetIRCConn(netConn), &options),
network: network,
user: network.user,
channels: newCasemapMap[*upstreamChannel](cm),
users: newCasemapMap[*upstreamUser](cm),
channels: xirc.NewCaseMappingMap[*upstreamChannel](cm),
users: xirc.NewCaseMappingMap[*upstreamUser](cm),
caps: xirc.NewCapRegistry(),
batches: make(map[string]upstreamBatch),
serverPrefix: &irc.Prefix{Name: "*"},
@ -377,7 +377,7 @@ func connectToUpstream(ctx context.Context, network *network) (*upstreamConn, er
availableMemberships: stdMemberships,
isupport: make(map[string]*string),
pendingCmds: make(map[string][]pendingUpstreamCommand),
monitored: newCasemapMap[bool](cm),
monitored: xirc.NewCaseMappingMap[bool](cm),
hasDesiredNick: true,
}
return uc, nil
@ -1174,7 +1174,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err
for _, ch := range strings.Split(channels, ",") {
if uc.isOurNick(msg.Prefix.Name) {
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{
Name: ch,
conn: uc,
@ -2259,10 +2259,10 @@ func (uc *upstreamConn) updateMonitor() {
var addList []string
seen := make(map[string]struct{})
uc.forEachDownstream(func(dc *downstreamConn) {
for _, entry := range dc.monitored.m {
targetCM := uc.network.casemap(entry.originalKey)
dc.monitored.ForEach(func(target string, _ struct{}) {
targetCM := uc.network.casemap(target)
if targetCM == serviceNickCM {
continue
return
}
if !uc.monitored.Has(targetCM) {
if _, ok := add[targetCM]; !ok {
@ -2272,7 +2272,7 @@ func (uc *upstreamConn) updateMonitor() {
} else {
seen[targetCM] = struct{}{}
}
}
})
})
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 deliveredStore struct {
m casemapMap[deliveredClientMap]
m xirc.CaseMappingMap[deliveredClientMap]
}
func newDeliveredStore(cm xirc.CaseMapping) deliveredStore {
return deliveredStore{newCasemapMap[deliveredClientMap](cm)}
return deliveredStore{xirc.NewCaseMappingMap[deliveredClientMap](cm)}
}
func (ds deliveredStore) HasTarget(target string) bool {
@ -147,9 +147,9 @@ type network struct {
stopped chan struct{}
conn *upstreamConn
channels casemapMap[*database.Channel]
channels xirc.CaseMappingMap[*database.Channel]
delivered deliveredStore
pushTargets casemapMap[time.Time]
pushTargets xirc.CaseMappingMap[time.Time]
lastError error
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
cm := xirc.CaseMappingNone
m := newCasemapMap[*database.Channel](cm)
m := xirc.NewCaseMappingMap[*database.Channel](cm)
for _, ch := range channels {
ch := ch
m.Set(ch.Name, &ch)
@ -174,7 +174,7 @@ func newNetwork(user *user, record *database.Network, channels []database.Channe
stopped: make(chan struct{}),
channels: m,
delivered: newDeliveredStore(cm),
pushTargets: newCasemapMap[time.Time](cm),
pushTargets: xirc.NewCaseMappingMap[time.Time](cm),
casemap: stdCaseMapping,
}
}

View file

@ -75,3 +75,71 @@ func ParseCaseMapping(s string) CaseMapping {
}
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
}