{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE PatternSynonyms #-}

module System.OsString.Internal.Types
  (
    WindowsString(..)
  , pattern WS
  , unWS
  , PosixString(..)
  , unPS
  , pattern PS
  , PlatformString
  , WindowsChar(..)
  , unWW
  , pattern WW
  , PosixChar(..)
  , unPW
  , pattern PW
  , PlatformChar
  , OsString(..)
  , OsChar(..)
  , coercionToPlatformTypes
  )
where


import Control.DeepSeq
import Data.Coerce (coerce)
import Data.Data
import Data.Type.Coercion (Coercion(..), coerceWith)
import Data.Word
import Language.Haskell.TH.Syntax
    ( Lift (..), lift )
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
#endif
import GHC.Generics (Generic)

import System.OsString.Encoding.Internal
import qualified System.OsString.Data.ByteString.Short as BS
import qualified System.OsString.Data.ByteString.Short.Word16 as BS16
import qualified Language.Haskell.TH.Syntax as TH

-- Using unpinned bytearrays to avoid Heap fragmentation and
-- which are reasonably cheap to pass to FFI calls
-- wrapped with typeclass-friendly types allowing to avoid CPP
--
-- Note that, while unpinned bytearrays incur a memcpy on each
-- FFI call, this overhead is generally much preferable to
-- the memory fragmentation of pinned bytearrays

-- | Commonly used windows string as wide character bytes.
newtype WindowsString = WindowsString { WindowsString -> ShortByteString
getWindowsString :: BS.ShortByteString }
  deriving (WindowsString -> WindowsString -> Bool
(WindowsString -> WindowsString -> Bool)
-> (WindowsString -> WindowsString -> Bool) -> Eq WindowsString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WindowsString -> WindowsString -> Bool
== :: WindowsString -> WindowsString -> Bool
$c/= :: WindowsString -> WindowsString -> Bool
/= :: WindowsString -> WindowsString -> Bool
Eq, Eq WindowsString
Eq WindowsString =>
(WindowsString -> WindowsString -> Ordering)
-> (WindowsString -> WindowsString -> Bool)
-> (WindowsString -> WindowsString -> Bool)
-> (WindowsString -> WindowsString -> Bool)
-> (WindowsString -> WindowsString -> Bool)
-> (WindowsString -> WindowsString -> WindowsString)
-> (WindowsString -> WindowsString -> WindowsString)
-> Ord WindowsString
WindowsString -> WindowsString -> Bool
WindowsString -> WindowsString -> Ordering
WindowsString -> WindowsString -> WindowsString
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: WindowsString -> WindowsString -> Ordering
compare :: WindowsString -> WindowsString -> Ordering
$c< :: WindowsString -> WindowsString -> Bool
< :: WindowsString -> WindowsString -> Bool
$c<= :: WindowsString -> WindowsString -> Bool
<= :: WindowsString -> WindowsString -> Bool
$c> :: WindowsString -> WindowsString -> Bool
> :: WindowsString -> WindowsString -> Bool
$c>= :: WindowsString -> WindowsString -> Bool
>= :: WindowsString -> WindowsString -> Bool
$cmax :: WindowsString -> WindowsString -> WindowsString
max :: WindowsString -> WindowsString -> WindowsString
$cmin :: WindowsString -> WindowsString -> WindowsString
min :: WindowsString -> WindowsString -> WindowsString
Ord, NonEmpty WindowsString -> WindowsString
WindowsString -> WindowsString -> WindowsString
(WindowsString -> WindowsString -> WindowsString)
-> (NonEmpty WindowsString -> WindowsString)
-> (forall b. Integral b => b -> WindowsString -> WindowsString)
-> Semigroup WindowsString
forall b. Integral b => b -> WindowsString -> WindowsString
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: WindowsString -> WindowsString -> WindowsString
<> :: WindowsString -> WindowsString -> WindowsString
$csconcat :: NonEmpty WindowsString -> WindowsString
sconcat :: NonEmpty WindowsString -> WindowsString
$cstimes :: forall b. Integral b => b -> WindowsString -> WindowsString
stimes :: forall b. Integral b => b -> WindowsString -> WindowsString
Semigroup, Semigroup WindowsString
WindowsString
Semigroup WindowsString =>
WindowsString
-> (WindowsString -> WindowsString -> WindowsString)
-> ([WindowsString] -> WindowsString)
-> Monoid WindowsString
[WindowsString] -> WindowsString
WindowsString -> WindowsString -> WindowsString
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: WindowsString
mempty :: WindowsString
$cmappend :: WindowsString -> WindowsString -> WindowsString
mappend :: WindowsString -> WindowsString -> WindowsString
$cmconcat :: [WindowsString] -> WindowsString
mconcat :: [WindowsString] -> WindowsString
Monoid, Typeable, (forall x. WindowsString -> Rep WindowsString x)
-> (forall x. Rep WindowsString x -> WindowsString)
-> Generic WindowsString
forall x. Rep WindowsString x -> WindowsString
forall x. WindowsString -> Rep WindowsString x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. WindowsString -> Rep WindowsString x
from :: forall x. WindowsString -> Rep WindowsString x
$cto :: forall x. Rep WindowsString x -> WindowsString
to :: forall x. Rep WindowsString x -> WindowsString
Generic, WindowsString -> ()
(WindowsString -> ()) -> NFData WindowsString
forall a. (a -> ()) -> NFData a
$crnf :: WindowsString -> ()
rnf :: WindowsString -> ()
NFData)

-- | Decodes as UCS-2.
instance Show WindowsString where
  -- cWcharsToChars_UCS2 is total
  show :: WindowsString -> String
show = ShowS
forall a. Show a => a -> String
show ShowS -> (WindowsString -> String) -> WindowsString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word16] -> String
cWcharsToChars_UCS2 ([Word16] -> String)
-> (WindowsString -> [Word16]) -> WindowsString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> [Word16]
BS16.unpack (ShortByteString -> [Word16])
-> (WindowsString -> ShortByteString) -> WindowsString -> [Word16]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowsString -> ShortByteString
getWindowsString

