{-# LANGUAGE TypeSynonymInstances,FlexibleInstances #-} -- | This module enables debugging all 'ByteString' to 'Text' to 'String' conversions. -- This is an internal module. -- -- @since 0.5.67 module B9.Text ( Text , LazyText , ByteString , LazyByteString , Textual(..) , writeTextFile , unsafeRenderToText , unsafeParseFromText , parseFromTextWithErrorMessage , encodeAsUtf8LazyByteString ) where import Data.ByteString ( ByteString ) import Control.Exception ( displayException ) -- import qualified Data.ByteString as Strict import qualified Data.ByteString.Lazy as LazyByteString import qualified Data.Text as Text import Data.Text ( Text ) import qualified Data.Text.Encoding as Text import qualified Data.Text.IO as Text import qualified Data.Text.Lazy as LazyText import qualified Data.Text.Lazy.Encoding as LazyText -- import qualified Data.Text.Encoding.Error as Text import Control.Monad.IO.Class import GHC.Stack -- | Lazy byte strings. -- -- A type alias to 'Lazy.ByteString' that can be used everywhere such that -- references don't need to be qualified with the complete module name everywere. -- -- @since 0.5.67 type LazyByteString = LazyByteString.ByteString -- | Lazy texts. -- -- A type alias to 'LazyText.Text' that can be used everywhere such that -- references don't need to be qualified with the complete module name everywere. -- -- @since 0.5.67 type LazyText = LazyText.Text -- | A class for values that can be converted to/from 'Text'. -- -- @since 0.5.67 class Textual a where -- | Convert a 'String' to 'Text' -- If an error occured, return 'Left' with the error message. -- -- @since 0.5.67 renderToText :: HasCallStack => a -> Either String Text -- | Convert a 'Text' to 'String' -- -- @since 0.5.67 parseFromText :: HasCallStack => Text -> Either String a instance Textual Text where renderToText = Right parseFromText = Right instance Textual String where renderToText = Right . Text.pack parseFromText = Right . Text.unpack -- | Convert a 'ByteString' with UTF-8 encoded string to 'Text' -- -- @since 0.5.67 instance Textual ByteString where renderToText x = case Text.decodeUtf8' x of Left u -> Left ( "renderToText of the ByteString failed: " ++ displayException u ++ " " ++ show x ++ "\nat:\n" ++ prettyCallStack callStack ) Right t -> Right t parseFromText = Right . Text.encodeUtf8 -- | Convert a 'LazyByteString' with UTF-8 encoded string to 'Text' -- -- @since 0.5.67 instance Textual LazyByteString where renderToText x = case LazyText.decodeUtf8' x of Left u -> Left ( "renderToText of the LazyByteString failed: " ++ displayException u ++ " " ++ show x ++ "\nat:\n" ++ prettyCallStack callStack ) Right t -> Right (LazyText.toStrict t) parseFromText = Right . LazyByteString.fromStrict . Text.encodeUtf8 -- | Render a 'Text' to a file. -- -- @since 0.5.67 writeTextFile :: (HasCallStack, MonadIO m) => FilePath -> Text -> m () writeTextFile f = liftIO . Text.writeFile f -- | Render a 'Text' via 'renderToText' and throw a runtime exception when rendering fails. -- -- @since 0.5.67 unsafeRenderToText :: (Textual a, HasCallStack) => a -> Text unsafeRenderToText = either error id . renderToText -- | Parse a 'Text' via 'parseFromText' and throw a runtime exception when parsing fails. -- -- @since 0.5.67 unsafeParseFromText :: (Textual a, HasCallStack) => Text -> a unsafeParseFromText = either error id . parseFromText -- | Encode a 'String' as UTF-8 encoded into a 'LazyByteString'. -- -- @since 0.5.67 encodeAsUtf8LazyByteString :: HasCallStack => String -> LazyByteString encodeAsUtf8LazyByteString = LazyByteString.fromStrict . Text.encodeUtf8 . Text.pack -- | Parse the given 'Text'. \ -- Return @Left errorMessage@ or @Right a@. -- -- error message. -- -- @since 0.5.67 parseFromTextWithErrorMessage :: (HasCallStack, Textual a) => String -- ^ An arbitrary string for error messages -> Text -> Either String a parseFromTextWithErrorMessage errorMessage b = case parseFromText b of Left e -> Left (unwords [errorMessage, e]) Right a -> Right a