From b5f245e703912c4066732c8d9753833194c8a61f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 23 Feb 2024 15:22:07 +0800 Subject: [PATCH 1/2] Add a new package values and new type NullableValue --- modules/values/nullable.go | 30 ++++++++++++++++++++++++++++++ modules/values/nullable_test.go | 21 +++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 modules/values/nullable.go create mode 100644 modules/values/nullable_test.go diff --git a/modules/values/nullable.go b/modules/values/nullable.go new file mode 100644 index 000000000000..697d557597b5 --- /dev/null +++ b/modules/values/nullable.go @@ -0,0 +1,30 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package values + +type NullableValue[T any] struct { + value *T + isNil bool +} + +func (n NullableValue[T]) IsNone() bool { + return n.isNil +} + +func (n NullableValue[T]) IsSome() bool { + return !n.isNil +} + +func (n NullableValue[T]) Value() T { + // check if the value is nil first, otherwise panic + return *n.value +} + +func None[T any]() NullableValue[T] { + return NullableValue[T]{nil, true} +} + +func Nullable[T any](value T) NullableValue[T] { + return NullableValue[T]{&value, false} +} diff --git a/modules/values/nullable_test.go b/modules/values/nullable_test.go new file mode 100644 index 000000000000..fd7e62b4cf49 --- /dev/null +++ b/modules/values/nullable_test.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package values + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNullable(t *testing.T) { + boolV := Nullable(true) + assert.True(t, boolV.Value()) + assert.True(t, boolV.IsSome()) + assert.False(t, boolV.IsNone()) + + nilBool := None[bool]() + assert.False(t, nilBool.IsSome()) + assert.True(t, nilBool.IsNone()) +} From f166ac58df8178d92302031a07eda11656d26637 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 23 Feb 2024 15:33:23 +0800 Subject: [PATCH 2/2] reimplement OptionalBool with values.NullableValue --- modules/indexer/issues/db/options.go | 3 ++- modules/util/util.go | 30 ++++++++++------------------ modules/values/nullable.go | 16 +++++++-------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go index 5406715bbcfb..957738a6ed59 100644 --- a/modules/indexer/issues/db/options.go +++ b/modules/indexer/issues/db/options.go @@ -11,6 +11,7 @@ import ( issue_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/indexer/issues/internal" + "code.gitea.io/gitea/modules/util" ) func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_model.IssuesOptions, error) { @@ -75,7 +76,7 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m UpdatedAfterUnix: convertInt64(options.UpdatedAfterUnix), UpdatedBeforeUnix: convertInt64(options.UpdatedBeforeUnix), PriorityRepoID: 0, - IsArchived: 0, + IsArchived: util.OptionalBoolNone, Org: nil, Team: nil, User: nil, diff --git a/modules/util/util.go b/modules/util/util.go index 28b549f40553..1b596a0bfef8 100644 --- a/modules/util/util.go +++ b/modules/util/util.go @@ -12,36 +12,37 @@ import ( "strings" "code.gitea.io/gitea/modules/optional" + "code.gitea.io/gitea/modules/values" "golang.org/x/text/cases" "golang.org/x/text/language" ) // OptionalBool a boolean that can be "null" -type OptionalBool byte +type OptionalBool values.NullableValue[bool] -const ( +var ( // OptionalBoolNone a "null" boolean value - OptionalBoolNone OptionalBool = iota + OptionalBoolNone = OptionalBool(values.None[bool]()) // OptionalBoolTrue a "true" boolean value - OptionalBoolTrue + OptionalBoolTrue = OptionalBool(values.Nullable(true)) // OptionalBoolFalse a "false" boolean value - OptionalBoolFalse + OptionalBoolFalse = OptionalBool(values.Nullable(false)) ) // IsTrue return true if equal to OptionalBoolTrue func (o OptionalBool) IsTrue() bool { - return o == OptionalBoolTrue + return values.NullableValue[bool](o).Equal(true) } // IsFalse return true if equal to OptionalBoolFalse func (o OptionalBool) IsFalse() bool { - return o == OptionalBoolFalse + return values.NullableValue[bool](o).Equal(false) } // IsNone return true if equal to OptionalBoolNone func (o OptionalBool) IsNone() bool { - return o == OptionalBoolNone + return values.NullableValue[bool](o).IsNone() } // ToGeneric converts OptionalBool to optional.Option[bool] @@ -52,20 +53,9 @@ func (o OptionalBool) ToGeneric() optional.Option[bool] { return optional.Some[bool](o.IsTrue()) } -// OptionalBoolFromGeneric converts optional.Option[bool] to OptionalBool -func OptionalBoolFromGeneric(o optional.Option[bool]) OptionalBool { - if o.Has() { - return OptionalBoolOf(o.Value()) - } - return OptionalBoolNone -} - // OptionalBoolOf get the corresponding OptionalBool of a bool func OptionalBoolOf(b bool) OptionalBool { - if b { - return OptionalBoolTrue - } - return OptionalBoolFalse + return OptionalBool(values.Nullable(b)) } // OptionalBoolParse get the corresponding OptionalBool of a string using strconv.ParseBool diff --git a/modules/values/nullable.go b/modules/values/nullable.go index 697d557597b5..ff518d872e95 100644 --- a/modules/values/nullable.go +++ b/modules/values/nullable.go @@ -3,7 +3,7 @@ package values -type NullableValue[T any] struct { +type NullableValue[T comparable] struct { value *T isNil bool } @@ -12,19 +12,19 @@ func (n NullableValue[T]) IsNone() bool { return n.isNil } -func (n NullableValue[T]) IsSome() bool { - return !n.isNil -} - func (n NullableValue[T]) Value() T { - // check if the value is nil first, otherwise panic + // check if the value IsNone first, otherwise panic return *n.value } -func None[T any]() NullableValue[T] { +func (n NullableValue[T]) Equal(v T) bool { + return n.value != nil && *n.value == v +} + +func None[T comparable]() NullableValue[T] { return NullableValue[T]{nil, true} } -func Nullable[T any](value T) NullableValue[T] { +func Nullable[T comparable](value T) NullableValue[T] { return NullableValue[T]{&value, false} }