rfc-prelude-0.0.0.1: src/RFC/Prelude/String.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module RFC.Prelude.String
( module RFC.Prelude.String
, module Data.Text.Conversions
) where
import ClassyPrelude hiding ( fail )
import Control.Monad.Fail ( MonadFail, fail )
import qualified Data.ByteString as SB
import qualified Data.ByteString.Lazy as LB
import qualified Data.ByteString.Short as Sbs
import Data.String ( String )
import qualified Data.Text as ST
import Data.Text.Conversions
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Builder as LTBuilder
import Network.URI ( URI (..), parseURIReference, uriToString )
import RFC.Prelude.Instances ()
#if VERSION_servant_docs
import Servant.Docs
#endif
{-# ANN module "HLint: ignore Use String" #-}
type LazyText = LT.Text
type StrictText = ST.Text
type LazyByteString = LB.ByteString
type StrictByteString = SB.ByteString
type ShortByteString = Sbs.ShortByteString
type LazyTextBuilder = LTBuilder.Builder
toStrictText :: (ToText a) => a -> StrictText
toStrictText = toText
{-# SPECIALIZE INLINE toStrictText :: String -> StrictText #-}
{-# SPECIALIZE INLINE toStrictText :: LazyText -> StrictText #-}
{-# SPECIALIZE INLINE toStrictText :: StrictText -> StrictText #-}
toLazyText :: (ToText a) => a -> LazyText
toLazyText = LT.fromStrict . toText
{-# INLINE toLazyText #-}
{-# SPECIALIZE INLINE toLazyText :: String -> LazyText #-}
{-# SPECIALIZE INLINE toLazyText :: StrictText -> LazyText #-}
{-# SPECIALIZE INLINE toLazyText :: LazyText -> LazyText #-}
toUTF8 :: (ToText a, FromText (UTF8 b)) => a -> b
toUTF8 = unUTF8 . fromText . toText
{-# INLINE toUTF8 #-}
{-# SPECIALIZE INLINE toUTF8 :: String-> LazyByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: StrictText -> LazyByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: LazyText -> LazyByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: String-> StrictByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: StrictText -> StrictByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: LazyText -> StrictByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: String-> ShortByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: StrictText -> ShortByteString #-}
{-# SPECIALIZE INLINE toUTF8 :: LazyText -> ShortByteString #-}
fromUTF8 :: (DecodeText f (UTF8 a), FromText b) => a -> f b
fromUTF8 = decodeConvertText . UTF8
{-# INLINE fromUTF8 #-}
{-# SPECIALIZE INLINE fromUTF8 :: LazyByteString -> Maybe String #-}
{-# SPECIALIZE INLINE fromUTF8 :: LazyByteString -> Maybe StrictText #-}
{-# SPECIALIZE INLINE fromUTF8 :: LazyByteString -> Maybe LazyText #-}
{-# SPECIALIZE INLINE fromUTF8 :: StrictByteString -> Maybe String #-}
{-# SPECIALIZE INLINE fromUTF8 :: StrictByteString -> Maybe StrictText #-}
{-# SPECIALIZE INLINE fromUTF8 :: StrictByteString -> Maybe LazyText #-}
{-# SPECIALIZE INLINE fromUTF8 :: ShortByteString -> Maybe String #-}
{-# SPECIALIZE INLINE fromUTF8 :: ShortByteString -> Maybe StrictText #-}
{-# SPECIALIZE INLINE fromUTF8 :: ShortByteString -> Maybe LazyText #-}
instance {-# OVERLAPPING #-} FromText (UTF8 ShortByteString) where
fromText = UTF8 . Sbs.toShort . encodeUtf8
{-# INLINE fromText #-}
instance {-# INCOHERENT #-} (MonadFail m, Show (UTF8 a), DecodeText Maybe (UTF8 a)) => DecodeText m (UTF8 a) where
{-# SPECIALIZE instance DecodeText IO (UTF8 ShortByteString) #-}
{-# SPECIALIZE instance DecodeText [] (UTF8 ShortByteString) #-}
decodeText arg =
case decodeText arg of
Nothing ->
fail $ "Unable to decode text: " <> show arg
Just x ->
return x
{-# INLINE decodeText #-}
emptyString :: (FromText a) => a
emptyString = fromText $ toText ""
{-# INLINE emptyString #-}
{-# SPECIALIZE INLINE emptyString :: String #-}
{-# SPECIALIZE INLINE emptyString :: LazyText #-}
{-# SPECIALIZE INLINE emptyString :: StrictText #-}
emptyUTF8 :: (FromText (UTF8 a)) => a
emptyUTF8 = unUTF8 . fromText $ toText ""
{-# INLINE emptyUTF8 #-}
instance {-# OVERLAPPING #-} ToText Char where
toText c = toText [c]
{-# INLINE toText #-}
instance {-# OVERLAPPABLE #-} (FromText a) => FromText (UTF8 a) where
{-# SPECIALISE instance FromText (UTF8 StrictText) #-}
{-# SPECIALISE instance FromText (UTF8 LazyText) #-}
{-# SPECIALISE instance FromText (UTF8 String) #-}
fromText = UTF8 . fromText
{-# INLINE fromText #-}
instance {-# OVERLAPPABLE #-} (ToText a) => ToText (UTF8 a) where
{-# SPECIALISE instance ToText (UTF8 StrictText) #-}
{-# SPECIALISE instance ToText (UTF8 LazyText) #-}
{-# SPECIALISE instance ToText (UTF8 String) #-}
toText = toText . unUTF8
{-# INLINE toText #-}
instance {-# OVERLAPPING #-} ToText URI where
toText uri = toText $ uriToString id uri ""
{-# INLINE toText #-}
instance {-# OVERLAPS #-} (MonadFail f) => FromText (f URI) where
{-# SPECIALIZE instance FromText (Maybe URI) #-}
{-# SPECIALIZE instance FromText (IO URI) #-}
fromText txt =
let str = fromText txt in
case parseURIReference str of
Nothing -> fail $ "Could not parse URI: " <> str
Just uri -> return uri
{-# INLINE fromText #-}
#if VERSION_servant_docs
instance ToSample StrictText where
toSamples _ = singleSample $ toText "This is arbitrary text"
instance ToSample LazyText where
toSamples _ = singleSample $ toText "This is arbitrary text"
#endif
instance {-# OVERLAPPING #-} ToText LazyTextBuilder where
toText = toText . LTBuilder.toLazyText
{-# INLINE toText #-}