2023-05-19 01:06:39 +02:00
|
|
|
module App.IPC (toIPC, fromIPC) where
|
|
|
|
|
2023-05-20 00:48:49 +02:00
|
|
|
import Prelude (bind, discard, ($), (>>>))
|
2023-05-19 01:06:39 +02:00
|
|
|
|
|
|
|
import Effect (Effect)
|
2023-05-20 00:48:49 +02:00
|
|
|
import Effect.Class (liftEffect)
|
2023-05-19 01:06:39 +02:00
|
|
|
|
2023-05-20 00:48:49 +02:00
|
|
|
import Data.UInt (fromInt)
|
2023-05-19 23:43:44 +02:00
|
|
|
import Data.ArrayBuffer.ArrayBuffer as ArrayBuffer
|
2023-05-20 00:48:49 +02:00
|
|
|
import Data.ArrayBuffer.Types (ArrayBuffer, DataView)
|
2023-05-19 23:43:44 +02:00
|
|
|
import Data.ArrayBuffer.Builder as Builder
|
|
|
|
|
|
|
|
import Data.ArrayBuffer.Cast as Cast
|
|
|
|
|
|
|
|
import Control.Monad.Trans.Class (lift)
|
2023-05-19 23:50:24 +02:00
|
|
|
import Control.Monad.Except (ExceptT(ExceptT), withExceptT)
|
2023-05-19 23:43:44 +02:00
|
|
|
import Data.ArrayBuffer.Typed as Typed
|
|
|
|
import Data.ArrayBuffer.DataView as DataView
|
|
|
|
import Parsing.DataView as Parsing.DataView
|
2023-05-19 23:50:24 +02:00
|
|
|
import Parsing as Parsing
|
2023-05-20 00:48:49 +02:00
|
|
|
import Parsing (ParseError, ParserT, runParserT)
|
2023-05-19 01:06:39 +02:00
|
|
|
|
2023-05-19 23:43:44 +02:00
|
|
|
import Web.Encoding.TextEncoder as TextEncoder
|
|
|
|
import Web.Encoding.TextDecoder as TextDecoder
|
|
|
|
import Web.Encoding.UtfLabel as UtfLabel
|
2023-05-19 01:06:39 +02:00
|
|
|
|
2023-05-20 00:48:49 +02:00
|
|
|
import Data.Either (Either)
|
2023-05-19 23:50:24 +02:00
|
|
|
import Effect.Exception as Exception
|
2023-05-19 01:06:39 +02:00
|
|
|
|
2023-05-19 23:43:44 +02:00
|
|
|
utf8ToArrayBuffer :: String -> Effect ArrayBuffer
|
|
|
|
utf8ToArrayBuffer s = Builder.execPutM do
|
|
|
|
textEncoder <- liftEffect TextEncoder.new
|
|
|
|
let stringbuf = Typed.buffer $ TextEncoder.encode s textEncoder
|
2023-05-19 01:06:39 +02:00
|
|
|
-- Put a 32-bit big-endian length for the utf8 string, in bytes.
|
2023-05-19 23:43:44 +02:00
|
|
|
Builder.putUint32be $ fromInt $ ArrayBuffer.byteLength stringbuf
|
|
|
|
Builder.putArrayBuffer stringbuf
|
2023-05-19 01:06:39 +02:00
|
|
|
|
|
|
|
toIPC :: String -> Effect ArrayBuffer
|
2023-05-19 23:43:44 +02:00
|
|
|
toIPC = utf8ToArrayBuffer
|
2023-05-19 01:06:39 +02:00
|
|
|
|
2023-05-20 00:31:01 +02:00
|
|
|
fromIPC :: ArrayBuffer -> Effect (Either ParseError String)
|
|
|
|
fromIPC = arrayBufferToUtf8
|
2023-05-19 23:43:44 +02:00
|
|
|
|
2023-05-20 00:36:17 +02:00
|
|
|
-- TODO: this code doesn't verify the actual length of the message.
|
|
|
|
-- An inconsistent length would be an error sign, message should be discarded
|
|
|
|
-- and the connection should be closed.
|
2023-05-19 23:43:44 +02:00
|
|
|
arrayBufferToUtf8 :: ArrayBuffer -> Effect (Either ParseError String)
|
|
|
|
arrayBufferToUtf8 arrayBuffer = do
|
|
|
|
textDecoder <- TextDecoder.new UtfLabel.utf8
|
|
|
|
let dataView = DataView.whole arrayBuffer
|
|
|
|
runParserT dataView do
|
|
|
|
-- First parse a 32-bit big-endian length prefix for the length
|
|
|
|
-- of the UTF-8 string in bytes.
|
|
|
|
length <- Parsing.DataView.anyInt32be
|
|
|
|
stringview <- Parsing.DataView.takeN length
|
|
|
|
stringarray <- lift $ liftEffect $ Cast.toUint8Array stringview
|
|
|
|
hoistEffectParserT $ TextDecoder.decode stringarray textDecoder
|
|
|
|
|
|
|
|
hoistEffectParserT
|
|
|
|
:: forall a
|
|
|
|
. Effect a
|
|
|
|
-> ParserT DataView Effect a
|
|
|
|
hoistEffectParserT
|
|
|
|
= Exception.try
|
|
|
|
>>> ExceptT
|
|
|
|
>>> withExceptT Exception.message
|
|
|
|
>>> Parsing.liftExceptT
|