{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE UnboxedSums #-}
{-# LANGUAGE UnboxedTuples #-}

{- | Unboxed @Maybe@ using @UnboxedSums@ to eliminate the @Just@/@Nothing@
heap indirection. When stored as @{\-\# UNPACK \#-\} !(UMaybe a)@ in a
parent record, GHC can inline the tag + pointer directly into the parent
closure, so there is zero extra indirection for the Maybe layer.

Based on unpacked-maybe by Kyle McKean & Daniel Cartwright (BSD-3).
-}
module OpenTelemetry.Internal.UnpackedMaybe (
  UMaybe (UMaybe, UJust, UNothing),
  umaybe,
  isUJust,
  isUNothing,
  fromUMaybe,
  toBaseMaybe,
  fromBaseMaybe,
) where

import Data.Function (id)
import Prelude (Bool (..), Maybe (..))


{- | An unboxed optional value. Single-constructor wrapper around an unboxed
sum, so @{\-\# UNPACK \#-\}@ can flatten it into a parent record.

@since 0.0.1.0
-}
data UMaybe a = UMaybe (# (# #) | a #)


pattern UJust :: a -> UMaybe a
pattern $bUJust :: forall a. a -> UMaybe a
$mUJust :: forall {r} {a}. UMaybe a -> (a -> r) -> ((# #) -> r) -> r
UJust a = UMaybe (# | a #)


pattern UNothing :: UMaybe a
pattern $bUNothing :: forall a. UMaybe a
$mUNothing :: forall {r} {a}. UMaybe a -> ((# #) -> r) -> ((# #) -> r) -> r
UNothing = UMaybe (# (# #) | #)


{-# COMPLETE UJust, UNothing #-}


-- | @since 0.0.1.0
umaybe :: b -> (a -> b) -> UMaybe a -> b
umaybe :: forall b a. b -> (a -> b) -> UMaybe a -> b
umaybe b
def a -> b
f (UMaybe (# (# #) | a #)
x) = case (# (# #) | a #)
x of
  (# (# #) | #) -> b
def
  (# | a
a #) -> a -> b
f a
a
{-# INLINE umaybe #-}


-- | @since 0.0.1.0
isUJust :: UMaybe a -> Bool
isUJust :: forall a. UMaybe a -> Bool
isUJust (UJust a
_) = Bool
True
isUJust UMaybe a
_ = Bool
False
{-# INLINE isUJust #-}


-- | @since 0.0.1.0
isUNothing :: UMaybe a -> Bool
isUNothing :: forall a. UMaybe a -> Bool
isUNothing UMaybe a
UNothing = Bool
True
isUNothing UMaybe a
_ = Bool
False
{-# INLINE isUNothing #-}


-- | @since 0.0.1.0
fromUMaybe :: a -> UMaybe a -> a
fromUMaybe :: forall a. a -> UMaybe a -> a
fromUMaybe a
def = a -> (a -> a) -> UMaybe a -> a
forall b a. b -> (a -> b) -> UMaybe a -> b
umaybe a
def a -> a
forall a. a -> a
id
{-# INLINE fromUMaybe #-}


-- | @since 0.0.1.0
toBaseMaybe :: UMaybe a -> Maybe a
toBaseMaybe :: forall a. UMaybe a -> Maybe a
toBaseMaybe = Maybe a -> (a -> Maybe a) -> UMaybe a -> Maybe a
forall b a. b -> (a -> b) -> UMaybe a -> b
umaybe Maybe a
forall a. Maybe a
Nothing a -> Maybe a
forall a. a -> Maybe a
Just
{-# INLINE toBaseMaybe #-}


-- | @since 0.0.1.0
fromBaseMaybe :: Maybe a -> UMaybe a
fromBaseMaybe :: forall a. Maybe a -> UMaybe a
fromBaseMaybe (Just a
x) = a -> UMaybe a
forall a. a -> UMaybe a
UJust a
x
fromBaseMaybe Maybe a
Nothing = UMaybe a
forall a. UMaybe a
UNothing
{-# INLINE fromBaseMaybe #-}