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(cycle): define notifications for life cycle events (#14)
- Loading branch information
1 parent
294e742
commit 8800a1e
Showing
13 changed files
with
386 additions
and
16 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 |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
"--fast" | ||
], | ||
"cSpell.words": [ | ||
"alloc", | ||
"astrolib", | ||
"bodyclose", | ||
"cmds", | ||
|
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
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 |
---|---|---|
@@ -1,9 +1,39 @@ | ||
package cycle | ||
|
||
// cycle represents life cycle events | ||
import ( | ||
"github.com/snivilised/traverse/core" | ||
"github.com/snivilised/traverse/event" | ||
) | ||
|
||
// cycle represents life cycle events; can't use prefs | ||
|
||
// beforeX | ||
// afterX | ||
|
||
// eg beforeOptions | ||
// afterOptions | ||
|
||
type ( | ||
Event[F any] interface { | ||
// On subscribes to a life cycle event | ||
On(handler F) | ||
} | ||
|
||
// SimpleHandler is a function that takes no parameters and can | ||
// be used by any notification with this signature. | ||
SimpleHandler func() | ||
|
||
// BeginHandler invoked before traversal begins | ||
BeginHandler func(root string) | ||
|
||
// EndHandler invoked at the end of traversal | ||
EndHandler func(result core.TraverseResult) | ||
|
||
// HibernateHandler is a generic handler that is used by hibernation | ||
// to indicate wake or sleep. | ||
HibernateHandler func(description string) | ||
|
||
// NodeHandler is a generic handler that is for any notification that contains | ||
// the traversal node, such as directory ascend or descend. | ||
NodeHandler func(node *event.Node) | ||
) |
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 cycle_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" //nolint:revive // ok | ||
. "github.com/onsi/gomega" //nolint:revive // ok | ||
) | ||
|
||
func TestCycle(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Cycle 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,156 @@ | ||
package cycle | ||
|
||
import ( | ||
"github.com/snivilised/traverse/core" | ||
"github.com/snivilised/traverse/event" | ||
) | ||
|
||
type ( | ||
broadcasterFunc[F any] func(listeners []F) F | ||
|
||
Dispatch[F any] struct { | ||
Invoke F | ||
broadcaster broadcasterFunc[F] | ||
} | ||
|
||
// NotificationCtrl contains the handler function to be invoked. The control | ||
// is agnostic to the handler's signature and therefore can not invoke it. | ||
NotificationCtrl[F any] struct { | ||
Dispatch Dispatch[F] | ||
subscribed bool | ||
listeners []F | ||
} | ||
|
||
Events struct { // --> options | ||
Ascend Event[NodeHandler] | ||
Begin Event[BeginHandler] | ||
Descend Event[NodeHandler] | ||
End Event[EndHandler] | ||
Start Event[HibernateHandler] | ||
Stop Event[HibernateHandler] | ||
} | ||
|
||
Controls struct { // --> registry | ||
Ascend NotificationCtrl[NodeHandler] | ||
Begin NotificationCtrl[BeginHandler] | ||
Descend NotificationCtrl[NodeHandler] | ||
End NotificationCtrl[EndHandler] | ||
Start NotificationCtrl[HibernateHandler] | ||
Stop NotificationCtrl[HibernateHandler] | ||
} | ||
) | ||
|
||
var ( | ||
AscendDispatcher Dispatch[NodeHandler] | ||
BeginDispatcher Dispatch[BeginHandler] | ||
DescendDispatcher Dispatch[NodeHandler] | ||
EndDispatcher Dispatch[EndHandler] | ||
StartDispatcher Dispatch[HibernateHandler] | ||
StopDispatcher Dispatch[HibernateHandler] | ||
) | ||
|
||
func init() { | ||
AscendDispatcher = Dispatch[NodeHandler]{ | ||
Invoke: func(_ *event.Node) {}, | ||
broadcaster: BroadcastNode, | ||
} | ||
|
||
BeginDispatcher = Dispatch[BeginHandler]{ | ||
Invoke: func(_ string) {}, | ||
broadcaster: BroadcastBegin, | ||
} | ||
|
||
DescendDispatcher = Dispatch[NodeHandler]{ | ||
Invoke: func(_ *event.Node) {}, | ||
broadcaster: BroadcastNode, | ||
} | ||
|
||
EndDispatcher = Dispatch[EndHandler]{ | ||
Invoke: func(_ core.TraverseResult) {}, | ||
broadcaster: BroadcastEnd, | ||
} | ||
|
||
StartDispatcher = Dispatch[HibernateHandler]{ | ||
Invoke: func(_ string) {}, | ||
broadcaster: BroadcastHibernate, | ||
} | ||
|
||
StopDispatcher = Dispatch[HibernateHandler]{ | ||
Invoke: func(_ string) {}, | ||
broadcaster: BroadcastHibernate, | ||
} | ||
} | ||
|
||
// Bind attaches the underlying notification controllers to the | ||
// Events. | ||
func (e *Events) Bind(cs *Controls) { | ||
e.Ascend = &cs.Ascend | ||
e.Begin = &cs.Begin | ||
e.Descend = &cs.Descend | ||
e.End = &cs.End | ||
e.Start = &cs.Start | ||
e.Stop = &cs.Stop | ||
} | ||
|
||
// On subscribes to a life cycle event | ||
func (c *NotificationCtrl[F]) On(handler F) { | ||
if !c.subscribed { | ||
c.Dispatch.Invoke = handler | ||
c.subscribed = true | ||
|
||
return | ||
} | ||
|
||
if c.listeners == nil { | ||
const alloc = 2 | ||
c.listeners = make([]F, 0, alloc) | ||
c.listeners = append(c.listeners, c.Dispatch.Invoke) | ||
} | ||
|
||
c.listeners = append(c.listeners, handler) | ||
c.Dispatch.Invoke = c.broadcaster(c.listeners) | ||
} | ||
|
||
func (c *NotificationCtrl[F]) broadcaster(listeners []F) F { | ||
return c.Dispatch.broadcaster(listeners) | ||
} | ||
|
||
func BroadcastBegin(listeners []BeginHandler) BeginHandler { | ||
return func(root string) { | ||
for _, listener := range listeners { | ||
listener(root) | ||
} | ||
} | ||
} | ||
|
||
func BroadcastEnd(listeners []EndHandler) EndHandler { | ||
return func(result core.TraverseResult) { | ||
for _, listener := range listeners { | ||
listener(result) | ||
} | ||
} | ||
} | ||
|
||
func BroadcastNode(listeners []NodeHandler) NodeHandler { | ||
return func(node *event.Node) { | ||
for _, listener := range listeners { | ||
listener(node) | ||
} | ||
} | ||
} | ||
|
||
func BroadcastHibernate(listeners []HibernateHandler) HibernateHandler { | ||
return func(description string) { | ||
for _, listener := range listeners { | ||
listener(description) | ||
} | ||
} | ||
} | ||
|
||
func BroadcastSimple(listeners []SimpleHandler) SimpleHandler { | ||
return func() { | ||
for _, listener := range listeners { | ||
listener() | ||
} | ||
} | ||
} |
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,47 @@ | ||
package cycle_test | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo/v2" //nolint:revive // ok | ||
. "github.com/onsi/gomega" //nolint:revive // ok | ||
|
||
"github.com/snivilised/traverse/core" | ||
"github.com/snivilised/traverse/cycle" | ||
) | ||
|
||
var _ = Describe("Notify", func() { | ||
Context("foo", func() { | ||
It("should:", func() { | ||
const path = "/traversal-root" | ||
|
||
var ( | ||
notifications cycle.Controls | ||
taps cycle.Events | ||
begun bool | ||
ended bool | ||
) | ||
|
||
// init(registry->options): | ||
// | ||
taps.Bind(¬ifications) | ||
|
||
// client: | ||
// | ||
taps.Begin.On(func(root string) { | ||
begun = true | ||
Expect(root).To(Equal(path)) | ||
}) | ||
|
||
taps.End.On(func(_ core.TraverseResult) { | ||
ended = true | ||
}) | ||
|
||
// component side: | ||
// | ||
notifications.Begin.Dispatch.Invoke(path) | ||
notifications.End.Dispatch.Invoke(nil) | ||
|
||
Expect(begun).To(BeTrue()) | ||
Expect(ended).To(BeTrue()) | ||
}) | ||
}) | ||
}) |
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
Oops, something went wrong.