-- |Implementations shared between multiple types.
module Cryptsy.API.Public.Types.Internal where

-- aeson
import Data.Aeson (Array, Value(Array, Null), withText)
import Data.Aeson.Types (Parser, typeMismatch)

-- base
import Data.Monoid (Monoid(mempty))

-- text
import Data.Text (unpack)

-- |Convert one "parser" type to another.
readsToParser :: String -> ReadS a -> Value -> Parser a
readsToParser name reader = withText name $ trans . reader . unpack
 where
	trans []        = fail "No parse."
	trans [(v, "")] = return v
	trans [(_, _ )] = fail "Incomplete parse."
	trans _         = fail "Ambiguous parse."
{-# INLINABLE readsToParser #-}

-- |Like 'Data.Aeson.withArray' but also accepting JSON nulls as mempty.
withNullableArray :: Monoid a
                  => String -> (Array -> Parser a) -> Value -> Parser a
withNullableArray _    parseArray (Array v) = parseArray v
withNullableArray _    _           Null     = return mempty
withNullableArray name _           v        = typeMismatch name v
{-# INLINABLE withNullableArray #-}