desktop-portal-0.8.0.0: src/Desktop/Portal/Util.hs
module Desktop.Portal.Util
( optionalFromVariant,
mapJust,
toVariantPair,
toVariantPair',
encodeNullTerminated,
decodeNullTerminated,
decodeFileUri,
decodeFileUris,
)
where
import DBus (IsVariant, Variant)
import DBus qualified
import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Lazy qualified as Bytes
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Text (Text, unpack)
import System.OsPath (OsPath)
import System.OsPath qualified as OsPath
import System.OsString.Data.ByteString.Short qualified as ShortByteString
import Text.URI (Authority (..), URI (..))
import Text.URI qualified as URI
import "os-string" System.OsString.Internal.Types (OsString (..), PosixString (..))
-- | 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 key variants =
mapJust DBus.fromVariant (Map.lookup key variants)
mapJust :: (a -> Maybe b) -> Maybe a -> Maybe (Maybe b)
mapJust f = \case
Nothing -> Just Nothing
Just x -> Just <$> f x
toVariantPair :: (IsVariant a) => Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair = toVariantPair' id
toVariantPair' :: (IsVariant b) => (a -> b) -> Text -> Maybe a -> Maybe (Text, Variant)
toVariantPair' f key = \case
Nothing -> Nothing
Just x -> Just (key, DBus.toVariant (f x))
encodeNullTerminated :: OsString -> ByteString
encodeNullTerminated (OsString (PosixString txt)) =
Bytes.fromStrict (ShortByteString.fromShort (txt <> ShortByteString.singleton 0))
decodeNullTerminated :: ByteString -> OsString
decodeNullTerminated =
OsString . PosixString . ShortByteString.toShort . Bytes.toStrict . Bytes.dropWhileEnd (== 0)
decodeFileUri :: Text -> Maybe OsPath
decodeFileUri uri =
case URI.mkURI uri of
Just
URI
{ uriScheme = Just (URI.unRText -> "file"),
uriAuthority = (validAuthority -> True),
uriPath = Just (_trailingSlash, parts),
uriQuery = [],
uriFragment = Nothing
} -> OsPath.encodeUtf . unpack $ foldMap (("/" <>) . URI.unRText) parts
_ ->
Nothing
where
validAuthority = \case
Left True -> True
Right
Authority
{ authUserInfo = Nothing,
authHost = (URI.unRText -> ""),
authPort = Nothing
} -> True
_ -> False
decodeFileUris :: [Text] -> Maybe [OsPath]
decodeFileUris = traverse decodeFileUri