{-# LANGUAGE ExistentialQuantification #-}
module Xrefcheck.Data.URI
( UriParseError (..)
, parseUri
) where
import Universum
import Control.Exception.Safe (handleJust)
import Control.Monad.Except (throwError)
import Text.URI (ParseExceptionBs, URI, mkURIBs)
import URI.ByteString qualified as URIBS
data UriParseError
= UPEInvalid URIBS.URIParseError
| UPEConversion ParseExceptionBs
deriving stock (Int -> UriParseError -> ShowS
[UriParseError] -> ShowS
UriParseError -> String
(Int -> UriParseError -> ShowS)
-> (UriParseError -> String)
-> ([UriParseError] -> ShowS)
-> Show UriParseError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UriParseError -> ShowS
showsPrec :: Int -> UriParseError -> ShowS
$cshow :: UriParseError -> String
show :: UriParseError -> String
$cshowList :: [UriParseError] -> ShowS
showList :: [UriParseError] -> ShowS
Show, UriParseError -> UriParseError -> Bool
(UriParseError -> UriParseError -> Bool)
-> (UriParseError -> UriParseError -> Bool) -> Eq UriParseError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: UriParseError -> UriParseError -> Bool
== :: UriParseError -> UriParseError -> Bool
$c/= :: UriParseError -> UriParseError -> Bool
/= :: UriParseError -> UriParseError -> Bool
Eq)
data AnyURIRef = forall a. AnyURIRef (URIBS.URIRef a)
serializeAnyURIRef :: AnyURIRef -> ByteString
serializeAnyURIRef :: AnyURIRef -> ByteString
serializeAnyURIRef (AnyURIRef URIRef a
uri) = URIRef a -> ByteString
forall a. URIRef a -> ByteString
URIBS.serializeURIRef' URIRef a
uri
parseUri :: Bool -> Text -> ExceptT UriParseError IO URI
parseUri :: Bool -> Text -> ExceptT UriParseError IO URI
parseUri Bool
canBeRelative Text
link = do
AnyURIRef
uri <- case URIParserOptions
-> ByteString -> Either URIParseError (URIRef Absolute)
URIBS.parseURI URIParserOptions
URIBS.laxURIParserOptions (Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 Text
link) of
Left (URIBS.MalformedScheme SchemaError
_) | Bool
canBeRelative ->
URIParserOptions
-> ByteString -> Either URIParseError (URIRef Relative)
URIBS.parseRelativeRef URIParserOptions
URIBS.laxURIParserOptions (Text -> ByteString
forall a b. ConvertUtf8 a b => a -> b
encodeUtf8 Text
link)
Either URIParseError (URIRef Relative)
-> (Either URIParseError (URIRef Relative)
-> ExceptT UriParseError IO AnyURIRef)
-> ExceptT UriParseError IO AnyURIRef
forall a b. a -> (a -> b) -> b
& (URIParseError -> ExceptT UriParseError IO AnyURIRef)
-> (URIRef Relative -> ExceptT UriParseError IO AnyURIRef)
-> Either URIParseError (URIRef Relative)
-> ExceptT UriParseError IO AnyURIRef
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (UriParseError -> ExceptT UriParseError IO AnyURIRef
forall a. UriParseError -> ExceptT UriParseError IO a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (UriParseError -> ExceptT UriParseError IO AnyURIRef)
-> (URIParseError -> UriParseError)
-> URIParseError
-> ExceptT UriParseError IO AnyURIRef
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URIParseError -> UriParseError
UPEInvalid) (AnyURIRef -> ExceptT UriParseError IO AnyURIRef
forall a. a -> ExceptT UriParseError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyURIRef -> ExceptT UriParseError IO AnyURIRef)
-> (URIRef Relative -> AnyURIRef)
-> URIRef Relative
-> ExceptT UriParseError IO AnyURIRef
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URIRef Relative -> AnyURIRef
forall a. URIRef a -> AnyURIRef
AnyURIRef)
Left URIParseError
err -> UriParseError -> ExceptT UriParseError IO AnyURIRef
forall a. UriParseError -> ExceptT UriParseError IO a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (UriParseError -> ExceptT UriParseError IO AnyURIRef)
-> UriParseError -> ExceptT UriParseError IO AnyURIRef
forall a b. (a -> b) -> a -> b
$ URIParseError -> UriParseError
UPEInvalid URIParseError
err
Right URIRef Absolute
uri -> AnyURIRef -> ExceptT UriParseError IO AnyURIRef
forall a. a -> ExceptT UriParseError IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyURIRef -> ExceptT UriParseError IO AnyURIRef)
-> AnyURIRef -> ExceptT UriParseError IO AnyURIRef
forall a b. (a -> b) -> a -> b
$ URIRef Absolute -> AnyURIRef
forall a. URIRef a -> AnyURIRef
AnyURIRef URIRef Absolute
uri
ByteString -> ExceptT UriParseError IO URI
forall (m :: * -> *). MonadThrow m => ByteString -> m URI
mkURIBs (AnyURIRef -> ByteString
serializeAnyURIRef AnyURIRef
uri)
ExceptT UriParseError IO URI
-> (ExceptT UriParseError IO URI -> ExceptT UriParseError IO URI)
-> ExceptT UriParseError IO URI
forall a b. a -> (a -> b) -> b
& (SomeException -> Maybe ParseExceptionBs)
-> (ParseExceptionBs -> ExceptT UriParseError IO URI)
-> ExceptT UriParseError IO URI
-> ExceptT UriParseError IO URI
forall (m :: * -> *) e b a.
(HasCallStack, MonadCatch m, Exception e) =>
(e -> Maybe b) -> (b -> m a) -> m a -> m a
handleJust SomeException -> Maybe ParseExceptionBs
forall e. Exception e => SomeException -> Maybe e
fromException (UriParseError -> ExceptT UriParseError IO URI
forall a. UriParseError -> ExceptT UriParseError IO a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (UriParseError -> ExceptT UriParseError IO URI)
-> (ParseExceptionBs -> UriParseError)
-> ParseExceptionBs
-> ExceptT UriParseError IO URI
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParseExceptionBs -> UriParseError
UPEConversion)