    -- |
    -- Module      : Data.String.Interpolate.Conversion
    -- Copyright   : (c) William Yao, 2019-2020
    -- License     : BSD-3
    -- Maintainer  : williamyaoh@gmail.com
    -- Stability   : experimental
    -- Portability : POSIX

    {-# OPTIONS -Wno-orphans           #-}
    {-# LANGUAGE CPP                   #-}
    {-# LANGUAGE DataKinds             #-}
    {-# LANGUAGE FlexibleInstances     #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE PackageImports        #-}
    {-# LANGUAGE Strict                #-}
    {-# LANGUAGE TypeFamilies          #-}
    {-# LANGUAGE TypeOperators         #-}
    {-# LANGUAGE UndecidableInstances  #-}

    module Data.String.Interpolate.Conversion
      ( IsCustomSink, InterpSink(..), Interpolatable(..)
      , bsToTextBuilder, lbsToTextBuilder, encodeCharUTF8, proxyWrapper
      )
    where

    import Data.String ( IsString, fromString )

    import qualified Data.ByteString         as B
    import qualified Data.ByteString.Builder as LB
    import qualified Data.ByteString.Lazy    as LB
    import qualified Data.Text               as T
    import qualified Data.Text.Lazy          as LT hiding ( singleton )
    import qualified Data.Text.Lazy.Builder  as LT

    import qualified "utf8-string" Data.ByteString.Lazy.UTF8 as LUTF8
    import qualified "utf8-string" Data.ByteString.UTF8      as UTF8

    import Data.String.Interpolate.Conversion.ByteStringSink ()
    import Data.String.Interpolate.Conversion.Classes
    import Data.String.Interpolate.Conversion.Encoding
    import Data.String.Interpolate.Conversion.TextSink       ()

    -- Remove some imports above GHC 8.8.X
    #if MIN_VERSION_base(4,13,0)
    #else
    import "base" Text.Show ( ShowS, showChar, showString )
    #endif

    instance (IsCustomSink str ~ 'False, IsString str) => InterpSink 'False str where
      type Builder 'False str = ShowS

      ofString :: Proxy 'False -> String -> B str (Builder 'False str)
    ofString Proxy 'False
    _ = ShowS -> B str ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B str ShowS)
    -> (String -> ShowS) -> String -> B str ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString
      build :: Proxy 'False
    -> B str (Builder 'False str)
    -> B str (Builder 'False str)
    -> B str (Builder 'False str)
    build Proxy 'False
    _ (B Builder 'False str
    f) (B Builder 'False str
    g) = Builder 'False str -> B str (Builder 'False str)
    forall dst a. a -> B dst a
    B (Builder 'False str -> B str (Builder 'False str))
    -> Builder 'False str -> B str (Builder 'False str)
    forall a b. (a -> b) -> a -> b
    $ Builder 'False str
    ShowS
    f ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder 'False str
    ShowS
    g
      finalize :: Proxy 'False -> B str (Builder 'False str) -> str
    finalize Proxy 'False
    _ = String -> str
    forall a. IsString a => String -> a
    fromString (String -> str) -> (B str ShowS -> String) -> B str ShowS -> str
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ String
    "") (ShowS -> String)
    -> (B str ShowS -> ShowS) -> B str ShowS -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . B str ShowS -> ShowS
    forall dst a. B dst a -> a
    unB

    instance {-# OVERLAPPABLE #-} (Show src, IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False src dst where
      interpolate :: Proxy 'False -> src -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS) -> (src -> ShowS) -> src -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . src -> ShowS
    forall a. Show a => a -> ShowS
    shows
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False Char dst where
      interpolate :: Proxy 'False -> Char -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS) -> (Char -> ShowS) -> Char -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> ShowS
    showChar
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False String dst where
      interpolate :: Proxy 'False -> String -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS)
    -> (String -> ShowS) -> String -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False T.Text dst where
      interpolate :: Proxy 'False -> Text -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS) -> (Text -> ShowS) -> Text -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (Text -> String) -> Text -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False LT.Text dst where
      interpolate :: Proxy 'False -> Text -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS) -> (Text -> ShowS) -> Text -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (Text -> String) -> Text -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    LT.unpack
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False LT.Builder dst where
      interpolate :: Proxy 'False -> Builder -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS)
    -> (Builder -> ShowS) -> Builder -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (Builder -> String) -> Builder -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    LT.unpack (Text -> String) -> (Builder -> Text) -> Builder -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    LT.toLazyText
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False B.ByteString dst where
      interpolate :: Proxy 'False -> ByteString -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS)
    -> (ByteString -> ShowS) -> ByteString -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (ByteString -> String) -> ByteString -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    UTF8.toString
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False LB.ByteString dst where
      interpolate :: Proxy 'False -> ByteString -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS)
    -> (ByteString -> ShowS) -> ByteString -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (ByteString -> String) -> ByteString -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    LUTF8.toString
    instance {-# OVERLAPS #-} (IsString dst, IsCustomSink dst ~ 'False) => Interpolatable 'False LB.Builder dst where
      interpolate :: Proxy 'False -> Builder -> B dst (Builder 'False dst)
    interpolate Proxy 'False
    _ = ShowS -> B dst ShowS
    forall dst a. a -> B dst a
    B (ShowS -> B dst ShowS)
    -> (Builder -> ShowS) -> Builder -> B dst ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    showString (String -> ShowS) -> (Builder -> String) -> Builder -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    LUTF8.toString (ByteString -> String)
    -> (Builder -> ByteString) -> Builder -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> ByteString
    LB.toLazyByteString