swap selector category types for ints (#661)

Though enumerated as ints, the selector service
categories are stored and managed as strings. The
only time that we use the int is when passing their
iota const to and from functions.  Using a string
type instead of an int allows us to get rid of the
string builders and AtoI funcs (though not the
stringer requirement in the Iface, sadly).
This commit is contained in:
Keepers 2022-08-29 13:46:08 -06:00 committed by GitHub
parent 81cb76dd55
commit 56c7e0f85f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 152 deletions

View File

@ -292,7 +292,7 @@ func (s *exchange) Users(users []string) []ExchangeScope {
// If the input is empty or selectors.None, the scope will always fail comparisons. // If the input is empty or selectors.None, the scope will always fail comparisons.
func (sr *ExchangeRestore) MailReceivedAfter(timeStrings string) []ExchangeScope { func (sr *ExchangeRestore) MailReceivedAfter(timeStrings string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope](ExchangeMail, ExchangeInfoMailReceivedAfter, []string{timeStrings}), makeFilterScope[ExchangeScope](ExchangeMail, ExchangeFilterMailReceivedAfter, []string{timeStrings}),
} }
} }
@ -302,7 +302,7 @@ func (sr *ExchangeRestore) MailReceivedAfter(timeStrings string) []ExchangeScope
// If the input is empty or selectors.None, the scope will always fail comparisons. // If the input is empty or selectors.None, the scope will always fail comparisons.
func (sr *ExchangeRestore) MailReceivedBefore(timeStrings string) []ExchangeScope { func (sr *ExchangeRestore) MailReceivedBefore(timeStrings string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope](ExchangeMail, ExchangeInfoMailReceivedBefore, []string{timeStrings}), makeFilterScope[ExchangeScope](ExchangeMail, ExchangeFilterMailReceivedBefore, []string{timeStrings}),
} }
} }
@ -313,7 +313,7 @@ func (sr *ExchangeRestore) MailReceivedBefore(timeStrings string) []ExchangeScop
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope { func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope](ExchangeMail, ExchangeInfoMailSender, senderIDs), makeFilterScope[ExchangeScope](ExchangeMail, ExchangeFilterMailSender, senderIDs),
} }
} }
@ -324,7 +324,7 @@ func (sr *ExchangeRestore) MailSender(senderIDs []string) []ExchangeScope {
// If any slice is empty, it defaults to [selectors.None] // If any slice is empty, it defaults to [selectors.None]
func (sr *ExchangeRestore) MailSubject(subjectSubstrings []string) []ExchangeScope { func (sr *ExchangeRestore) MailSubject(subjectSubstrings []string) []ExchangeScope {
return []ExchangeScope{ return []ExchangeScope{
makeFilterScope[ExchangeScope](ExchangeMail, ExchangeInfoMailSubject, subjectSubstrings), makeFilterScope[ExchangeScope](ExchangeMail, ExchangeFilterMailSubject, subjectSubstrings),
} }
} }
@ -372,57 +372,27 @@ func (d ExchangeDestination) Set(cat exchangeCategory, dest string) error {
// exchangeCategory enumerates the type of the lowest level // exchangeCategory enumerates the type of the lowest level
// of data specified by the scope. // of data specified by the scope.
type exchangeCategory int type exchangeCategory string
// interface compliance checks // interface compliance checks
var _ categorizer = ExchangeCategoryUnknown var _ categorizer = ExchangeCategoryUnknown
//go:generate stringer -type=exchangeCategory
const ( const (
ExchangeCategoryUnknown exchangeCategory = iota ExchangeCategoryUnknown exchangeCategory = ""
// types of data identified by exchange // types of data identified by exchange
ExchangeContact ExchangeContact exchangeCategory = "ExchangeContact"
ExchangeContactFolder ExchangeContactFolder exchangeCategory = "ExchangeContactFolder"
ExchangeEvent ExchangeEvent exchangeCategory = "ExchangeEvent"
ExchangeMail ExchangeMail exchangeCategory = "ExchangeMail"
ExchangeMailFolder ExchangeMailFolder exchangeCategory = "ExchangeFolder"
ExchangeUser ExchangeUser exchangeCategory = "ExchangeUser"
// filterable topics identified by exchange // filterable topics identified by exchange
ExchangeInfoMailSender exchangeCategory = iota + 100 // offset to pad out future data additions ExchangeFilterMailSender exchangeCategory = "ExchangeFilterMailSender"
ExchangeInfoMailSubject ExchangeFilterMailSubject exchangeCategory = "ExchangeFilterMailSubject"
ExchangeInfoMailReceivedAfter ExchangeFilterMailReceivedAfter exchangeCategory = "ExchangeFilterMailReceivedAfter"
ExchangeInfoMailReceivedBefore ExchangeFilterMailReceivedBefore exchangeCategory = "ExchangeFilterMailReceivedBefore"
) )
func exchangeCatAtoI(s string) exchangeCategory {
switch s {
// data types
case ExchangeContact.String():
return ExchangeContact
case ExchangeContactFolder.String():
return ExchangeContactFolder
case ExchangeEvent.String():
return ExchangeEvent
case ExchangeMail.String():
return ExchangeMail
case ExchangeMailFolder.String():
return ExchangeMailFolder
case ExchangeUser.String():
return ExchangeUser
// filters
case ExchangeInfoMailSender.String():
return ExchangeInfoMailSender
case ExchangeInfoMailSubject.String():
return ExchangeInfoMailSubject
case ExchangeInfoMailReceivedAfter.String():
return ExchangeInfoMailReceivedAfter
case ExchangeInfoMailReceivedBefore.String():
return ExchangeInfoMailReceivedBefore
default:
return ExchangeCategoryUnknown
}
}
// exchangePathSet describes the category type keys used in Exchange paths. // exchangePathSet describes the category type keys used in Exchange paths.
// The order of each slice is important, and should match the order in which // The order of each slice is important, and should match the order in which
// these types appear in the canonical Path for each type. // these types appear in the canonical Path for each type.
@ -433,6 +403,10 @@ var exchangePathSet = map[categorizer][]categorizer{
ExchangeUser: {ExchangeUser}, // the root category must be represented ExchangeUser: {ExchangeUser}, // the root category must be represented
} }
func (ec exchangeCategory) String() string {
return string(ec)
}
// leafCat returns the leaf category of the receiver. // leafCat returns the leaf category of the receiver.
// If the receiver category has multiple leaves (ex: User) or no leaves, // If the receiver category has multiple leaves (ex: User) or no leaves,
// (ex: Unknown), the receiver itself is returned. // (ex: Unknown), the receiver itself is returned.
@ -530,7 +504,7 @@ var _ scoper = &ExchangeScope{}
// Category describes the type of the data in scope. // Category describes the type of the data in scope.
func (s ExchangeScope) Category() exchangeCategory { func (s ExchangeScope) Category() exchangeCategory {
return exchangeCatAtoI(s[scopeKeyCategory]) return exchangeCategory(s[scopeKeyCategory])
} }
// categorizer type is a generic wrapper around Category. // categorizer type is a generic wrapper around Category.
@ -548,7 +522,7 @@ func (s ExchangeScope) Contains(cat exchangeCategory, target string) bool {
// FilterCategory returns the category enum of the scope filter. // FilterCategory returns the category enum of the scope filter.
// If the scope is not a filter type, returns ExchangeUnknownCategory. // If the scope is not a filter type, returns ExchangeUnknownCategory.
func (s ExchangeScope) FilterCategory() exchangeCategory { func (s ExchangeScope) FilterCategory() exchangeCategory {
return exchangeCatAtoI(s[scopeKeyInfoFilter]) return exchangeCategory(s[scopeKeyInfoFilter])
} }
// Granularity describes the granularity (directory || item) // Granularity describes the granularity (directory || item)
@ -627,7 +601,7 @@ func (s ExchangeScope) matchesEntry(
return matchesPathValues(s, cat.(exchangeCategory), pathValues) || s.matchesInfo(entry.Exchange) return matchesPathValues(s, cat.(exchangeCategory), pathValues) || s.matchesInfo(entry.Exchange)
} }
// matchesInfo handles the standard behavior when comparing a scope and an exchangeInfo // matchesInfo handles the standard behavior when comparing a scope and an ExchangeFilter
// returns true if the scope and info match for the provided category. // returns true if the scope and info match for the provided category.
func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool { func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
// we need values to match against // we need values to match against
@ -654,19 +628,19 @@ func (s ExchangeScope) matchesInfo(info *details.ExchangeInfo) bool {
// any of the targets for a given info filter may succeed. // any of the targets for a given info filter may succeed.
for _, target := range targets { for _, target := range targets {
switch filterCat { switch filterCat {
case ExchangeInfoMailSender: case ExchangeFilterMailSender:
if target == info.Sender { if target == info.Sender {
return true return true
} }
case ExchangeInfoMailSubject: case ExchangeFilterMailSubject:
if strings.Contains(info.Subject, target) { if strings.Contains(info.Subject, target) {
return true return true
} }
case ExchangeInfoMailReceivedAfter: case ExchangeFilterMailReceivedAfter:
if target < common.FormatTime(info.Received) { if target < common.FormatTime(info.Received) {
return true return true
} }
case ExchangeInfoMailReceivedBefore: case ExchangeFilterMailReceivedBefore:
if target > common.FormatTime(info.Received) { if target > common.FormatTime(info.Received) {
return true return true
} }

View File

@ -1034,7 +1034,7 @@ func (suite *ExchangeSelectorSuite) TestExchangeCategory_leafCat() {
cat exchangeCategory cat exchangeCategory
expect exchangeCategory expect exchangeCategory
}{ }{
{exchangeCategory(-1), exchangeCategory(-1)}, {exchangeCategory("foo"), exchangeCategory("foo")},
{ExchangeCategoryUnknown, ExchangeCategoryUnknown}, {ExchangeCategoryUnknown, ExchangeCategoryUnknown},
{ExchangeUser, ExchangeUser}, {ExchangeUser, ExchangeUser},
{ExchangeMailFolder, ExchangeMail}, {ExchangeMailFolder, ExchangeMail},

View File

@ -1,44 +0,0 @@
// Code generated by "stringer -type=exchangeCategory"; DO NOT EDIT.
package selectors
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[ExchangeCategoryUnknown-0]
_ = x[ExchangeContact-1]
_ = x[ExchangeContactFolder-2]
_ = x[ExchangeEvent-3]
_ = x[ExchangeMail-4]
_ = x[ExchangeMailFolder-5]
_ = x[ExchangeUser-6]
_ = x[ExchangeInfoMailSender-107]
_ = x[ExchangeInfoMailSubject-108]
_ = x[ExchangeInfoMailReceivedAfter-109]
_ = x[ExchangeInfoMailReceivedBefore-110]
}
const (
_exchangeCategory_name_0 = "ExchangeCategoryUnknownExchangeContactExchangeContactFolderExchangeEventExchangeMailExchangeMailFolderExchangeUser"
_exchangeCategory_name_1 = "ExchangeInfoMailSenderExchangeInfoMailSubjectExchangeInfoMailReceivedAfterExchangeInfoMailReceivedBefore"
)
var (
_exchangeCategory_index_0 = [...]uint8{0, 23, 38, 59, 72, 84, 102, 114}
_exchangeCategory_index_1 = [...]uint8{0, 22, 45, 74, 104}
)
func (i exchangeCategory) String() string {
switch {
case 0 <= i && i <= 6:
return _exchangeCategory_name_0[_exchangeCategory_index_0[i]:_exchangeCategory_index_0[i+1]]
case 107 <= i && i <= 110:
i -= 107
return _exchangeCategory_name_1[_exchangeCategory_index_1[i]:_exchangeCategory_index_1[i+1]]
default:
return "exchangeCategory(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@ -7,25 +7,18 @@ import "github.com/alcionai/corso/pkg/backup/details"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// categorizer // categorizer
type mockCategorizer int type mockCategorizer string
const ( const (
unknownCatStub mockCategorizer = iota unknownCatStub mockCategorizer = ""
rootCatStub rootCatStub mockCategorizer = "rootCatStub"
leafCatStub leafCatStub mockCategorizer = "leafCatStub"
) )
var _ categorizer = unknownCatStub var _ categorizer = unknownCatStub
func (mc mockCategorizer) String() string { func (mc mockCategorizer) String() string {
switch mc { return string(mc)
case leafCatStub:
return "leaf"
case rootCatStub:
return "root"
}
return "unknown"
} }
func (mc mockCategorizer) leafCat() categorizer { func (mc mockCategorizer) leafCat() categorizer {

View File

@ -139,29 +139,17 @@ func (s *oneDrive) DiscreteScopes(userPNs []string) []OneDriveScope {
// oneDriveCategory enumerates the type of the lowest level // oneDriveCategory enumerates the type of the lowest level
// of data () in a scope. // of data () in a scope.
type oneDriveCategory int type oneDriveCategory string
// interface compliance checks // interface compliance checks
var _ categorizer = OneDriveCategoryUnknown var _ categorizer = OneDriveCategoryUnknown
//go:generate go run golang.org/x/tools/cmd/stringer -type=oneDriveCategory
const ( const (
OneDriveCategoryUnknown oneDriveCategory = iota OneDriveCategoryUnknown oneDriveCategory = ""
// types of data identified by OneDrive // types of data identified by OneDrive
OneDriveUser OneDriveUser oneDriveCategory = "OneDriveUser"
) )
func oneDriveCatAtoI(s string) oneDriveCategory {
switch s {
// data types
case OneDriveUser.String():
return OneDriveUser
// filters
default:
return OneDriveCategoryUnknown
}
}
// oneDrivePathSet describes the category type keys used in OneDrive paths. // oneDrivePathSet describes the category type keys used in OneDrive paths.
// The order of each slice is important, and should match the order in which // The order of each slice is important, and should match the order in which
// these types appear in the canonical Path for each type. // these types appear in the canonical Path for each type.
@ -169,6 +157,10 @@ var oneDrivePathSet = map[categorizer][]categorizer{
OneDriveUser: {OneDriveUser}, // the root category must be represented OneDriveUser: {OneDriveUser}, // the root category must be represented
} }
func (c oneDriveCategory) String() string {
return string(c)
}
// leafCat returns the leaf category of the receiver. // leafCat returns the leaf category of the receiver.
// If the receiver category has multiple leaves (ex: User) or no leaves, // If the receiver category has multiple leaves (ex: User) or no leaves,
// (ex: Unknown), the receiver itself is returned. // (ex: Unknown), the receiver itself is returned.
@ -234,7 +226,7 @@ var _ scoper = &OneDriveScope{}
// Category describes the type of the data in scope. // Category describes the type of the data in scope.
func (s OneDriveScope) Category() oneDriveCategory { func (s OneDriveScope) Category() oneDriveCategory {
return oneDriveCatAtoI(s[scopeKeyCategory]) return oneDriveCategory(s[scopeKeyCategory])
} }
// categorizer type is a generic wrapper around Category. // categorizer type is a generic wrapper around Category.
@ -246,7 +238,7 @@ func (s OneDriveScope) categorizer() categorizer {
// FilterCategory returns the category enum of the scope filter. // FilterCategory returns the category enum of the scope filter.
// If the scope is not a filter type, returns OneDriveUnknownCategory. // If the scope is not a filter type, returns OneDriveUnknownCategory.
func (s OneDriveScope) FilterCategory() oneDriveCategory { func (s OneDriveScope) FilterCategory() oneDriveCategory {
return oneDriveCatAtoI(s[scopeKeyInfoFilter]) return oneDriveCategory(s[scopeKeyInfoFilter])
} }
// Granularity describes the granularity (directory || item) // Granularity describes the granularity (directory || item)

View File

@ -1,24 +0,0 @@
// Code generated by "stringer -type=oneDriveCategory"; DO NOT EDIT.
package selectors
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[OneDriveCategoryUnknown-0]
_ = x[OneDriveUser-1]
}
const _oneDriveCategory_name = "OneDriveCategoryUnknownOneDriveUser"
var _oneDriveCategory_index = [...]uint8{0, 23, 35}
func (i oneDriveCategory) String() string {
if i < 0 || i >= oneDriveCategory(len(_oneDriveCategory_index)-1) {
return "oneDriveCategory(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _oneDriveCategory_name[_oneDriveCategory_index[i]:_oneDriveCategory_index[i+1]]
}

View File

@ -51,7 +51,7 @@ type (
} }
// categoryT is the generic type interface of a categorizer // categoryT is the generic type interface of a categorizer
categoryT interface { categoryT interface {
~int ~string
categorizer categorizer
} }
) )