{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Text.JSON.Canonical.Types
( JSValue(..)
, Int54(..)
, JSString
, toJSString
, fromJSString
) where
import Control.Arrow (first)
import Control.DeepSeq (NFData(..))
import Data.Bits (Bits)
#if MIN_VERSION_base(4,7,0)
import Data.Bits (FiniteBits)
#endif
import Data.Data (Data)
import Data.Int (Int64)
import Data.Ix (Ix)
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (Monoid)
#endif
#if MIN_VERSION_base(4,9,0)
import Data.Semigroup (Semigroup)
#endif
import Data.Typeable (Typeable)
import Foreign.Storable (Storable)
#if MIN_VERSION_base(4,7,0)
import Text.Printf (PrintfArg(..))
import qualified Text.Printf as Printf
#else
import Text.Printf (PrintfArg)
#endif
import Data.String (IsString)
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as BS
data JSValue
= JSNull
| JSBool !Bool
| JSNum !Int54
| JSString !JSString
| JSArray [JSValue]
| JSObject [(JSString, JSValue)]
deriving (Show, Read, Eq, Ord)
instance NFData JSValue where
rnf JSNull = ()
rnf JSBool{} = ()
rnf JSNum{} = ()
rnf JSString{} = ()
rnf (JSArray vs) = rnf vs
rnf (JSObject vs) = rnf vs
newtype JSString = JStr ShortByteString
deriving (Eq, Ord, IsString,
#if MIN_VERSION_base(4,9,0)
Semigroup,
#endif
Monoid)
instance NFData JSString where
rnf JStr{} = ()
instance Show JSString where
showsPrec n (JStr bs) = showsPrec n bs
instance Read JSString where
readsPrec p = map (first JStr) . readsPrec p
#if MIN_VERSION_base(4,7,0)
instance PrintfArg JSString where
formatArg = Printf.formatString . fromJSString
#endif
toJSString :: String -> JSString
toJSString str
| all (<= '\255') str = JStr . BS.pack . map (fromIntegral . fromEnum) $ str
| otherwise = error "toJSString: cannot use non-ASCII chars"
fromJSString :: JSString -> String
fromJSString = map (toEnum . fromIntegral) . BS.unpack . (\(JStr bs) -> bs)
newtype Int54 = Int54 { int54ToInt64 :: Int64 }
deriving ( Enum
, Eq
, Integral
, Data
, Num
, Ord
, Real
, Ix
#if MIN_VERSION_base(4,7,0)
, FiniteBits
#endif
, Bits
, Storable
, PrintfArg
, Typeable
)
instance Bounded Int54 where
maxBound = Int54 ( 2^(53 :: Int) - 1)
minBound = Int54 (-(2^(53 :: Int) - 1))
instance Show Int54 where
show = show . int54ToInt64
instance Read Int54 where
readsPrec p = map (first Int54) . readsPrec p