{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Trustworthy #-}
module System.Log.FastLogger.LogStr (
Builder
, LogStr(..)
, logStrLength
, fromLogStr
, ToLogStr(..)
, mempty
, (<>)
) where
import qualified Data.ByteString as BS
import Data.ByteString.Builder (Builder)
import qualified Data.ByteString.Builder as B
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Short as SBS
#if MIN_VERSION_base(4,9,0)
import qualified Data.Semigroup as Semi (Semigroup(..))
#endif
import Data.String (IsString(..))
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
#if MIN_VERSION_text(2,0,0)
import qualified Data.Text.Foreign as T
#endif
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import System.Log.FastLogger.Imports
toBuilder :: ByteString -> Builder
toBuilder :: ByteString -> Builder
toBuilder = ByteString -> Builder
B.byteString
fromBuilder :: Builder -> ByteString
#if MIN_VERSION_bytestring(0,10,0)
fromBuilder :: Builder -> ByteString
fromBuilder = ByteString -> ByteString
BL.toStrict (ByteString -> ByteString)
-> (Builder -> ByteString) -> Builder -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
B.toLazyByteString
#else
fromBuilder = BS.concat . BL.toChunks . B.toLazyByteString
#endif
data LogStr = LogStr !Int Builder
#if MIN_VERSION_base(4,9,0)
instance Semi.Semigroup LogStr where
{-# INLINE (<>) #-}
LogStr Int
s1 Builder
b1 <> :: LogStr -> LogStr -> LogStr
<> LogStr Int
s2 Builder
b2 = Int -> Builder -> LogStr
LogStr (Int
s1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
s2) (Builder
b1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
b2)
instance Monoid LogStr where
mempty :: LogStr
mempty = Int -> Builder -> LogStr
LogStr Int
0 (ByteString -> Builder
toBuilder ByteString
BS.empty)
#else
instance Monoid LogStr where
mempty = LogStr 0 (toBuilder BS.empty)
{-# INLINE mappend #-}
LogStr s1 b1 `mappend` LogStr s2 b2 = LogStr (s1 + s2) (b1 <> b2)
#endif
instance IsString LogStr where
{-# INLINE fromString #-}
fromString :: String -> LogStr
fromString = Text -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Text -> LogStr) -> (String -> Text) -> String -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
TL.pack
class ToLogStr msg where
toLogStr :: msg -> LogStr
instance ToLogStr LogStr where
{-# INLINE toLogStr #-}
toLogStr :: LogStr -> LogStr
toLogStr = LogStr -> LogStr
forall a. a -> a
id
instance ToLogStr S8.ByteString where
{-# INLINE toLogStr #-}
toLogStr :: ByteString -> LogStr
toLogStr ByteString
bs = Int -> Builder -> LogStr
LogStr (ByteString -> Int
BS.length ByteString
bs) (ByteString -> Builder
toBuilder ByteString
bs)
instance ToLogStr BL.ByteString where
{-# INLINE toLogStr #-}
toLogStr :: ByteString -> LogStr
toLogStr ByteString
b = Int -> Builder -> LogStr
LogStr (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int64
BL.length ByteString
b)) (ByteString -> Builder
B.lazyByteString ByteString
b)
instance ToLogStr Builder where
{-# INLINE toLogStr #-}
toLogStr :: Builder -> LogStr
toLogStr Builder
x = let b :: ByteString
b = Builder -> ByteString
B.toLazyByteString Builder
x in Int -> Builder -> LogStr
LogStr (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteString -> Int64
BL.length ByteString
b)) (ByteString -> Builder
B.lazyByteString ByteString
b)
instance ToLogStr SBS.ShortByteString where
{-# INLINE toLogStr #-}
toLogStr :: ShortByteString -> LogStr
toLogStr ShortByteString
b = Int -> Builder -> LogStr
LogStr (ShortByteString -> Int
SBS.length ShortByteString
b) (ShortByteString -> Builder
B.shortByteString ShortByteString
b)
instance ToLogStr String where
{-# INLINE toLogStr #-}
toLogStr :: String -> LogStr
toLogStr = Text -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Text -> LogStr) -> (String -> Text) -> String -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
TL.pack
instance ToLogStr T.Text where
{-# INLINE toLogStr #-}
#if MIN_VERSION_text(2,0,0)
toLogStr :: Text -> LogStr
toLogStr Text
t = Int -> Builder -> LogStr
LogStr (Text -> Int
T.lengthWord8 Text
t) (Text -> Builder
T.encodeUtf8Builder Text
t)
#else
toLogStr = toLogStr . T.encodeUtf8
#endif
instance ToLogStr TL.Text where
{-# INLINE toLogStr #-}
#if MIN_VERSION_text(2,0,0)
toLogStr :: Text -> LogStr
toLogStr Text
t = Int -> Builder -> LogStr
LogStr ((Int -> Text -> Int) -> Int -> Text -> Int
forall a. (a -> Text -> a) -> a -> Text -> a
TL.foldlChunks (\Int
n Text
c -> Text -> Int
T.lengthWord8 Text
c Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n) Int
0 Text
t) (Text -> Builder
TL.encodeUtf8Builder Text
t)
#else
toLogStr = toLogStr . TL.encodeUtf8
#endif
instance ToLogStr Int where
{-# INLINE toLogStr #-}
toLogStr :: Int -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Int -> Builder) -> Int -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder
B.intDec
instance ToLogStr Int8 where
{-# INLINE toLogStr #-}
toLogStr :: Int8 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Int8 -> Builder) -> Int8 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int8 -> Builder
B.int8Dec
instance ToLogStr Int16 where
{-# INLINE toLogStr #-}
toLogStr :: Int16 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Int16 -> Builder) -> Int16 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int16 -> Builder
B.int16Dec
instance ToLogStr Int32 where
{-# INLINE toLogStr #-}
toLogStr :: Int32 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Int32 -> Builder) -> Int32 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> Builder
B.int32Dec
instance ToLogStr Int64 where
{-# INLINE toLogStr #-}
toLogStr :: Int64 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Int64 -> Builder) -> Int64 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> Builder
B.int64Dec
instance ToLogStr Word where
{-# INLINE toLogStr #-}
toLogStr :: Word -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Word -> Builder) -> Word -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> Builder
B.wordDec
instance ToLogStr Word8 where
{-# INLINE toLogStr #-}
toLogStr :: Word8 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Word8 -> Builder) -> Word8 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Builder
B.word8Dec
instance ToLogStr Word16 where
{-# INLINE toLogStr #-}
toLogStr :: Word16 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Word16 -> Builder) -> Word16 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder
B.word16Dec
instance ToLogStr Word32 where
{-# INLINE toLogStr #-}
toLogStr :: Word32 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Word32 -> Builder) -> Word32 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Builder
B.word32Dec
instance ToLogStr Word64 where
{-# INLINE toLogStr #-}
toLogStr :: Word64 -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Word64 -> Builder) -> Word64 -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Builder
B.word64Dec
instance ToLogStr Integer where
{-# INLINE toLogStr #-}
toLogStr :: Integer -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Integer -> Builder) -> Integer -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Builder
B.integerDec
instance ToLogStr Float where
{-# INLINE toLogStr #-}
toLogStr :: Float -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Float -> Builder) -> Float -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Builder
B.floatDec
instance ToLogStr Double where
{-# INLINE toLogStr #-}
toLogStr :: Double -> LogStr
toLogStr = Builder -> LogStr
forall msg. ToLogStr msg => msg -> LogStr
toLogStr (Builder -> LogStr) -> (Double -> Builder) -> Double -> LogStr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Builder
B.doubleDec
instance Show LogStr where
show :: LogStr -> String
show = Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (LogStr -> Text) -> LogStr -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
T.decodeUtf8 (ByteString -> Text) -> (LogStr -> ByteString) -> LogStr -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogStr -> ByteString
fromLogStr
instance Eq LogStr where
LogStr
a == :: LogStr -> LogStr -> Bool
== LogStr
b = LogStr -> ByteString
fromLogStr LogStr
a ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== LogStr -> ByteString
fromLogStr LogStr
b
logStrLength :: LogStr -> Int
logStrLength :: LogStr -> Int
logStrLength (LogStr Int
n Builder
_) = Int
n
fromLogStr :: LogStr -> ByteString
fromLogStr :: LogStr -> ByteString
fromLogStr (LogStr Int
_ Builder
builder) = Builder -> ByteString
fromBuilder Builder
builder