-- | Just a short bidirectional synonym for 'WindowsString' constructor.
pattern WS :: BS.ShortByteString -> WindowsString
pattern $mWS :: forall {r}.
WindowsString -> (ShortByteString -> r) -> ((# #) -> r) -> r
$bWS :: ShortByteString -> WindowsString
WS { WindowsString -> ShortByteString
unWS } <- WindowsString unWS where
  WS ShortByteString
a = ShortByteString -> WindowsString
WindowsString ShortByteString
a
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE WS #-}
#endif


instance Lift WindowsString where
  lift :: forall (m :: * -> *). Quote m => WindowsString -> m Exp
lift (WindowsString ShortByteString
bs) = Exp -> Exp -> Exp
TH.AppE (Name -> Exp
TH.ConE 'WindowsString) (Exp -> Exp) -> m Exp -> m Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ShortByteString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => ShortByteString -> m Exp
lift ShortByteString
bs)
#if MIN_VERSION_template_haskell(2,17,0)
  liftTyped :: forall (m :: * -> *).
Quote m =>
WindowsString -> Code m WindowsString
liftTyped = m Exp -> Code m WindowsString
forall a (m :: * -> *). Quote m => m Exp -> Code m a
TH.unsafeCodeCoerce (m Exp -> Code m WindowsString)
-> (WindowsString -> m Exp)
-> WindowsString
-> Code m WindowsString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowsString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => WindowsString -> m Exp
TH.lift
#elif MIN_VERSION_template_haskell(2,16,0)
  liftTyped = TH.unsafeTExpCoerce . TH.lift
#endif

-- | Commonly used Posix string as uninterpreted @char[]@
-- array.
newtype PosixString = PosixString { PosixString -> ShortByteString
getPosixString :: BS.ShortByteString }
  deriving (PosixString -> PosixString -> Bool
(PosixString -> PosixString -> Bool)
-> (PosixString -> PosixString -> Bool) -> Eq PosixString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PosixString -> PosixString -> Bool
== :: PosixString -> PosixString -> Bool
$c/= :: PosixString -> PosixString -> Bool
/= :: PosixString -> PosixString -> Bool
Eq, Eq PosixString
Eq PosixString =>
(PosixString -> PosixString -> Ordering)
-> (PosixString -> PosixString -> Bool)
-> (PosixString -> PosixString -> Bool)
-> (PosixString -> PosixString -> Bool)
-> (PosixString -> PosixString -> Bool)
-> (PosixString -> PosixString -> PosixString)
-> (PosixString -> PosixString -> PosixString)
-> Ord PosixString
PosixString -> PosixString -> Bool
PosixString -> PosixString -> Ordering
PosixString -> PosixString -> PosixString
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PosixString -> PosixString -> Ordering
compare :: PosixString -> PosixString -> Ordering
$c< :: PosixString -> PosixString -> Bool
< :: PosixString -> PosixString -> Bool
$c<= :: PosixString -> PosixString -> Bool
<= :: PosixString -> PosixString -> Bool
$c> :: PosixString -> PosixString -> Bool
> :: PosixString -> PosixString -> Bool
$c>= :: PosixString -> PosixString -> Bool
>= :: PosixString -> PosixString -> Bool
$cmax :: PosixString -> PosixString -> PosixString
max :: PosixString -> PosixString -> PosixString
$cmin :: PosixString -> PosixString -> PosixString
min :: PosixString -> PosixString -> PosixString
Ord, NonEmpty PosixString -> PosixString
PosixString -> PosixString -> PosixString
(PosixString -> PosixString -> PosixString)
-> (NonEmpty PosixString -> PosixString)
-> (forall b. Integral b => b -> PosixString -> PosixString)
-> Semigroup PosixString
forall b. Integral b => b -> PosixString -> PosixString
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: PosixString -> PosixString -> PosixString
<> :: PosixString -> PosixString -> PosixString
$csconcat :: NonEmpty PosixString -> PosixString
sconcat :: NonEmpty PosixString -> PosixString
$cstimes :: forall b. Integral b => b -> PosixString -> PosixString
stimes :: forall b. Integral b => b -> PosixString -> PosixString
Semigroup, Semigroup PosixString
PosixString
Semigroup PosixString =>
PosixString
-> (PosixString -> PosixString -> PosixString)
-> ([PosixString] -> PosixString)
-> Monoid PosixString
[PosixString] -> PosixString
PosixString -> PosixString -> PosixString
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: PosixString
mempty :: PosixString
$cmappend :: PosixString -> PosixString -> PosixString
mappend :: PosixString -> PosixString -> PosixString
$cmconcat :: [PosixString] -> PosixString
mconcat :: [PosixString] -> PosixString
Monoid, Typeable, (forall x. PosixString -> Rep PosixString x)
-> (forall x. Rep PosixString x -> PosixString)
-> Generic PosixString
forall x. Rep PosixString x -> PosixString
forall x. PosixString -> Rep PosixString x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PosixString -> Rep PosixString x
from :: forall x. PosixString -> Rep PosixString x
$cto :: forall x. Rep PosixString x -> PosixString
to :: forall x. Rep PosixString x -> PosixString
Generic, PosixString -> ()
(PosixString -> ()) -> NFData PosixString
forall a. (a -> ()) -> NFData a
$crnf :: PosixString -> ()
rnf :: PosixString -> ()
NFData)

-- | Prints the raw bytes without decoding.
instance Show PosixString where
  show :: PosixString -> String
show (PosixString ShortByteString
ps) = ShortByteString -> String
forall a. Show a => a -> String
show ShortByteString
ps

-- | Just a short bidirectional synonym for 'PosixString' constructor.
pattern PS :: BS.ShortByteString -> PosixString
pattern $mPS :: forall {r}.
PosixString -> (ShortByteString -> r) -> ((# #) -> r) -> r
$bPS :: ShortByteString -> PosixString
PS { PosixString -> ShortByteString
unPS } <- PosixString unPS where
  PS ShortByteString
a = ShortByteString -> PosixString
PosixString ShortByteString
a
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE PS #-}
#endif

instance Lift PosixString where
  lift :: forall (m :: * -> *). Quote m => PosixString -> m Exp
lift (PosixString ShortByteString
bs) = Exp -> Exp -> Exp
TH.AppE (Name -> Exp
TH.ConE 'PosixString) (Exp -> Exp) -> m Exp -> m Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ShortByteString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => ShortByteString -> m Exp
lift ShortByteString
bs)
#if MIN_VERSION_template_haskell(2,17,0)
  liftTyped :: forall (m :: * -> *). Quote m => PosixString -> Code m PosixString
liftTyped = m Exp -> Code m PosixString
forall a (m :: * -> *). Quote m => m Exp -> Code m a
TH.unsafeCodeCoerce (m Exp -> Code m PosixString)
-> (PosixString -> m Exp) -> PosixString -> Code m PosixString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PosixString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => PosixString -> m Exp
TH.lift
#elif MIN_VERSION_template_haskell(2,16,0)
  liftTyped = TH.unsafeTExpCoerce . TH.lift
#endif


#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
type PlatformString = WindowsString
#else
type PlatformString = PosixString
#endif

newtype WindowsChar = WindowsChar { WindowsChar -> Word16
getWindowsChar :: Word16 }
  deriving (WindowsChar -> WindowsChar -> Bool
(WindowsChar -> WindowsChar -> Bool)
-> (WindowsChar -> WindowsChar -> Bool) -> Eq WindowsChar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WindowsChar -> WindowsChar -> Bool
== :: WindowsChar -> WindowsChar -> Bool
$c/= :: WindowsChar -> WindowsChar -> Bool
/= :: WindowsChar -> WindowsChar -> Bool
Eq, Eq WindowsChar
Eq WindowsChar =>
(WindowsChar -> WindowsChar -> Ordering)
-> (WindowsChar -> WindowsChar -> Bool)
-> (WindowsChar -> WindowsChar -> Bool)
-> (WindowsChar -> WindowsChar -> Bool)
-> (WindowsChar -> WindowsChar -> Bool)
-> (WindowsChar -> WindowsChar -> WindowsChar)
-> (WindowsChar -> WindowsChar -> WindowsChar)
-> Ord WindowsChar
WindowsChar -> WindowsChar -> Bool
WindowsChar -> WindowsChar -> Ordering
WindowsChar -> WindowsChar -> WindowsChar
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: WindowsChar -> WindowsChar -> Ordering
compare :: WindowsChar -> WindowsChar -> Ordering
$c< :: WindowsChar -> WindowsChar -> Bool
< :: WindowsChar -> WindowsChar -> Bool
$c<= :: WindowsChar -> WindowsChar -> Bool
<= :: WindowsChar -> WindowsChar -> Bool
$c> :: WindowsChar -> WindowsChar -> Bool
> :: WindowsChar -> WindowsChar -> Bool
$c>= :: WindowsChar -> WindowsChar -> Bool
>= :: WindowsChar -> WindowsChar -> Bool
$cmax :: WindowsChar -> WindowsChar -> WindowsChar
max :: WindowsChar -> WindowsChar -> WindowsChar
$cmin :: WindowsChar -> WindowsChar -> WindowsChar
min :: WindowsChar -> WindowsChar -> WindowsChar
Ord, Typeable, (forall x. WindowsChar -> Rep WindowsChar x)
-> (forall x. Rep WindowsChar x -> WindowsChar)
-> Generic WindowsChar
forall x. Rep WindowsChar x -> WindowsChar
forall x. WindowsChar -> Rep WindowsChar x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. WindowsChar -> Rep WindowsChar x
from :: forall x. WindowsChar -> Rep WindowsChar x
$cto :: forall x. Rep WindowsChar x -> WindowsChar
to :: forall x. Rep WindowsChar x -> WindowsChar
Generic, WindowsChar -> ()
(WindowsChar -> ()) -> NFData WindowsChar
forall a. (a -> ()) -> NFData a
$crnf :: WindowsChar -> ()
rnf :: WindowsChar -> ()
NFData)

instance Show WindowsChar where
  show :: WindowsChar -> String
show (WindowsChar Word16
wc) = Word16 -> String
forall a. Show a => a -> String
show Word16
wc

newtype PosixChar   = PosixChar { PosixChar -> Word8
getPosixChar :: Word8 }
  deriving (PosixChar -> PosixChar -> Bool
(PosixChar -> PosixChar -> Bool)
-> (PosixChar -> PosixChar -> Bool) -> Eq PosixChar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PosixChar -> PosixChar -> Bool
== :: PosixChar -> PosixChar -> Bool
$c/= :: PosixChar -> PosixChar -> Bool
/= :: PosixChar -> PosixChar -> Bool
Eq, Eq PosixChar
Eq PosixChar =>
(PosixChar -> PosixChar -> Ordering)
-> (PosixChar -> PosixChar -> Bool)
-> (PosixChar -> PosixChar -> Bool)
-> (PosixChar -> PosixChar -> Bool)
-> (PosixChar -> PosixChar -> Bool)
-> (PosixChar -> PosixChar -> PosixChar)
-> (PosixChar -> PosixChar -> PosixChar)
-> Ord PosixChar
PosixChar -> PosixChar -> Bool
PosixChar -> PosixChar -> Ordering
PosixChar -> PosixChar -> PosixChar
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PosixChar -> PosixChar -> Ordering
compare :: PosixChar -> PosixChar -> Ordering
$c< :: PosixChar -> PosixChar -> Bool
< :: PosixChar -> PosixChar -> Bool
$c<= :: PosixChar -> PosixChar -> Bool
<= :: PosixChar -> PosixChar -> Bool
$c> :: PosixChar -> PosixChar -> Bool
> :: PosixChar -> PosixChar -> Bool
$c>= :: PosixChar -> PosixChar -> Bool
>= :: PosixChar -> PosixChar -> Bool
$cmax :: PosixChar -> PosixChar -> PosixChar
max :: PosixChar -> PosixChar -> PosixChar
$cmin :: PosixChar -> PosixChar -> PosixChar
min :: PosixChar -> PosixChar -> PosixChar
Ord, Typeable, (forall x. PosixChar -> Rep PosixChar x)
-> (forall x. Rep PosixChar x -> PosixChar) -> Generic PosixChar
forall x. Rep PosixChar x -> PosixChar
forall x. PosixChar -> Rep PosixChar x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PosixChar -> Rep PosixChar x
from :: forall x. PosixChar -> Rep PosixChar x
$cto :: forall x. Rep PosixChar x -> PosixChar
to :: forall x. Rep PosixChar x -> PosixChar
Generic, PosixChar -> ()
(PosixChar -> ()) -> NFData PosixChar
forall a. (a -> ()) -> NFData a
$crnf :: PosixChar -> ()
rnf :: PosixChar -> ()
NFData)

instance Show PosixChar where
  show :: PosixChar -> String
show (PosixChar Word8
pc) = Word8 -> String
forall a. Show a => a -> String
show Word8
pc

-- | Just a short bidirectional synonym for 'WindowsChar' constructor.
pattern WW :: Word16 -> WindowsChar
pattern $mWW :: forall {r}. WindowsChar -> (Word16 -> r) -> ((# #) -> r) -> r
$bWW :: Word16 -> WindowsChar
WW { WindowsChar -> Word16
unWW } <- WindowsChar unWW where
  WW Word16
a = Word16 -> WindowsChar
WindowsChar Word16
a
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE WW #-}
#endif

-- | Just a short bidirectional synonym for 'PosixChar' constructor.
pattern PW :: Word8 -> PosixChar
pattern $mPW :: forall {r}. PosixChar -> (Word8 -> r) -> ((# #) -> r) -> r
$bPW :: Word8 -> PosixChar
PW { PosixChar -> Word8
unPW } <- PosixChar unPW where
  PW Word8
a = Word8 -> PosixChar
PosixChar Word8
a
#if __GLASGOW_HASKELL__ >= 802
{-# COMPLETE PW #-}
#endif

#if defined(mingw32_HOST_OS) || defined(__MINGW32__)
type PlatformChar = WindowsChar
#else
type PlatformChar = PosixChar
#endif


-- | Newtype representing short operating system specific strings.
--
-- Internally this is either 'WindowsString' or 'PosixString',
-- depending on the platform. Both use unpinned
-- 'ShortByteString' for efficiency.
--
-- The constructor is only exported via "System.OsString.Internal.Types", since
-- dealing with the internals isn't generally recommended, but supported
-- in case you need to write platform specific code.
newtype OsString = OsString { OsString -> PosixString
getOsString :: PlatformString }
  deriving (Typeable, (forall x. OsString -> Rep OsString x)
-> (forall x. Rep OsString x -> OsString) -> Generic OsString
forall x. Rep OsString x -> OsString
forall x. OsString -> Rep OsString x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OsString -> Rep OsString x
from :: forall x. OsString -> Rep OsString x
$cto :: forall x. Rep OsString x -> OsString
to :: forall x. Rep OsString x -> OsString
Generic, OsString -> ()
(OsString -> ()) -> NFData OsString
forall a. (a -> ()) -> NFData a
$crnf :: OsString -> ()
rnf :: OsString -> ()
NFData)

-- | On windows, decodes as UCS-2. On unix prints the raw bytes without decoding.
instance Show OsString where
  show :: OsString -> String
show (OsString PosixString
os) = PosixString -> String
forall a. Show a => a -> String
show PosixString
os

-- | Byte equality of the internal representation.
instance Eq OsString where
  (OsString PosixString
a) == :: OsString -> OsString -> Bool
== (OsString PosixString
b) = PosixString
a PosixString -> PosixString -> Bool
forall a. Eq a => a -> a -> Bool
== PosixString
b

-- | Byte ordering of the internal representation.
instance Ord OsString where
  compare :: OsString -> OsString -> Ordering
compare (OsString PosixString
a) (OsString PosixString
b) = PosixString -> PosixString -> Ordering
forall a. Ord a => a -> a -> Ordering
compare PosixString
a PosixString
b


-- | \"String-Concatenation\" for 'OsString'. This is __not__ the same
-- as '(</>)'.
instance Monoid OsString where
    mempty :: OsString
mempty  = ShortByteString -> OsString
forall a b. Coercible a b => a -> b
coerce ShortByteString
BS.empty
#if MIN_VERSION_base(4,11,0)
    mappend :: OsString -> OsString -> OsString
mappend = OsString -> OsString -> OsString
forall a. Semigroup a => a -> a -> a
(<>)
#else
    mappend = coerce (mappend :: BS.ShortByteString -> BS.ShortByteString -> BS.ShortByteString)
#endif

#if MIN_VERSION_base(4,11,0)
instance Semigroup OsString where
    <> :: OsString -> OsString -> OsString
(<>) = (ShortByteString -> ShortByteString -> ShortByteString)
-> OsString -> OsString -> OsString
forall a b. Coercible a b => a -> b
coerce (ShortByteString -> ShortByteString -> ShortByteString
forall a. Monoid a => a -> a -> a
mappend :: BS.ShortByteString -> BS.ShortByteString -> BS.ShortByteString)
#endif


instance Lift OsString where
  lift :: forall (m :: * -> *). Quote m => OsString -> m Exp
lift OsString
xs = case Either
  (Coercion OsChar WindowsChar, Coercion OsString WindowsString)
  (Coercion OsChar PosixChar, Coercion OsString PosixString)
coercionToPlatformTypes of
    Left (Coercion OsChar WindowsChar
_, Coercion OsString WindowsString
co) ->
      Exp -> Exp -> Exp
TH.AppE (Name -> Exp
TH.ConE 'OsString) (Exp -> Exp) -> m Exp -> m Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (WindowsString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => WindowsString -> m Exp
lift (WindowsString -> m Exp) -> WindowsString -> m Exp
forall a b. (a -> b) -> a -> b
$ Coercion OsString WindowsString -> OsString -> WindowsString
forall a b. Coercion a b -> a -> b
coerceWith Coercion OsString WindowsString
co OsString
xs)
    Right (Coercion OsChar PosixChar
_, Coercion OsString PosixString
co) -> do
      Exp -> Exp -> Exp
TH.AppE (Name -> Exp
TH.ConE 'OsString) (Exp -> Exp) -> m Exp -> m Exp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (PosixString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => PosixString -> m Exp
lift (PosixString -> m Exp) -> PosixString -> m Exp
forall a b. (a -> b) -> a -> b
$ Coercion OsString PosixString -> OsString -> PosixString
forall a b. Coercion a b -> a -> b
coerceWith Coercion OsString PosixString
co OsString
xs)
#if MIN_VERSION_template_haskell(2,17,0)
  liftTyped :: forall (m :: * -> *). Quote m => OsString -> Code m OsString
liftTyped = m Exp -> Code m OsString
forall a (m :: * -> *). Quote m => m Exp -> Code m a
TH.unsafeCodeCoerce (m Exp -> Code m OsString)
-> (OsString -> m Exp) -> OsString -> Code m OsString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OsString -> m Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => OsString -> m Exp
TH.lift
#elif MIN_VERSION_template_haskell(2,16,0)
  liftTyped = TH.unsafeTExpCoerce . TH.lift
#endif


-- | Newtype representing a code unit.
--
-- On Windows, this is restricted to two-octet codepoints 'Word16',
-- on POSIX one-octet ('Word8').
newtype OsChar = OsChar { OsChar -> PosixChar
getOsChar :: PlatformChar }
  deriving (Typeable, (forall x. OsChar -> Rep OsChar x)
-> (forall x. Rep OsChar x -> OsChar) -> Generic OsChar
forall x. Rep OsChar x -> OsChar
forall x. OsChar -> Rep OsChar x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. OsChar -> Rep OsChar x
from :: forall x. OsChar -> Rep OsChar x
$cto :: forall x. Rep OsChar x -> OsChar
to :: forall x. Rep OsChar x -> OsChar
Generic, OsChar -> ()
(OsChar -> ()) -> NFData OsChar
forall a. (a -> ()) -> NFData a
$crnf :: OsChar -> ()
rnf :: OsChar -> ()
NFData)

instance Show OsChar where
  show :: OsChar -> String
show (OsChar PosixChar
pc) = PosixChar -> String
forall a. Show a => a -> String
show PosixChar
pc

-- | Byte equality of the internal representation.
instance Eq OsChar where
  (OsChar PosixChar
a) == :: OsChar -> OsChar -> Bool
== (OsChar PosixChar
b) = PosixChar
a PosixChar -> PosixChar -> Bool
forall a. Eq a => a -> a -> Bool
== PosixChar
b

-- | Byte ordering of the internal representation.
instance Ord OsChar where
  compare :: OsChar -> OsChar -> Ordering
compare (OsChar PosixChar
a) (OsChar PosixChar
b) = PosixChar -> PosixChar -> Ordering
forall a. Ord a => a -> a -> Ordering
compare PosixChar
a PosixChar
b

-- | This is a type-level evidence that 'OsChar' is a newtype wrapper
-- over 'WindowsChar' or 'PosixChar' and 'OsString' is a newtype wrapper
-- over 'WindowsString' or 'PosixString'. If you pattern match on
-- 'coercionToPlatformTypes', GHC will know that relevant types
-- are coercible to each other. This helps to avoid CPP in certain scenarios.
coercionToPlatformTypes
  :: Either
  (Coercion OsChar WindowsChar, Coercion OsString WindowsString)
  (Coercion OsChar PosixChar, Coercion OsString PosixString)
#if defined(mingw32_HOST_OS)
coercionToPlatformTypes = Left (Coercion, Coercion)
#else
coercionToPlatformTypes :: Either
  (Coercion OsChar WindowsChar, Coercion OsString WindowsString)
  (Coercion OsChar PosixChar, Coercion OsString PosixString)
coercionToPlatformTypes = (Coercion OsChar PosixChar, Coercion OsString PosixString)
-> Either
     (Coercion OsChar WindowsChar, Coercion OsString WindowsString)
     (Coercion OsChar PosixChar, Coercion OsString PosixString)
forall a b. b -> Either a b
Right (Coercion OsChar PosixChar
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion, Coercion OsString PosixString
forall {k} (a :: k) (b :: k). Coercible a b => Coercion a b
Coercion)
#endif