1// Copyright 2023 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package optional
16
17// ShallowOptional is an optional type that can be constructed from a pointer.
18// It will not copy the pointer, and its size is the same size as a single pointer.
19// It can be used to prevent a downstream consumer from modifying the value through
20// the pointer, but is not suitable for an Optional type with stronger value semantics
21// like you would expect from C++ or Rust Optionals.
22type ShallowOptional[T any] struct {
23	inner *T
24}
25
26// NewShallowOptional creates a new ShallowOptional from a pointer.
27// The pointer will not be copied, the object could be changed by the calling
28// code after the optional was created.
29func NewShallowOptional[T any](inner *T) ShallowOptional[T] {
30	return ShallowOptional[T]{inner: inner}
31}
32
33// IsPresent returns true if the optional contains a value
34func (o *ShallowOptional[T]) IsPresent() bool {
35	return o.inner != nil
36}
37
38// IsEmpty returns true if the optional does not have a value
39func (o *ShallowOptional[T]) IsEmpty() bool {
40	return o.inner == nil
41}
42
43// Get() returns the value inside the optional. It panics if IsEmpty() returns true
44func (o *ShallowOptional[T]) Get() T {
45	if o.inner == nil {
46		panic("tried to get an empty optional")
47	}
48	return *o.inner
49}
50
51// GetOrDefault() returns the value inside the optional if IsPresent() returns true,
52// or the provided value otherwise.
53func (o *ShallowOptional[T]) GetOrDefault(other T) T {
54	if o.inner == nil {
55		return other
56	}
57	return *o.inner
58}
59