{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, FlexibleInstances, OverloadedStrings, TupleSections, LambdaCase #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module GHCJS.Marshal ( FromJSVal(..) , ToJSVal(..) , toJSVal_aeson , toJSVal_pure ) where import Control.Monad (join) import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT) import qualified Data.Aeson as AE import Data.Int (Int8, Int16, Int32) import Data.Text (Text) import Data.Word (Word8, Word16, Word32, Word) import GHC.Prim import Language.Javascript.JSaddle.Types (JSM, JSVal, SomeJSArray(..), ghcjsPure) import Language.Javascript.JSaddle.Native.Internal (valueToJSONValue, jsonValueToValue, valueToNumber) import GHCJS.Types (JSString, isUndefined, isNull) import GHCJS.Foreign.Internal (isTruthy) import GHCJS.Marshal.Pure () import JavaScript.Array (fromListIO) import qualified JavaScript.Array as A (read) import GHCJS.Marshal.Internal instance FromJSVal JSVal where fromJSValUnchecked x = return x {-# INLINE fromJSValUnchecked #-} fromJSVal = return . Just {-# INLINE fromJSVal #-} instance FromJSVal () where fromJSValUnchecked = fromJSValUnchecked_pure {-# INLINE fromJSValUnchecked #-} fromJSVal = fromJSVal_pure -- {-# INLINE fromJSVal #-} instance FromJSVal Bool where fromJSValUnchecked = ghcjsPure . isTruthy {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap Just . ghcjsPure . isTruthy {-# INLINE fromJSVal #-} instance FromJSVal Int where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Int8 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Int16 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Int32 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Word where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Word8 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Word16 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Word32 where fromJSValUnchecked = fmap round . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . round) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Float where fromJSValUnchecked = fmap realToFrac . valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap (Just . realToFrac) . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal Double where fromJSValUnchecked = valueToNumber {-# INLINE fromJSValUnchecked #-} fromJSVal = fmap Just . valueToNumber {-# INLINE fromJSVal #-} instance FromJSVal AE.Value where fromJSVal r = Just <$> valueToJSONValue r {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b) => FromJSVal (a,b) where fromJSVal r = runMaybeT $ (,) <$> jf r 0 <*> jf r 1 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c) => FromJSVal (a,b,c) where fromJSVal r = runMaybeT $ (,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d) => FromJSVal (a,b,c,d) where fromJSVal r = runMaybeT $ (,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e) => FromJSVal (a,b,c,d,e) where fromJSVal r = runMaybeT $ (,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f) => FromJSVal (a,b,c,d,e,f) where fromJSVal r = runMaybeT $ (,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f, FromJSVal g) => FromJSVal (a,b,c,d,e,f,g) where fromJSVal r = runMaybeT $ (,,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5 <*> jf r 6 {-# INLINE fromJSVal #-} instance (FromJSVal a, FromJSVal b, FromJSVal c, FromJSVal d, FromJSVal e, FromJSVal f, FromJSVal g, FromJSVal h) => FromJSVal (a,b,c,d,e,f,g,h) where fromJSVal r = runMaybeT $ (,,,,,,,) <$> jf r 0 <*> jf r 1 <*> jf r 2 <*> jf r 3 <*> jf r 4 <*> jf r 5 <*> jf r 6 <*> jf r 7 {-# INLINE fromJSVal #-} jf :: FromJSVal a => JSVal -> Int -> MaybeT JSM a jf r n = MaybeT $ do r' <- A.read n (SomeJSArray r) ghcjsPure (isUndefined r) >>= \case True -> return Nothing False -> fromJSVal r' instance (ToJSVal a, ToJSVal b) => ToJSVal (a,b) where toJSVal (a,b) = join $ arr2 <$> toJSVal a <*> toJSVal b {-# INLINE toJSVal #-} instance (ToJSVal a, ToJSVal b, ToJSVal c) => ToJSVal (a,b,c) where toJSVal (a,b,c) = join $ arr3 <$> toJSVal a <*> toJSVal b <*> toJSVal c {-# INLINE toJSVal #-} instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d) => ToJSVal (a,b,c,d) where toJSVal (a,b,c,d) = join $ arr4 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d {-# INLINE toJSVal #-} instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e) => ToJSVal (a,b,c,d,e) where toJSVal (a,b,c,d,e) = join $ arr5 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e {-# INLINE toJSVal #-} instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e, ToJSVal f) => ToJSVal (a,b,c,d,e,f) where toJSVal (a,b,c,d,e,f) = join $ arr6 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e <*> toJSVal f {-# INLINE toJSVal #-} instance (ToJSVal a, ToJSVal b, ToJSVal c, ToJSVal d, ToJSVal e, ToJSVal f, ToJSVal g) => ToJSVal (a,b,c,d,e,f,g) where toJSVal (a,b,c,d,e,f,g) = join $ arr7 <$> toJSVal a <*> toJSVal b <*> toJSVal c <*> toJSVal d <*> toJSVal e <*> toJSVal f <*> toJSVal g {-# INLINE toJSVal #-} arr2 :: JSVal -> JSVal -> JSM JSVal arr2 a b = coerce <$> fromListIO [a,b] arr3 :: JSVal -> JSVal -> JSVal -> JSM JSVal arr3 a b c = coerce <$> fromListIO [a,b,c] arr4 :: JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal arr4 a b c d = coerce <$> fromListIO [a,b,c,d] arr5 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal arr5 a b c d e = coerce <$> fromListIO [a,b,c,d,e] arr6 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal arr6 a b c d e f = coerce <$> fromListIO [a,b,c,d,e,f] arr7 :: JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSVal -> JSM JSVal arr7 a b c d e f g = coerce <$> fromListIO [a,b,c,d,e,f,g] toJSVal_aeson :: AE.ToJSON a => a -> JSM JSVal toJSVal_aeson = jsonValueToValue . AE.toJSON