module Text.DeadSimpleJSON.Convert (
Value (..),
Convert (..)
) where
import Prelude hiding (True, False)
import qualified Prelude
import Data.Int
import Data.Ratio
import Text.DeadSimpleJSON.Types
import qualified Data.Vector as V
default ()
class Convert a where
convert :: Value -> a
convert' :: Value -> Maybe a
convert' n@(Number _ _) = return $ convert n
convert' _ = fail ""
toJSON :: a -> Value
toJSON = undefined
instance Convert a => Convert (Maybe a) where
convert = convert'
convert' = maybe Nothing Just . convert'
toJSON (Just a) = toJSON a
toJSON Nothing = Null
instance Convert Value where
convert = id
convert' = return
toJSON = id
instance Convert Bool where
convert True = Prelude.True
convert (String "") = Prelude.False
convert (String _) = Prelude.True
convert (Number 0 _) = Prelude.False
convert (Number _ _) = Prelude.True
convert _ = Prelude.False
convert' True = return Prelude.True
convert' False = return Prelude.False
convert' _ = fail ""
toJSON (Prelude.True) = True
toJSON (Prelude.False) = False
instance Convert String where
convert (String s) = s
convert (Number n e)
| e >= 10 = show e
| otherwise = show n ++ "e" ++ show e
convert (Array arr) = tail $ tail $ V.foldr (\v l -> ", " ++ convert v ++ l) "" arr
convert (Object _) = "{object}"
convert True = "true"
convert False = "false"
convert Null = "null"
convert' (String s) = return s
convert' _ = fail ""
toJSON = String
instance Convert a => Convert [a] where
convert (Array v) = map convert $ V.toList v
convert _ = []
convert' arr@(Array _) = return $ convert arr
convert' _ = fail ""
toJSON = Array . V.fromList . map toJSON
instance Convert Double where
convert (Number n e)
| e >= 0 = fromInteger (n * 10 ^ e) / 1.0
| otherwise = fromInteger n / fromInteger (10 ^ negate e)
convert (Object _) = 0/0
convert (Array _) = 0/0
convert Null = 0/0
convert v = def v
instance Convert Float where
convert (Number n e)
| e >= 0 = fromInteger (n * 10 ^ e) / 1.0
| otherwise = fromInteger n / fromInteger (10 ^ negate e)
convert (Object _) = 0/0
convert (Array _) = 0/0
convert Null = 0/0
convert v = def v
instance forall a. (Read a, Integral a) => Convert (Ratio a) where
convert (Number n e)
| e >= 0 = n' * 10 ^ e' % 1
| otherwise = n' % 10 ^ negate e'
where n' = fromInteger n :: a
e' = fromInteger e :: a
convert v = def v % 1
instance Convert Integer where
convert (Number n e) = int n e
convert v = def v
toJSON = flip Number 1
instance Convert Int where
convert (Number n e) = fromInteger $ int n e
convert v = def v
toJSON = flip Number 1 . toInteger
instance Convert Int8 where
convert (Number n e) = fromInteger $ int n e
convert v = def v
toJSON = flip Number 1 . toInteger
instance Convert Int16 where
convert (Number n e) = fromInteger $ int n e
convert v = def v
toJSON = flip Number 1 . toInteger
instance Convert Int32 where
convert (Number n e) = fromInteger $ int n e
convert v = def v
toJSON = flip Number 1 . toInteger
instance Convert Int64 where
convert (Number n e) = fromInteger $ int n e
convert v = def v
toJSON = flip Number 1 . toInteger
int :: Integral a => a -> a -> a
int n e
| e >= 0 = n * 10 ^ e
| otherwise = n `quot` 10 ^ negate e
def :: (Read a, Num a) => Value -> a
def True = 1
def False = 0
def Null = 0
def (String s) = let v = reads s in case v of ((n, _):_) -> n; _ -> 0
def (Array _) = 0
def (Object _) = 0
def _ = undefined