Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rx): rename generic parameter (#129) #130

Merged
merged 1 commit into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 46 additions & 46 deletions rx/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,100 +9,100 @@ import (
)

// AssertPredicate is a custom predicate based on the items.
type AssertPredicate[I any] func(items []I) error
type AssertPredicate[T any] func(items []T) error

// RxAssert lists the Observable assertions.
type RxAssert[I any] interface { //nolint:revive // foo
apply(*rxAssert[I])
itemsToBeChecked() (bool, []I)
itemsNoOrderedToBeChecked() (bool, []I)
type RxAssert[T any] interface { //nolint:revive // foo
apply(*rxAssert[T])
itemsToBeChecked() (bool, []T)
itemsNoOrderedToBeChecked() (bool, []T)
noItemsToBeChecked() bool
someItemsToBeChecked() bool
raisedErrorToBeChecked() (bool, error)
raisedErrorsToBeChecked() (bool, []error)
raisedAnErrorToBeChecked() (bool, error)
notRaisedErrorToBeChecked() bool
itemToBeChecked() (bool, I)
noItemToBeChecked() (bool, I)
customPredicatesToBeChecked() (bool, []AssertPredicate[I])
itemToBeChecked() (bool, T)
noItemToBeChecked() (bool, T)
customPredicatesToBeChecked() (bool, []AssertPredicate[T])
}

type rxAssert[I any] struct {
f func(*rxAssert[I])
type rxAssert[T any] struct {
f func(*rxAssert[T])
checkHasItems bool
checkHasNoItems bool
checkHasSomeItems bool
items []I
items []T
checkHasItemsNoOrder bool
itemsNoOrder []I
itemsNoOrder []T
checkHasRaisedError bool
err error
checkHasRaisedErrors bool
errs []error
checkHasRaisedAnError bool
checkHasNotRaisedError bool
checkHasItem bool
item I
item T
checkHasNoItem bool
checkHasCustomPredicate bool
customPredicates []AssertPredicate[I]
customPredicates []AssertPredicate[T]
}

func (ass *rxAssert[I]) apply(do *rxAssert[I]) {
func (ass *rxAssert[T]) apply(do *rxAssert[T]) {
ass.f(do)
}

func (ass *rxAssert[I]) itemsToBeChecked() (b bool, i []I) {
func (ass *rxAssert[T]) itemsToBeChecked() (b bool, i []T) {
return ass.checkHasItems, ass.items
}

func (ass *rxAssert[I]) itemsNoOrderedToBeChecked() (b bool, i []I) {
func (ass *rxAssert[T]) itemsNoOrderedToBeChecked() (b bool, i []T) {
return ass.checkHasItemsNoOrder, ass.itemsNoOrder
}

func (ass *rxAssert[I]) noItemsToBeChecked() bool {
func (ass *rxAssert[T]) noItemsToBeChecked() bool {
return ass.checkHasNoItems
}

func (ass *rxAssert[I]) someItemsToBeChecked() bool {
func (ass *rxAssert[T]) someItemsToBeChecked() bool {
return ass.checkHasSomeItems
}
func (ass *rxAssert[I]) raisedErrorToBeChecked() (bool, error) {
func (ass *rxAssert[T]) raisedErrorToBeChecked() (bool, error) {
return ass.checkHasRaisedError, ass.err
}

func (ass *rxAssert[I]) raisedErrorsToBeChecked() (bool, []error) {
func (ass *rxAssert[T]) raisedErrorsToBeChecked() (bool, []error) {
return ass.checkHasRaisedErrors, ass.errs
}

func (ass *rxAssert[I]) raisedAnErrorToBeChecked() (bool, error) {
func (ass *rxAssert[T]) raisedAnErrorToBeChecked() (bool, error) {
return ass.checkHasRaisedAnError, ass.err
}

func (ass *rxAssert[I]) notRaisedErrorToBeChecked() bool {
func (ass *rxAssert[T]) notRaisedErrorToBeChecked() bool {
return ass.checkHasNotRaisedError
}

func (ass *rxAssert[I]) itemToBeChecked() (b bool, i I) {
func (ass *rxAssert[T]) itemToBeChecked() (b bool, i T) {
return ass.checkHasItem, ass.item
}

func (ass *rxAssert[I]) noItemToBeChecked() (b bool, i I) {
func (ass *rxAssert[T]) noItemToBeChecked() (b bool, i T) {
return ass.checkHasNoItem, ass.item
}

func (ass *rxAssert[I]) customPredicatesToBeChecked() (bool, []AssertPredicate[I]) {
func (ass *rxAssert[T]) customPredicatesToBeChecked() (bool, []AssertPredicate[T]) {
return ass.checkHasCustomPredicate, ass.customPredicates
}

func newAssertion[I any](f func(*rxAssert[I])) *rxAssert[I] {
return &rxAssert[I]{
func newAssertion[T any](f func(*rxAssert[T])) *rxAssert[T] {
return &rxAssert[T]{
f: f,
}
}

func parseAssertions[I any](assertions ...RxAssert[I]) RxAssert[I] {
ass := new(rxAssert[I])
func parseAssertions[T any](assertions ...RxAssert[T]) RxAssert[T] {
ass := new(rxAssert[T])

for _, assertion := range assertions {
assertion.apply(ass)
Expand All @@ -111,9 +111,9 @@ func parseAssertions[I any](assertions ...RxAssert[I]) RxAssert[I] {
return ass
}

func Assert[I any](ctx context.Context, iterable Iterable[I], assertions ...RxAssert[I]) {
func Assert[T any](ctx context.Context, iterable Iterable[T], assertions ...RxAssert[T]) {
ass := parseAssertions(assertions...)
got := make([]I, 0)
got := make([]T, 0)
errs := make([]error, 0)
observe := iterable.Observe()

Expand Down Expand Up @@ -211,51 +211,51 @@ loop:
}
}

func HasItems[I any](expectedItems []I) RxAssert[I] {
return newAssertion(func(ra *rxAssert[I]) {
func HasItems[T any](expectedItems []T) RxAssert[T] {
return newAssertion(func(ra *rxAssert[T]) {
ra.checkHasItems = true
ra.items = expectedItems
})
}

// HasItem checks if a single or optional single has a specific item.
func HasItem[I any](i I) RxAssert[I] {
return newAssertion(func(a *rxAssert[I]) {
func HasItem[T any](i T) RxAssert[T] {
return newAssertion(func(a *rxAssert[T]) {
a.checkHasItem = true
a.item = i
})
}

// IsNotEmpty checks that the observable produces some items.
func IsNotEmpty[I any]() RxAssert[I] {
return newAssertion(func(a *rxAssert[I]) {
func IsNotEmpty[T any]() RxAssert[T] {
return newAssertion(func(a *rxAssert[T]) {
a.checkHasSomeItems = true
})
}

// IsEmpty checks that the observable has not produce any item.
func IsEmpty[I any]() RxAssert[I] {
return newAssertion(func(a *rxAssert[I]) {
func IsEmpty[T any]() RxAssert[T] {
return newAssertion(func(a *rxAssert[T]) {
a.checkHasNoItems = true
})
}

func HasError[I any](err error) RxAssert[I] {
return newAssertion(func(a *rxAssert[I]) {
func HasError[T any](err error) RxAssert[T] {
return newAssertion(func(a *rxAssert[T]) {
a.checkHasRaisedError = true
a.err = err
})
}

// HasAnError checks that the observable has produce an error.
func HasAnError[I any]() RxAssert[I] {
return newAssertion(func(a *rxAssert[I]) {
func HasAnError[T any]() RxAssert[T] {
return newAssertion(func(a *rxAssert[T]) {
a.checkHasRaisedAnError = true
})
}

func HasNoError[I any]() RxAssert[I] {
return newAssertion(func(ra *rxAssert[I]) {
func HasNoError[T any]() RxAssert[T] {
return newAssertion(func(ra *rxAssert[T]) {
ra.checkHasNotRaisedError = true
})
}
34 changes: 17 additions & 17 deletions rx/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@ package rx

// Amb takes several Observables, emit all of the items from only the first of these Observables
// to emit an item or notification.
func Amb[I any](observables []Observable[I], opts ...Option[I]) Observable[I] {
func Amb[T any](observables []Observable[T], opts ...Option[T]) Observable[T] {
_, _ = observables, opts

panic("Amb: NOT-IMPL")
}

// Empty creates an Observable with no item and terminate immediately.
func Empty[I any]() Observable[I] {
next := make(chan Item[I])
func Empty[T any]() Observable[T] {
next := make(chan Item[T])
close(next)

return &ObservableImpl[I]{
return &ObservableImpl[T]{
iterable: newChannelIterable(next),
}
}

// FromChannel creates a cold observable from a channel.
func FromChannel[I any](next <-chan Item[I], opts ...Option[I]) Observable[I] {
func FromChannel[T any](next <-chan Item[T], opts ...Option[T]) Observable[T] {
option := parseOptions(opts...)
ctx := option.buildContext(emptyContext)

return &ObservableImpl[I]{
return &ObservableImpl[T]{
parent: ctx,
iterable: newChannelIterable(next, opts...),
}
}

// Just creates an Observable with the provided items.
func Just[I any](values ...I) func(opts ...Option[I]) Observable[I] {
return func(opts ...Option[I]) Observable[I] {
return &ObservableImpl[I]{
func Just[T any](values ...T) func(opts ...Option[T]) Observable[T] {
return func(opts ...Option[T]) Observable[T] {
return &ObservableImpl[T]{
iterable: newJustIterable(values...)(opts...),
}
}
Expand All @@ -41,28 +41,28 @@ func Just[I any](values ...I) func(opts ...Option[I]) Observable[I] {
// JustSingle is like JustItem in that it is defined for a single item iterable
// but behaves like Just in that it returns a func.
// This is probably not required, just defined for experimental purposes for now.
func JustSingle[I any](value I, opts ...Option[I]) func(opts ...Option[I]) Single[I] {
return func(_ ...Option[I]) Single[I] {
return &SingleImpl[I]{
func JustSingle[T any](value T, opts ...Option[T]) func(opts ...Option[T]) Single[T] {
return func(_ ...Option[T]) Single[T] {
return &SingleImpl[T]{
iterable: newJustIterable(value)(opts...),
}
}
}

// JustItem creates a single from one item.
func JustItem[I any](value I, opts ...Option[I]) Single[I] {
func JustItem[T any](value T, opts ...Option[T]) Single[T] {
// Why does this not return a func, but Just does?
//
return &SingleImpl[I]{
return &SingleImpl[T]{
iterable: newJustIterable(value)(opts...),
}
}

// Never creates an Observable that emits no items and does not terminate.
func Never[I any]() Observable[I] {
next := make(chan Item[I])
func Never[T any]() Observable[T] {
next := make(chan Item[T])

return &ObservableImpl[I]{
return &ObservableImpl[T]{
iterable: newChannelIterable(next),
}
}
32 changes: 16 additions & 16 deletions rx/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import (
type (
// Item is a wrapper having either a value or an error.
//
Item[I any] struct {
V I
Item[T any] struct {
V T
E error
}

// TimestampItem attach a timestamp to an item.
//
TimestampItem[I any] struct {
TimestampItem[T any] struct {
Timestamp time.Time
V I
V T
}

// CloseChannelStrategy indicates a strategy on whether to close a channel.
Expand All @@ -32,21 +32,21 @@ const (
)

// Of creates an item from a value.
func Of[I any](v I) Item[I] {
return Item[I]{V: v}
func Of[T any](v T) Item[T] {
return Item[T]{V: v}
}

// Error creates an item from an error.
func Error[I any](err error) Item[I] {
return Item[I]{E: err}
func Error[T any](err error) Item[T] {
return Item[T]{E: err}
}

// SendItems is an utility function that send a list of items and indicate a
// strategy on whether to close the channel once the function completes.
// This method has been derived from the original SendItems.
// (does not support channels or slice)
func SendItems[I any](ctx context.Context,
ch chan<- Item[I], strategy CloseChannelStrategy, items ...Item[I],
func SendItems[T any](ctx context.Context,
ch chan<- Item[T], strategy CloseChannelStrategy, items ...Item[T],
) {
if strategy == CloseChannel {
defer close(ch)
Expand All @@ -55,25 +55,25 @@ func SendItems[I any](ctx context.Context,
sendItems(ctx, ch, items...)
}

func sendItems[I any](ctx context.Context, ch chan<- Item[I], items ...Item[I]) {
func sendItems[T any](ctx context.Context, ch chan<- Item[T], items ...Item[T]) {
for _, item := range items {
item.SendContext(ctx, ch)
}
}

// IsError checks if an item is an error.
func (i Item[I]) IsError() bool {
func (i Item[T]) IsError() bool {
return i.E != nil
}

// SendBlocking sends an item and blocks until it is sent.
func (i Item[I]) SendBlocking(ch chan<- Item[I]) {
func (i Item[T]) SendBlocking(ch chan<- Item[T]) {
ch <- i
}

// SendContext sends an item and blocks until it is sent or a context canceled.
// It returns a boolean to indicate whether the item was sent.
func (i Item[I]) SendContext(ctx context.Context, ch chan<- Item[I]) bool {
func (i Item[T]) SendContext(ctx context.Context, ch chan<- Item[T]) bool {
select {
case <-ctx.Done(): // Context's done channel has the highest priority
return false
Expand All @@ -87,7 +87,7 @@ func (i Item[I]) SendContext(ctx context.Context, ch chan<- Item[I]) bool {
}
}

func (i Item[I]) SendOpContext(ctx context.Context, ch any) bool { // Item[operator[I]]
func (i Item[T]) SendOpContext(ctx context.Context, ch any) bool { // Item[operator[T]]
_ = ctx
_ = ch

Expand All @@ -96,7 +96,7 @@ func (i Item[I]) SendOpContext(ctx context.Context, ch any) bool { // Item[opera

// SendNonBlocking sends an item without blocking.
// It returns a boolean to indicate whether the item was sent.
func (i Item[I]) SendNonBlocking(ch chan<- Item[I]) bool {
func (i Item[T]) SendNonBlocking(ch chan<- Item[T]) bool {
select {
default:
return false
Expand Down
Loading
Loading