module Desktop.Portal.Util
  ( optionalFromVariant,
    mapJust,
    toVariantPair,
    toVariantPair',
    encodeNullTerminatedUtf8,
  )
where

import DBus (IsVariant, Variant)
import DBus qualified
import Data.Binary.Builder qualified as Binary
import Data.ByteString.Lazy (ByteString)
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Text (Text)
import Data.Text.Encoding qualified as Encoding

-- | Returns @Just Nothing@ if the field does not exist, @Just (Just x)@ if it does exist and
-- can be turned into the expected type, or @Nothing@ if the field exists with the wrong type.
optionalFromVariant :: forall a. IsVariant a => Text -> Map Text Variant -> Maybe (Maybe a)
optionalFromVariant :: forall a.
IsVariant a =>
Text -> Map Text Variant -> Maybe (Maybe a)
optionalFromVariant Text
key Map Text Variant
variants =
  forall a b. (a -> Maybe b) -> Maybe a -> Maybe (Maybe b)
mapJust forall a. IsVariant a => Variant -> Maybe a
DBus.fromVariant (forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
key Map Text Variant
variants)

mapJust :: (a -> Maybe b) -> Maybe a -> Maybe (Maybe b)
mapJust :: forall a b. (a -> Maybe b) -> Maybe a -> Maybe (Maybe b)
mapJust a -> Maybe b
f = \case
  Maybe a
Nothing -> forall a. a -> Maybe a
Just forall a. Maybe a
Nothing
  Just a
x -> forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe b
f a
x

toVariantPair :: IsVariant a => Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair :: forall a. IsVariant a => Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair = forall b a.
IsVariant b =>
(a -> b) -> Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair' forall a. a -> a
id

toVariantPair' :: IsVariant b => (a -> b) -> Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair' :: forall b a.
IsVariant b =>
(a -> b) -> Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair' a -> b
f Text
key = \case
  Maybe a
Nothing -> forall a. Maybe a
Nothing
  Just a
x -> forall a. a -> Maybe a
Just (Text
key, forall a. IsVariant a => a -> Variant
DBus.toVariant (a -> b
f a
x))

encodeNullTerminatedUtf8 :: Text -> ByteString
encodeNullTerminatedUtf8 :: Text -> ByteString
encodeNullTerminatedUtf8 Text
txt =
  Builder -> ByteString
Binary.toLazyByteString (Text -> Builder
Encoding.encodeUtf8Builder Text
txt forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
Binary.singleton Word8
0)