From f9c4ba636f46901e47dc77411b5ebbfedc94b17e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 30 May 2022 09:12:28 +0200 Subject: [PATCH] xirc: move over Membership --- bridge.go | 4 ++-- irc.go | 62 ++++++++-------------------------------------------- upstream.go | 18 +++++++-------- xirc/xirc.go | 45 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 64 deletions(-) diff --git a/bridge.go b/bridge.go index 82c0301..ee23ae3 100644 --- a/bridge.go +++ b/bridge.go @@ -76,8 +76,8 @@ func sendNames(dc *downstreamConn, ch *upstreamChannel) { var members []string for _, entry := range ch.Members.innerMap { nick := entry.originalKey - memberships := entry.value.(*memberships) - s := memberships.Format(dc) + dc.marshalEntity(ch.conn.network, nick) + memberships := entry.value.(*xirc.MembershipSet) + s := formatMemberPrefix(*memberships, dc) + dc.marshalEntity(ch.conn.network, nick) members = append(members, s) } diff --git a/irc.go b/irc.go index a56fc23..fc4ee11 100644 --- a/irc.go +++ b/irc.go @@ -180,12 +180,7 @@ func (cm channelModes) Format() (modeString string, parameters []string) { const stdChannelTypes = "#&+!" -type membership struct { - Mode byte - Prefix byte -} - -var stdMemberships = []membership{ +var stdMemberships = []xirc.Membership{ {'q', '~'}, // founder {'a', '&'}, // protected {'o', '@'}, // operator @@ -193,55 +188,16 @@ var stdMemberships = []membership{ {'v', '+'}, // voice } -// memberships always sorted by descending membership rank -type memberships []membership - -func (m *memberships) Add(availableMemberships []membership, newMembership membership) { - l := *m - i := 0 - for _, availableMembership := range availableMemberships { - if i >= len(l) { - break - } - if l[i] == availableMembership { - if availableMembership == newMembership { - // we already have this membership - return - } - i++ - continue - } - if availableMembership == newMembership { - break - } - } - // insert newMembership at i - l = append(l, membership{}) - copy(l[i+1:], l[i:]) - l[i] = newMembership - *m = l -} - -func (m *memberships) Remove(oldMembership membership) { - l := *m - for i, currentMembership := range l { - if currentMembership == oldMembership { - *m = append(l[:i], l[i+1:]...) - return - } - } -} - -func (m memberships) Format(dc *downstreamConn) string { +func formatMemberPrefix(ms xirc.MembershipSet, dc *downstreamConn) string { if !dc.caps.IsEnabled("multi-prefix") { - if len(m) == 0 { + if len(ms) == 0 { return "" } - return string(m[0].Prefix) + return string(ms[0].Prefix) } - prefixes := make([]byte, len(m)) - for i, membership := range m { - prefixes[i] = membership.Prefix + prefixes := make([]byte, len(ms)) + for i, m := range ms { + prefixes[i] = m.Prefix } return string(prefixes) } @@ -439,12 +395,12 @@ func (cm *channelCasemapMap) Value(name string) *database.Channel { type membershipsCasemapMap struct{ casemapMap } -func (cm *membershipsCasemapMap) Value(name string) *memberships { +func (cm *membershipsCasemapMap) Value(name string) *xirc.MembershipSet { entry, ok := cm.innerMap[cm.casemap(name)] if !ok { return nil } - return entry.value.(*memberships) + return entry.value.(*xirc.MembershipSet) } type deliveredCasemapMap struct{ casemapMap } diff --git a/upstream.go b/upstream.go index 9ceb076..c474083 100644 --- a/upstream.go +++ b/upstream.go @@ -119,7 +119,7 @@ type upstreamConn struct { availableUserModes string availableChannelModes map[byte]channelModeType availableChannelTypes string - availableMemberships []membership + availableMemberships []xirc.Membership isupport map[string]*string registered bool @@ -413,8 +413,8 @@ func (uc *upstreamConn) cancelPendingCommandsByDownstreamID(downstreamID uint64) } } -func (uc *upstreamConn) parseMembershipPrefix(s string) (ms *memberships, nick string) { - memberships := make(memberships, 0, 4) +func (uc *upstreamConn) parseMembershipPrefix(s string) (ms xirc.MembershipSet, nick string) { + var memberships xirc.MembershipSet i := 0 for _, m := range uc.availableMemberships { if i >= len(s) { @@ -425,7 +425,7 @@ func (uc *upstreamConn) parseMembershipPrefix(s string) (ms *memberships, nick s i++ } } - return &memberships, s[i:] + return memberships, s[i:] } func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) error { @@ -1021,7 +1021,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if err != nil { return err } - ch.Members.SetValue(msg.Prefix.Name, &memberships{}) + ch.Members.SetValue(msg.Prefix.Name, &xirc.MembershipSet{}) } chMsg := msg.Copy() @@ -1340,7 +1340,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err members := splitSpace(members) for i, member := range members { memberships, nick := uc.parseMembershipPrefix(member) - members[i] = memberships.Format(dc) + dc.marshalEntity(uc.network, nick) + members[i] = formatMemberPrefix(memberships, dc) + dc.marshalEntity(uc.network, nick) } memberStr := strings.Join(members, " ") @@ -1484,7 +1484,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err for i, channel := range channels { prefix, channel := uc.parseMembershipPrefix(channel) channel = dc.marshalEntity(uc.network, channel) - l[i] = prefix.Format(dc) + channel + l[i] = formatMemberPrefix(prefix, dc) + channel } channelList = strings.Join(l, " ") dc.SendMessage(&irc.Message{ @@ -1842,9 +1842,9 @@ func (uc *upstreamConn) handleMemberships(s string) error { if sep < 0 || len(s) != sep*2 { return fmt.Errorf("malformed ISUPPORT PREFIX value: %v", s) } - memberships := make([]membership, len(s)/2-1) + memberships := make([]xirc.Membership, len(s)/2-1) for i := range memberships { - memberships[i] = membership{ + memberships[i] = xirc.Membership{ Mode: s[i+1], Prefix: s[sep+i+1], } diff --git a/xirc/xirc.go b/xirc/xirc.go index 332d8af..0a9ac33 100644 --- a/xirc/xirc.go +++ b/xirc/xirc.go @@ -86,3 +86,48 @@ func ParseChannelStatus(s string) (ChannelStatus, error) { return 0, fmt.Errorf("invalid channel status %q: unknown status", s) } } + +// Membership is a channel member rank. +type Membership struct { + Mode byte + Prefix byte +} + +// MembershipSet is a set of memberships sorted by descending rank. +type MembershipSet []Membership + +func (ms *MembershipSet) Add(availableMemberships []Membership, newMembership Membership) { + l := *ms + i := 0 + for _, availableMembership := range availableMemberships { + if i >= len(l) { + break + } + if l[i] == availableMembership { + if availableMembership == newMembership { + // we already have this membership + return + } + i++ + continue + } + if availableMembership == newMembership { + break + } + } + // insert newMembership at i + l = append(l, Membership{}) + copy(l[i+1:], l[i:]) + l[i] = newMembership + *ms = l +} + +func (ms *MembershipSet) Remove(membership Membership) { + l := *ms + for i, m := range l { + if m == membership { + *ms = append(l[:i], l[i+1:]...) + return + } + } +}