mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-21 11:16:39 +00:00
[performance] minimise log field allocations (#3529)
* when appending log field only do so by minimal amount * move slice utils to separate package to fix import cycle, add GrowJust() and AppendJust() functions * fix GrowJust() not returning slice of same length * improved xslices tests * make AppendJust() test check for slice contents, fix AppendJust() final copying behaviour * add a +1 with field growth to try minimise allocation for log 'msg' field
This commit is contained in:
parent
98eef328ea
commit
e3c2b790fd
|
@ -36,6 +36,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/dialect"
|
"github.com/uptrace/bun/dialect"
|
||||||
)
|
)
|
||||||
|
@ -86,7 +87,7 @@ func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||||
// Reorder the statuses by their
|
// Reorder the statuses by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(a *gtsmodel.Account) string { return a.ID }
|
getID := func(a *gtsmodel.Account) string { return a.ID }
|
||||||
util.OrderBy(accounts, ids, getID)
|
xslices.OrderBy(accounts, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ func(uncached []string) ([]*gtsmodel.Token, error) {
|
||||||
// Reoroder the tokens by their
|
// Reoroder the tokens by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(t *gtsmodel.Token) string { return t.ID }
|
getID := func(t *gtsmodel.Token) string { return t.ID }
|
||||||
util.OrderBy(tokens, tokenIDs, getID)
|
xslices.OrderBy(tokens, tokenIDs, getID)
|
||||||
|
|
||||||
return tokens, nil
|
return tokens, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/dialect"
|
"github.com/uptrace/bun/dialect"
|
||||||
)
|
)
|
||||||
|
@ -209,7 +209,7 @@ func(accountID string, uncached []string) ([]*gtsmodel.Conversation, error) {
|
||||||
|
|
||||||
// Reorder the conversations by their last status IDs to ensure correct order.
|
// Reorder the conversations by their last status IDs to ensure correct order.
|
||||||
getID := func(b *gtsmodel.Conversation) string { return b.ID }
|
getID := func(b *gtsmodel.Conversation) string { return b.ID }
|
||||||
util.OrderBy(conversations, conversationLastStatusIDs, getID)
|
xslices.OrderBy(conversations, conversationLastStatusIDs, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
@ -558,7 +558,7 @@ func (c *conversationDB) DeleteStatusFromConversations(ctx context.Context, stat
|
||||||
|
|
||||||
// Invalidate cache entries.
|
// Invalidate cache entries.
|
||||||
updatedConversationIDs = append(updatedConversationIDs, deletedConversationIDs...)
|
updatedConversationIDs = append(updatedConversationIDs, deletedConversationIDs...)
|
||||||
updatedConversationIDs = util.Deduplicate(updatedConversationIDs)
|
updatedConversationIDs = xslices.Deduplicate(updatedConversationIDs)
|
||||||
c.state.Caches.DB.Conversation.InvalidateIDs("ID", updatedConversationIDs)
|
c.state.Caches.DB.Conversation.InvalidateIDs("ID", updatedConversationIDs)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/dialect"
|
"github.com/uptrace/bun/dialect"
|
||||||
)
|
)
|
||||||
|
@ -597,7 +597,7 @@ func(uncached []string) ([]*gtsmodel.Emoji, error) {
|
||||||
// Reorder the emojis by their
|
// Reorder the emojis by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(e *gtsmodel.Emoji) string { return e.ID }
|
getID := func(e *gtsmodel.Emoji) string { return e.ID }
|
||||||
util.OrderBy(emojis, ids, getID)
|
xslices.OrderBy(emojis, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
@ -661,7 +661,7 @@ func(uncached []string) ([]*gtsmodel.EmojiCategory, error) {
|
||||||
// Reorder the categories by their
|
// Reorder the categories by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(c *gtsmodel.EmojiCategory) string { return c.ID }
|
getID := func(c *gtsmodel.EmojiCategory) string { return c.ID }
|
||||||
util.OrderBy(categories, ids, getID)
|
xslices.OrderBy(categories, ids, getID)
|
||||||
|
|
||||||
return categories, nil
|
return categories, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ func(uncached []string) ([]*gtsmodel.Filter, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the filter structs in the same order as the filter IDs.
|
// Put the filter structs in the same order as the filter IDs.
|
||||||
util.OrderBy(filters, filterIDs, func(filter *gtsmodel.Filter) string { return filter.ID })
|
xslices.OrderBy(filters, filterIDs, func(filter *gtsmodel.Filter) string { return filter.ID })
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
return filters, nil
|
return filters, nil
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ func(uncached []string) ([]*gtsmodel.FilterKeyword, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the filter keyword structs in the same order as the filter keyword IDs.
|
// Put the filter keyword structs in the same order as the filter keyword IDs.
|
||||||
util.OrderBy(filterKeywords, filterKeywordIDs, func(filterKeyword *gtsmodel.FilterKeyword) string {
|
xslices.OrderBy(filterKeywords, filterKeywordIDs, func(filterKeyword *gtsmodel.FilterKeyword) string {
|
||||||
return filterKeyword.ID
|
return filterKeyword.ID
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ func(uncached []string) ([]*gtsmodel.FilterStatus, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the filter status structs in the same order as the filter status IDs.
|
// Put the filter status structs in the same order as the filter status IDs.
|
||||||
util.OrderBy(filterStatuses, filterStatusIDs, func(filterStatus *gtsmodel.FilterStatus) string {
|
xslices.OrderBy(filterStatuses, filterStatusIDs, func(filterStatus *gtsmodel.FilterStatus) string {
|
||||||
return filterStatus.ID
|
return filterStatus.ID
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func(uncached []string) ([]*gtsmodel.InteractionRequest, error) {
|
||||||
// Reorder the requests by their
|
// Reorder the requests by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(r *gtsmodel.InteractionRequest) string { return r.ID }
|
getID := func(r *gtsmodel.InteractionRequest) string { return r.ID }
|
||||||
util.OrderBy(requests, ids, getID)
|
xslices.OrderBy(requests, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ func(uncached []string) ([]*gtsmodel.List, error) {
|
||||||
// Reorder the lists by their
|
// Reorder the lists by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(l *gtsmodel.List) string { return l.ID }
|
getID := func(l *gtsmodel.List) string { return l.ID }
|
||||||
util.OrderBy(lists, ids, getID)
|
xslices.OrderBy(lists, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
@ -387,12 +387,12 @@ func (l *listDB) PutListEntries(ctx context.Context, entries []*gtsmodel.ListEnt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect unique list IDs from the provided list entries.
|
// Collect unique list IDs from the provided list entries.
|
||||||
listIDs := util.Collate(entries, func(e *gtsmodel.ListEntry) string {
|
listIDs := xslices.Collate(entries, func(e *gtsmodel.ListEntry) string {
|
||||||
return e.ListID
|
return e.ListID
|
||||||
})
|
})
|
||||||
|
|
||||||
// Collect unique follow IDs from the provided list entries.
|
// Collect unique follow IDs from the provided list entries.
|
||||||
followIDs := util.Collate(entries, func(e *gtsmodel.ListEntry) string {
|
followIDs := xslices.Collate(entries, func(e *gtsmodel.ListEntry) string {
|
||||||
return e.FollowID
|
return e.FollowID
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -441,7 +441,7 @@ func (l *listDB) DeleteAllListEntriesByFollows(ctx context.Context, followIDs ..
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deduplicate IDs before invalidate.
|
// Deduplicate IDs before invalidate.
|
||||||
listIDs = util.Deduplicate(listIDs)
|
listIDs = xslices.Deduplicate(listIDs)
|
||||||
|
|
||||||
// Invalidate all related list entry caches.
|
// Invalidate all related list entry caches.
|
||||||
l.invalidateEntryCaches(ctx, listIDs, followIDs)
|
l.invalidateEntryCaches(ctx, listIDs, followIDs)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ func(uncached []string) ([]*gtsmodel.MediaAttachment, error) {
|
||||||
// Reorder the media by their
|
// Reorder the media by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(m *gtsmodel.MediaAttachment) string { return m.ID }
|
getID := func(m *gtsmodel.MediaAttachment) string { return m.ID }
|
||||||
util.OrderBy(media, ids, getID)
|
xslices.OrderBy(media, ids, getID)
|
||||||
|
|
||||||
return media, nil
|
return media, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ func(uncached []string) ([]*gtsmodel.Mention, error) {
|
||||||
// Reorder the mentions by their
|
// Reorder the mentions by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(m *gtsmodel.Mention) string { return m.ID }
|
getID := func(m *gtsmodel.Mention) string { return m.ID }
|
||||||
util.OrderBy(mentions, ids, getID)
|
xslices.OrderBy(mentions, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ func(uncached []string) ([]*gtsmodel.Notification, error) {
|
||||||
// Reorder the notifs by their
|
// Reorder the notifs by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(n *gtsmodel.Notification) string { return n.ID }
|
getID := func(n *gtsmodel.Notification) string { return n.ID }
|
||||||
util.OrderBy(notifs, ids, getID)
|
xslices.OrderBy(notifs, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ func(uncached []string) ([]*gtsmodel.PollVote, error) {
|
||||||
// Reorder the poll votes by their
|
// Reorder the poll votes by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(v *gtsmodel.PollVote) string { return v.ID }
|
getID := func(v *gtsmodel.PollVote) string { return v.ID }
|
||||||
util.OrderBy(votes, voteIDs, getID)
|
xslices.OrderBy(votes, voteIDs, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ func(uncached []string) ([]*gtsmodel.Block, error) {
|
||||||
// Reorder the blocks by their
|
// Reorder the blocks by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(b *gtsmodel.Block) string { return b.ID }
|
getID := func(b *gtsmodel.Block) string { return b.ID }
|
||||||
util.OrderBy(blocks, ids, getID)
|
xslices.OrderBy(blocks, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ func(uncached []string) ([]*gtsmodel.Follow, error) {
|
||||||
// Reorder the follows by their
|
// Reorder the follows by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(f *gtsmodel.Follow) string { return f.ID }
|
getID := func(f *gtsmodel.Follow) string { return f.ID }
|
||||||
util.OrderBy(follows, ids, getID)
|
xslices.OrderBy(follows, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
@ -376,7 +376,7 @@ func (r *relationshipDB) DeleteAccountFollows(ctx context.Context, accountID str
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather the follow IDs that were deleted for removing related list entries.
|
// Gather the follow IDs that were deleted for removing related list entries.
|
||||||
followIDs := util.Gather(nil, deleted, func(follow *gtsmodel.Follow) string {
|
followIDs := xslices.Gather(nil, deleted, func(follow *gtsmodel.Follow) string {
|
||||||
return follow.ID
|
return follow.ID
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ func(uncached []string) ([]*gtsmodel.FollowRequest, error) {
|
||||||
// Reorder the requests by their
|
// Reorder the requests by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(f *gtsmodel.FollowRequest) string { return f.ID }
|
getID := func(f *gtsmodel.FollowRequest) string { return f.ID }
|
||||||
util.OrderBy(follows, ids, getID)
|
xslices.OrderBy(follows, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
"github.com/uptrace/bun/dialect"
|
"github.com/uptrace/bun/dialect"
|
||||||
)
|
)
|
||||||
|
@ -109,7 +109,7 @@ func(uncached []string) ([]*gtsmodel.UserMute, error) {
|
||||||
// Reorder the mutes by their
|
// Reorder the mutes by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(b *gtsmodel.UserMute) string { return b.ID }
|
getID := func(b *gtsmodel.UserMute) string { return b.ID }
|
||||||
util.OrderBy(mutes, ids, getID)
|
xslices.OrderBy(mutes, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func(uncached []string) ([]*gtsmodel.Status, error) {
|
||||||
// Reorder the statuses by their
|
// Reorder the statuses by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(s *gtsmodel.Status) string { return s.ID }
|
getID := func(s *gtsmodel.Status) string { return s.ID }
|
||||||
util.OrderBy(statuses, ids, getID)
|
xslices.OrderBy(statuses, ids, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ func(uncached []string) ([]*gtsmodel.StatusBookmark, error) {
|
||||||
// Reorder the bookmarks by their
|
// Reorder the bookmarks by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(b *gtsmodel.StatusBookmark) string { return b.ID }
|
getID := func(b *gtsmodel.StatusBookmark) string { return b.ID }
|
||||||
util.OrderBy(bookmarks, ids, getID)
|
xslices.OrderBy(bookmarks, ids, getID)
|
||||||
|
|
||||||
// Populate all loaded bookmarks, removing those we fail
|
// Populate all loaded bookmarks, removing those we fail
|
||||||
// to populate (removes needing so many later nil checks).
|
// to populate (removes needing so many later nil checks).
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ func(uncached []string) ([]*gtsmodel.StatusFave, error) {
|
||||||
// Reorder the statuses by their
|
// Reorder the statuses by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(f *gtsmodel.StatusFave) string { return f.ID }
|
getID := func(f *gtsmodel.StatusFave) string { return f.ID }
|
||||||
util.OrderBy(faves, faveIDs, getID)
|
xslices.OrderBy(faves, faveIDs, getID)
|
||||||
|
|
||||||
if gtscontext.Barebones(ctx) {
|
if gtscontext.Barebones(ctx) {
|
||||||
// no need to fully populate.
|
// no need to fully populate.
|
||||||
|
@ -339,7 +339,7 @@ func (s *statusFaveDB) DeleteStatusFaves(ctx context.Context, targetAccountID st
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deduplicate determined status IDs.
|
// Deduplicate determined status IDs.
|
||||||
statusIDs = util.Deduplicate(statusIDs)
|
statusIDs = xslices.Deduplicate(statusIDs)
|
||||||
|
|
||||||
// Invalidate any cached status faves for this status ID.
|
// Invalidate any cached status faves for this status ID.
|
||||||
s.state.Caches.DB.StatusFave.InvalidateIDs("ID", statusIDs)
|
s.state.Caches.DB.StatusFave.InvalidateIDs("ID", statusIDs)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
"github.com/superseriousbusiness/gotosocial/internal/paging"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/state"
|
"github.com/superseriousbusiness/gotosocial/internal/state"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ func(uncached []string) ([]*gtsmodel.Tag, error) {
|
||||||
// Reorder the tags by their
|
// Reorder the tags by their
|
||||||
// IDs to ensure in correct order.
|
// IDs to ensure in correct order.
|
||||||
getID := func(t *gtsmodel.Tag) string { return t.ID }
|
getID := func(t *gtsmodel.Tag) string { return t.ID }
|
||||||
util.OrderBy(tags, ids, getID)
|
xslices.OrderBy(tags, ids, getID)
|
||||||
|
|
||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
|
@ -301,5 +301,5 @@ func (t *tagDB) GetAccountIDsFollowingTagIDs(ctx context.Context, tagIDs []strin
|
||||||
|
|
||||||
// Accounts might be following multiple tags in list,
|
// Accounts might be following multiple tags in list,
|
||||||
// but we only want to return each account once.
|
// but we only want to return each account once.
|
||||||
return util.Deduplicate(accountIDs), nil
|
return xslices.Deduplicate(accountIDs), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type errOtherIRIBlocked struct {
|
type errOtherIRIBlocked struct {
|
||||||
|
@ -162,7 +162,7 @@ func (f *Federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques
|
||||||
|
|
||||||
// OtherIRIs will likely contain some
|
// OtherIRIs will likely contain some
|
||||||
// duplicate entries now, so remove them.
|
// duplicate entries now, so remove them.
|
||||||
otherIRIs = util.DeduplicateFunc(otherIRIs,
|
otherIRIs = xslices.DeduplicateFunc(otherIRIs,
|
||||||
(*url.URL).String, // serialized URL is 'key()'
|
(*url.URL).String, // serialized URL is 'key()'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Conversation represents direct messages between the owner account and a set of other accounts.
|
// Conversation represents direct messages between the owner account and a set of other accounts.
|
||||||
|
@ -62,7 +62,7 @@ type Conversation struct {
|
||||||
|
|
||||||
// ConversationOtherAccountsKey creates an OtherAccountsKey from a list of OtherAccountIDs.
|
// ConversationOtherAccountsKey creates an OtherAccountsKey from a list of OtherAccountIDs.
|
||||||
func ConversationOtherAccountsKey(otherAccountIDs []string) string {
|
func ConversationOtherAccountsKey(otherAccountIDs []string) string {
|
||||||
otherAccountIDs = util.Deduplicate(otherAccountIDs)
|
otherAccountIDs = xslices.Deduplicate(otherAccountIDs)
|
||||||
slices.Sort(otherAccountIDs)
|
slices.Sort(otherAccountIDs)
|
||||||
return strings.Join(otherAccountIDs, ",")
|
return strings.Join(otherAccountIDs, ",")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"codeberg.org/gruf/go-kv"
|
"codeberg.org/gruf/go-kv"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -412,7 +412,10 @@ func logf(ctx context.Context, depth int, lvl LEVEL, fields []kv.Field, s string
|
||||||
buf.B = append(buf.B, lvlstrs[lvl]...)
|
buf.B = append(buf.B, lvlstrs[lvl]...)
|
||||||
buf.B = append(buf.B, ' ')
|
buf.B = append(buf.B, ' ')
|
||||||
|
|
||||||
if ctx != nil {
|
if ctx != nil && len(ctxhooks) > 0 {
|
||||||
|
// Ensure fields have space for hooks (+1 for below).
|
||||||
|
fields = xslices.GrowJust(fields, len(ctxhooks)+1)
|
||||||
|
|
||||||
// Pass context through hooks.
|
// Pass context through hooks.
|
||||||
for _, hook := range ctxhooks {
|
for _, hook := range ctxhooks {
|
||||||
fields = hook(ctx, fields)
|
fields = hook(ctx, fields)
|
||||||
|
@ -420,9 +423,8 @@ func logf(ctx context.Context, depth int, lvl LEVEL, fields []kv.Field, s string
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != "" {
|
if s != "" {
|
||||||
// Append message to log fields.
|
// Append message (if given) as final log field.
|
||||||
fields = slices.Grow(fields, 1)
|
fields = xslices.AppendJust(fields, kv.Field{
|
||||||
fields = append(fields, kv.Field{
|
|
||||||
K: "msg", V: fmt.Sprintf(s, a...),
|
K: "msg", V: fmt.Sprintf(s, a...),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Processor) Alias(
|
func (p *Processor) Alias(
|
||||||
|
@ -137,8 +137,8 @@ type uri struct {
|
||||||
// Dedupe URIs + accounts, in case someone
|
// Dedupe URIs + accounts, in case someone
|
||||||
// provided both an account URL and an
|
// provided both an account URL and an
|
||||||
// account URI above, for the same account.
|
// account URI above, for the same account.
|
||||||
account.AlsoKnownAsURIs = util.Deduplicate(account.AlsoKnownAsURIs)
|
account.AlsoKnownAsURIs = xslices.Deduplicate(account.AlsoKnownAsURIs)
|
||||||
account.AlsoKnownAs = util.DeduplicateFunc(
|
account.AlsoKnownAs = xslices.DeduplicateFunc(
|
||||||
account.AlsoKnownAs,
|
account.AlsoKnownAs,
|
||||||
func(a *gtsmodel.Account) string {
|
func(a *gtsmodel.Account) string {
|
||||||
return a.URI
|
return a.URI
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create processes the given form to create a new status, returning the api model representation of that status if it's OK.
|
// Create processes the given form to create a new status, returning the api model representation of that status if it's OK.
|
||||||
|
@ -536,9 +537,9 @@ func (p *Processor) processContent(ctx context.Context, parseMention gtsmodel.Pa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather all the database IDs from each of the gathered status mentions, tags, and emojis.
|
// Gather all the database IDs from each of the gathered status mentions, tags, and emojis.
|
||||||
status.MentionIDs = util.Gather(nil, status.Mentions, func(mention *gtsmodel.Mention) string { return mention.ID })
|
status.MentionIDs = xslices.Gather(nil, status.Mentions, func(mention *gtsmodel.Mention) string { return mention.ID })
|
||||||
status.TagIDs = util.Gather(nil, status.Tags, func(tag *gtsmodel.Tag) string { return tag.ID })
|
status.TagIDs = xslices.Gather(nil, status.Tags, func(tag *gtsmodel.Tag) string { return tag.ID })
|
||||||
status.EmojiIDs = util.Gather(nil, status.Emojis, func(emoji *gtsmodel.Emoji) string { return emoji.ID })
|
status.EmojiIDs = xslices.Gather(nil, status.Emojis, func(emoji *gtsmodel.Emoji) string { return emoji.ID })
|
||||||
|
|
||||||
if status.ContentWarning != "" && len(status.AttachmentIDs) > 0 {
|
if status.ContentWarning != "" && len(status.AttachmentIDs) > 0 {
|
||||||
// If a content-warning is set, and
|
// If a content-warning is set, and
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccountToAS converts a gts model account into an activity streams person, suitable for federation
|
// AccountToAS converts a gts model account into an activity streams person, suitable for federation
|
||||||
|
@ -1819,7 +1819,7 @@ func populateValuesForProp[T ap.WithIRI](
|
||||||
// Deduplicate the iri strings to
|
// Deduplicate the iri strings to
|
||||||
// make sure we're not parsing + adding
|
// make sure we're not parsing + adding
|
||||||
// the same string multiple times.
|
// the same string multiple times.
|
||||||
iriStrs = util.Deduplicate(iriStrs)
|
iriStrs = xslices.Deduplicate(iriStrs)
|
||||||
|
|
||||||
// Append them to the property.
|
// Append them to the property.
|
||||||
for _, iriStr := range iriStrs {
|
for _, iriStr := range iriStrs {
|
||||||
|
|
|
@ -15,12 +15,53 @@
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package util
|
package xslices
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GrowJust increases slice capacity to guarantee
|
||||||
|
// extra room 'size', where in the case that it does
|
||||||
|
// need to allocate more it ONLY allocates 'size' extra.
|
||||||
|
// This is different to typical slices.Grow behaviour,
|
||||||
|
// which simply guarantees extra through append() which
|
||||||
|
// may allocate more than necessary extra size.
|
||||||
|
func GrowJust[T any](in []T, size int) []T {
|
||||||
|
|
||||||
|
if cap(in)-len(in) < size {
|
||||||
|
// Reallocate enough for in + size.
|
||||||
|
in2 := make([]T, len(in), len(in)+size)
|
||||||
|
_ = copy(in2, in)
|
||||||
|
in = in2
|
||||||
|
}
|
||||||
|
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendJust appends extra elements to slice,
|
||||||
|
// ONLY allocating at most len(extra) elements. This
|
||||||
|
// is different to the typical append behaviour which
|
||||||
|
// will append extra, in a manner to reduce the need
|
||||||
|
// for new allocations on every call to append.
|
||||||
|
func AppendJust[T any](in []T, extra ...T) []T {
|
||||||
|
l := len(in)
|
||||||
|
|
||||||
|
if cap(in)-l < len(extra) {
|
||||||
|
// Reallocate enough for + extra.
|
||||||
|
in2 := make([]T, l+len(extra))
|
||||||
|
_ = copy(in2, in)
|
||||||
|
in = in2
|
||||||
|
} else {
|
||||||
|
// Reslice for + extra.
|
||||||
|
in = in[:l+len(extra)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy extra into slice.
|
||||||
|
_ = copy(in[l:], extra)
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
// Deduplicate deduplicates entries in the given slice.
|
// Deduplicate deduplicates entries in the given slice.
|
||||||
func Deduplicate[T comparable](in []T) []T {
|
func Deduplicate[T comparable](in []T) []T {
|
||||||
var (
|
var (
|
|
@ -15,22 +15,90 @@
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package util_test
|
package xslices_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func TestGrowJust(t *testing.T) {
|
||||||
testURLSlice = []*url.URL{}
|
for _, l := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
)
|
for _, x := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
|
s := make([]int, l, l+x)
|
||||||
|
for _, g := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
|
s2 := xslices.GrowJust(s, g)
|
||||||
|
|
||||||
|
// Slice length should not be different.
|
||||||
|
assert.Equal(t, len(s), len(s2))
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// If slice already has capacity for
|
||||||
|
// 'g' then it should not be changed.
|
||||||
|
case cap(s) >= len(s)+g:
|
||||||
|
assert.Equal(t, cap(s), cap(s2))
|
||||||
|
|
||||||
|
// Else, returned slice should only
|
||||||
|
// have capacity for original length
|
||||||
|
// plus extra elements, NOTHING MORE.
|
||||||
|
default:
|
||||||
|
assert.Equal(t, cap(s2), len(s)+g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendJust(t *testing.T) {
|
||||||
|
for _, l := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
|
for _, x := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
|
s := make([]int, l, l+x)
|
||||||
|
|
||||||
|
// Randomize slice.
|
||||||
|
for i := range s {
|
||||||
|
s[i] = rand.Int()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range []int{0, 2, 4, 8, 16, 32, 64} {
|
||||||
|
toAppend := make([]int, a)
|
||||||
|
|
||||||
|
// Randomize appended vals.
|
||||||
|
for i := range toAppend {
|
||||||
|
toAppend[i] = rand.Int()
|
||||||
|
}
|
||||||
|
|
||||||
|
s2 := xslices.AppendJust(s, toAppend...)
|
||||||
|
|
||||||
|
// Slice length should be as expected.
|
||||||
|
assert.Equal(t, len(s)+a, len(s2))
|
||||||
|
|
||||||
|
// Slice contents should be as expected.
|
||||||
|
assert.Equal(t, append(s, toAppend...), s2)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
// If slice already has capacity for
|
||||||
|
// 'toAppend' then it should not change.
|
||||||
|
case cap(s) >= len(s)+a:
|
||||||
|
assert.Equal(t, cap(s), cap(s2))
|
||||||
|
|
||||||
|
// Else, returned slice should only
|
||||||
|
// have capacity for original length
|
||||||
|
// plus extra elements, NOTHING MORE.
|
||||||
|
default:
|
||||||
|
assert.Equal(t, len(s)+a, cap(s2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGather(t *testing.T) {
|
func TestGather(t *testing.T) {
|
||||||
out := util.Gather(nil, []*url.URL{
|
out := xslices.Gather(nil, []*url.URL{
|
||||||
{Scheme: "https", Host: "google.com", Path: "/some-search"},
|
{Scheme: "https", Host: "google.com", Path: "/some-search"},
|
||||||
{Scheme: "http", Host: "example.com", Path: "/robots.txt"},
|
{Scheme: "http", Host: "example.com", Path: "/robots.txt"},
|
||||||
}, (*url.URL).String)
|
}, (*url.URL).String)
|
||||||
|
@ -41,7 +109,7 @@ func TestGather(t *testing.T) {
|
||||||
t.Fatal("unexpected gather output")
|
t.Fatal("unexpected gather output")
|
||||||
}
|
}
|
||||||
|
|
||||||
out = util.Gather([]string{
|
out = xslices.Gather([]string{
|
||||||
"starting input string",
|
"starting input string",
|
||||||
"another starting input",
|
"another starting input",
|
||||||
}, []*url.URL{
|
}, []*url.URL{
|
||||||
|
@ -59,7 +127,7 @@ func TestGather(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGatherIf(t *testing.T) {
|
func TestGatherIf(t *testing.T) {
|
||||||
out := util.GatherIf(nil, []string{
|
out := xslices.GatherIf(nil, []string{
|
||||||
"hello world",
|
"hello world",
|
||||||
"not hello world",
|
"not hello world",
|
||||||
"hello world",
|
"hello world",
|
||||||
|
@ -73,7 +141,7 @@ func TestGatherIf(t *testing.T) {
|
||||||
t.Fatal("unexpected gatherif output")
|
t.Fatal("unexpected gatherif output")
|
||||||
}
|
}
|
||||||
|
|
||||||
out = util.GatherIf([]string{
|
out = xslices.GatherIf([]string{
|
||||||
"starting input string",
|
"starting input string",
|
||||||
"another starting input",
|
"another starting input",
|
||||||
}, []string{
|
}, []string{
|
Loading…
Reference in a new issue