generated from snivilised/astrolib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(kernel): define guardian decoration order (#73)
- Loading branch information
1 parent
75e93d4
commit f085eb1
Showing
24 changed files
with
520 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,6 +92,7 @@ | |
"watchv", | ||
"watchvc", | ||
"watchvi", | ||
"Wrapf" | ||
"Wrapf", | ||
"xcol" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,10 @@ tasks: | |
cmds: | ||
- go test ./i18n | ||
|
||
toc: | ||
cmds: | ||
- go test ./collections | ||
|
||
tp: | ||
cmds: | ||
- go test ./pref | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package collections_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" //nolint:revive // ok | ||
. "github.com/onsi/gomega" //nolint:revive // ok | ||
) | ||
|
||
func TestCollections(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Collections Suite") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package collections | ||
|
||
import ( | ||
"github.com/snivilised/traverse/internal/lo" | ||
"golang.org/x/exp/constraints" | ||
) | ||
|
||
type Orderable interface { | ||
constraints.Integer | string | ||
} | ||
|
||
type PositionalSet[T Orderable] struct { | ||
order []T // Defines the valid elements and their order | ||
items map[T]bool // Tracks which items are in the set | ||
positions map[T]int // Maps each item to its position in the order | ||
anchor T | ||
} | ||
|
||
func NewPositionalSet[T Orderable](order []T, anchor T) *PositionalSet[T] { | ||
o := lo.Reject(lo.Uniq(order), func( | ||
item T, _ int, | ||
) bool { | ||
return item == anchor | ||
}) | ||
o = append(o, anchor) | ||
|
||
ps := &PositionalSet[T]{ | ||
order: o, | ||
items: make(map[T]bool), | ||
positions: make(map[T]int), | ||
anchor: anchor, | ||
} | ||
|
||
for i, item := range o { | ||
ps.positions[item] = i | ||
} | ||
ps.items[anchor] = true | ||
|
||
return ps | ||
} | ||
|
||
// Insert adds an item to the set if it's in the order and is not present | ||
func (ps *PositionalSet[T]) Insert(item T) bool { | ||
if item == ps.anchor { | ||
return false | ||
} | ||
|
||
if _, exists := ps.positions[item]; exists { | ||
if _, found := ps.items[item]; found { | ||
return false | ||
} | ||
ps.items[item] = true | ||
return true | ||
} | ||
|
||
return false | ||
} | ||
|
||
// Add insert multiple items into the set under the same conditions as | ||
// Insert | ||
func (ps *PositionalSet[T]) All(items ...T) bool { | ||
result := true | ||
|
||
for _, item := range items { | ||
inserted := ps.Insert(item) | ||
|
||
if result { | ||
result = inserted | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
// Delete removes an item from the set | ||
func (ps *PositionalSet[T]) Delete(item T) { | ||
if item == ps.anchor { | ||
return | ||
} | ||
|
||
ps.items[item] = false | ||
delete(ps.items, item) | ||
} | ||
|
||
// Contains checks if an item is in the set | ||
func (ps *PositionalSet[T]) Contains(item T) bool { | ||
return ps.items[item] | ||
} | ||
|
||
// Items returns all items in the set, in the defined order | ||
func (ps *PositionalSet[T]) Items() []T { | ||
result := make([]T, 0, len(ps.items)) | ||
for _, item := range ps.order { | ||
if ps.items[item] { | ||
result = append(result, item) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
// Position returns the position of an item in the order | ||
func (ps *PositionalSet[T]) Position(item T) (int, bool) { | ||
pos, exists := ps.positions[item] | ||
return pos, exists | ||
} | ||
|
||
// Count returns the elements in the set | ||
func (ps *PositionalSet[T]) Count() int { | ||
return len(ps.items) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package collections_test | ||
|
||
import ( | ||
"fmt" | ||
|
||
. "github.com/onsi/ginkgo/v2" //nolint:revive // ok | ||
. "github.com/onsi/gomega" //nolint:revive // ok | ||
|
||
"github.com/snivilised/traverse/collections" | ||
"github.com/snivilised/traverse/internal/helpers" | ||
) | ||
|
||
var ( | ||
rainbow = []string{"richard", "of", "york", "gave", "battle", "in", "vain"} | ||
scrambled = []string{"york", "vain", "battle", "of", "richard", "gave", "in"} | ||
) | ||
|
||
func assertColoursAreInOrder(set *collections.PositionalSet[string]) { | ||
anchor, _ := set.Position("ANCHOR") | ||
|
||
for _, colour := range rainbow { | ||
pos, _ := set.Position(colour) | ||
Expect(pos < anchor).To(BeTrue(), helpers.Reason( | ||
fmt.Sprintf("position(%v) of colour: %v should be less than anchor's(%v)", | ||
pos, colour, anchor), | ||
)) | ||
} | ||
} | ||
|
||
var _ = Describe("PositionalSet", func() { | ||
type ( | ||
orderingStringTE struct { | ||
given string | ||
should string | ||
roles []string | ||
} | ||
) | ||
|
||
var ( | ||
set *collections.PositionalSet[string] | ||
) | ||
|
||
BeforeEach(func() { | ||
set = collections.NewPositionalSet(rainbow, "ANCHOR") | ||
}) | ||
|
||
Context("Count", func() { | ||
When("no items added", func() { | ||
It("🧪 should: contain just the anchor", func() { | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present")) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("Insert", func() { | ||
When("requested item is the anchor", func() { | ||
It("🧪 should: not insert", func() { | ||
Expect(set.Insert("ANCHOR")).To(BeFalse(), helpers.Reason("inserting anchor is invalid")) | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present")) | ||
}) | ||
}) | ||
|
||
When("valid item requested", func() { | ||
It("🧪 should: insert", func() { | ||
Expect(set.Insert("richard")).To(BeTrue(), helpers.Reason("richard is in order list")) | ||
Expect(set.Count()).To(Equal(2), helpers.Reason("richard, anchor")) | ||
}) | ||
}) | ||
|
||
When("valid item already present", func() { | ||
It("🧪 should: not insert", func() { | ||
set.Insert("richard") | ||
Expect(set.Insert("richard")).To(BeFalse(), helpers.Reason("richard already in order list")) | ||
Expect(set.Count()).To(Equal(2), helpers.Reason("richard, anchor")) | ||
}) | ||
}) | ||
|
||
When("invalid item requested", func() { | ||
It("🧪 should: not insert", func() { | ||
Expect(set.Insert("gold")).To(BeFalse(), helpers.Reason("gold not in order list")) | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present")) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("All", func() { | ||
When("All valid items requested", func() { | ||
It("🧪 should: insert all", func() { | ||
Expect(set.All( | ||
"richard", "of", "york", "gave", "battle", "in", "vain", | ||
)).To(BeTrue(), helpers.Reason("all items are valid")) | ||
Expect(set.Count()).To(Equal(8), helpers.Reason("should contain all items")) | ||
}) | ||
}) | ||
|
||
When("Not all are valid", func() { | ||
It("🧪 should: insert only valid", func() { | ||
Expect(set.All( | ||
"richard", "gold", "of", "silver", "york", "bronze", | ||
)).To(BeFalse(), helpers.Reason("all items are valid")) | ||
Expect(set.Count()).To(Equal(4), helpers.Reason("should contain valid items")) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("Delete", func() { | ||
When("requested item is the anchor", func() { | ||
It("🧪 should: not delete", func() { | ||
set.Delete("ANCHOR") | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("anchor should still be present")) | ||
}) | ||
}) | ||
|
||
When("requested valid item is present", func() { | ||
It("🧪 should: delete", func() { | ||
set.Insert("york") | ||
set.Delete("york") | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("york should deleted")) | ||
}) | ||
}) | ||
|
||
When("requested valid item is not present", func() { | ||
It("🧪 should: not delete", func() { | ||
set.Delete("york") | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present")) | ||
}) | ||
}) | ||
|
||
When("requested valid item is not valid", func() { | ||
It("🧪 should: not delete", func() { | ||
set.Delete("silver") | ||
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present")) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("Position", func() { | ||
When("multiple items inserted in order", func() { | ||
It("🧪 should: return position less than anchor", func() { | ||
set.All(rainbow...) | ||
assertColoursAreInOrder(set) | ||
}) | ||
}) | ||
|
||
When("multiple items inserted out of order", func() { | ||
It("🧪 should: return position less than anchor", func() { | ||
set.All(scrambled...) | ||
assertColoursAreInOrder(set) | ||
}) | ||
|
||
It("🧪 should: contain correct positions when colours compared", func() { | ||
set.All(scrambled...) | ||
richard, _ := set.Position("richard") | ||
of, _ := set.Position("of") | ||
york, _ := set.Position("york") | ||
Expect(richard < of).To(BeTrue()) | ||
Expect(richard < york).To(BeTrue()) | ||
}) | ||
}) | ||
}) | ||
|
||
Context("Items", func() { | ||
When("multiple items inserted in order", func() { | ||
It("🧪 should: return items defined by order", func() { | ||
set.All(rainbow...) | ||
expected := append(append([]string{}, rainbow...), "ANCHOR") | ||
Expect(set.Items()).To(HaveExactElements(expected)) | ||
}) | ||
}) | ||
|
||
When("multiple items inserted out of order", func() { | ||
It("🧪 should: return items defined by order", func() { | ||
set.All(scrambled...) | ||
expected := append(append([]string{}, rainbow...), "ANCHOR") | ||
Expect(set.Items()).To(HaveExactElements(expected)) | ||
}) | ||
}) | ||
|
||
When("partial items inserted in order", func() { | ||
It("🧪 should: return items defined by order", func() { | ||
set.All("vain", "battle", "york") | ||
expected := []string{"york", "battle", "vain", "ANCHOR"} | ||
Expect(set.Items()).To(HaveExactElements(expected)) | ||
|
||
set.Delete("battle") | ||
set.Insert("of") | ||
|
||
expected = []string{"of", "york", "vain", "ANCHOR"} | ||
Expect(set.Items()).To(HaveExactElements(expected)) | ||
}) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.