-- |
-- 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 UndecidableInstances  #-}

module Data.String.Interpolate.Conversion
  ( IsCustomSink, InterpSink(..), Interpolatable(..)
  , bsToTextBuilder, lbsToTextBuilder, encodeCharUTF8
  )
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) = ShowS -> B str ShowS
forall dst a. a -> B dst a
B (ShowS -> B str ShowS) -> ShowS -> B str ShowS
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