Z-MessagePack 0.1.0.0 → 0.3.0.0
raw patch · 7 files changed
+611/−294 lines, 7 filesdep ~Z-Datadep ~Z-IOdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: Z-Data, Z-IO, base
API changes (from Hackage documentation)
- Z.Data.MessagePack: decodeChunks' :: (MessagePack a, Monad m) => m Bytes -> Bytes -> m (Either DecodeError a)
- Z.Data.MessagePack: infixl 9 <?>
- Z.Data.MessagePack.Base: decodeChunks' :: (MessagePack a, Monad m) => m Bytes -> Bytes -> m (Either DecodeError a)
- Z.Data.MessagePack.Base: infixl 9 <?>
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack (f a), Z.Data.MessagePack.Base.MessagePack (g a), Z.Data.MessagePack.Base.MessagePack a) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Sum.Sum f g a)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b) => Z.Data.MessagePack.Base.MessagePack (Data.Either.Either a b)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b) => Z.Data.MessagePack.Base.MessagePack (a, b)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c) => Z.Data.MessagePack.Base.MessagePack (a, b, c)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e, Z.Data.MessagePack.Base.MessagePack f) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e, f)
- Z.Data.MessagePack.Base: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e, Z.Data.MessagePack.Base.MessagePack f, Z.Data.MessagePack.Base.MessagePack g) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e, f, g)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.CalendarDiffDays.CalendarDiffDays
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.Days.Day
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.Week.DayOfWeek
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.DiffTime.DiffTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.SystemTime.SystemTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.UTCTime.UTCTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.LocalTime.LocalTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Data.Version.Version
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CBool
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CChar
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CClock
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CDouble
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CFloat
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CInt
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CIntMax
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CIntPtr
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CLLong
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CLong
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CPtrdiff
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSChar
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSUSeconds
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CShort
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSigAtomic
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSize
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CTime
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUChar
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUInt
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUIntMax
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUIntPtr
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CULLong
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CULong
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUSeconds
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUShort
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CWchar
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack GHC.IO.Exception.ExitCode
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Identity.Identity a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Monoid.First a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Monoid.Last a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.First a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Internal.Dual a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Last a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Max a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Min a)
- Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.WrappedMonoid a)
- Z.Data.MessagePack.Base: instance forall k (f :: k -> *) (a :: k) (g :: k -> *). (Z.Data.MessagePack.Base.MessagePack (f a), Z.Data.MessagePack.Base.MessagePack (g a)) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Product.Product f g a)
- Z.Data.MessagePack.Base: instance forall k a (b :: k). Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Const.Const a b)
- Z.Data.MessagePack.Base: instance forall k b (a :: k). Z.Data.MessagePack.Base.MessagePack b => Z.Data.MessagePack.Base.MessagePack (Data.Tagged.Tagged a b)
- Z.Data.MessagePack.Base: instance forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1). Z.Data.MessagePack.Base.MessagePack (f (g a)) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Compose.Compose f g a)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack (f a), Z.Data.MessagePack.Base.MessagePack (g a), Z.Data.MessagePack.Base.MessagePack a) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Sum.Sum f g a)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b) => Z.Data.MessagePack.Base.MessagePack (Data.Either.Either a b)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b) => Z.Data.MessagePack.Base.MessagePack (a, b)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c) => Z.Data.MessagePack.Base.MessagePack (a, b, c)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e, Z.Data.MessagePack.Base.MessagePack f) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e, f)
+ Z.Data.MessagePack: instance (Z.Data.MessagePack.Base.MessagePack a, Z.Data.MessagePack.Base.MessagePack b, Z.Data.MessagePack.Base.MessagePack c, Z.Data.MessagePack.Base.MessagePack d, Z.Data.MessagePack.Base.MessagePack e, Z.Data.MessagePack.Base.MessagePack f, Z.Data.MessagePack.Base.MessagePack g) => Z.Data.MessagePack.Base.MessagePack (a, b, c, d, e, f, g)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.CalendarDiffDays.CalendarDiffDays
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.Days.Day
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Calendar.Week.DayOfWeek
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.DiffTime.DiffTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.SystemTime.SystemTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.Clock.Internal.UTCTime.UTCTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.CalendarDiffTime.CalendarDiffTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.LocalTime.LocalTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Time.LocalTime.Internal.ZonedTime.ZonedTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Data.Version.Version
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CBool
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CChar
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CClock
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CDouble
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CFloat
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CInt
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CIntMax
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CIntPtr
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CLLong
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CLong
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CPtrdiff
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSChar
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSUSeconds
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CShort
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSigAtomic
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CSize
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CTime
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUChar
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUInt
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUIntMax
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUIntPtr
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CULLong
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CULong
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUSeconds
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CUShort
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack Foreign.C.Types.CWchar
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack GHC.IO.Exception.ExitCode
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Identity.Identity a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Monoid.First a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Monoid.Last a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.First a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Internal.Dual a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Last a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Max a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.Min a)
+ Z.Data.MessagePack: instance Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Semigroup.WrappedMonoid a)
+ Z.Data.MessagePack: instance forall k (f :: k -> *) (a :: k) (g :: k -> *). (Z.Data.MessagePack.Base.MessagePack (f a), Z.Data.MessagePack.Base.MessagePack (g a)) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Product.Product f g a)
+ Z.Data.MessagePack: instance forall k a (b :: k). Z.Data.MessagePack.Base.MessagePack a => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Const.Const a b)
+ Z.Data.MessagePack: instance forall k b (a :: k). Z.Data.MessagePack.Base.MessagePack b => Z.Data.MessagePack.Base.MessagePack (Data.Tagged.Tagged a b)
+ Z.Data.MessagePack: instance forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1). Z.Data.MessagePack.Base.MessagePack (f (g a)) => Z.Data.MessagePack.Base.MessagePack (Data.Functor.Compose.Compose f g a)
+ Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack GHC.Base.String
+ Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Z.Data.CBytes.CBytes
+ Z.Data.MessagePack.Base: instance Z.Data.MessagePack.Base.MessagePack Z.Data.Vector.Base.Bytes
+ Z.Data.MessagePack.Base: type ParseChunks (m :: Type -> Type) chunk err x = m chunk -> chunk -> m (chunk, Either err x)
+ Z.Data.MessagePack.Base: withBoundedScientific :: Text -> (Scientific -> Converter a) -> Value -> Converter a
+ Z.Data.MessagePack.Base: withSystemTime :: Text -> (SystemTime -> Converter a) -> Value -> Converter a
+ Z.IO.RPC.MessagePack: Client :: Counter -> Counter -> BufferedInput -> BufferedOutput -> Client
+ Z.IO.RPC.MessagePack: RPCException :: Value -> CallStack -> RPCException
+ Z.IO.RPC.MessagePack: [CallHandler] :: (MessagePack req, MessagePack res) => (req -> IO res) -> ServerHandler
+ Z.IO.RPC.MessagePack: [NotifyHandler] :: MessagePack req => (req -> IO ()) -> ServerHandler
+ Z.IO.RPC.MessagePack: [_clientBufferedInput] :: Client -> BufferedInput
+ Z.IO.RPC.MessagePack: [_clientBufferedOutput] :: Client -> BufferedOutput
+ Z.IO.RPC.MessagePack: [_clientPipelineReqNum] :: Client -> Counter
+ Z.IO.RPC.MessagePack: [_clientSeqRef] :: Client -> Counter
+ Z.IO.RPC.MessagePack: call :: (MessagePack req, MessagePack res) => Client -> Text -> req -> IO res
+ Z.IO.RPC.MessagePack: callPipeline :: HasCallStack => MessagePack req => Client -> Text -> req -> IO PipelineId
+ Z.IO.RPC.MessagePack: data Client
+ Z.IO.RPC.MessagePack: data RPCException
+ Z.IO.RPC.MessagePack: data ServerHandler
+ Z.IO.RPC.MessagePack: execPipeline :: HasCallStack => Client -> IO PipelineResult
+ Z.IO.RPC.MessagePack: fetchPipeline :: HasCallStack => MessagePack res => PipelineId -> PipelineResult -> IO res
+ Z.IO.RPC.MessagePack: instance GHC.Exception.Type.Exception Z.IO.RPC.MessagePack.RPCException
+ Z.IO.RPC.MessagePack: instance GHC.Show.Show Z.IO.RPC.MessagePack.RPCException
+ Z.IO.RPC.MessagePack: notify :: MessagePack req => Client -> Text -> req -> IO ()
+ Z.IO.RPC.MessagePack: notifyPipeline :: HasCallStack => MessagePack req => Client -> Text -> req -> IO ()
+ Z.IO.RPC.MessagePack: rpcClient :: (Input dev, Output dev) => dev -> IO Client
+ Z.IO.RPC.MessagePack: rpcClient' :: (Input i, Output o) => i -> o -> Int -> Int -> IO Client
+ Z.IO.RPC.MessagePack: serveRPC :: ServerLoop -> ServerService -> IO ()
+ Z.IO.RPC.MessagePack: serveRPC' :: ServerLoop -> Int -> Int -> ServerService -> IO ()
+ Z.IO.RPC.MessagePack: simpleRouter :: [(Text, ServerHandler)] -> ServerService
+ Z.IO.RPC.MessagePack: type PipelineId = Int
+ Z.IO.RPC.MessagePack: type PipelineResult = FlatIntMap Value
+ Z.IO.RPC.MessagePack: type ServerLoop = (UVStream -> IO ()) -> IO ()
+ Z.IO.RPC.MessagePack: type ServerService = Text -> Maybe ServerHandler
Files
- CHANGELOG.md +5/−2
- Z-MessagePack.cabal +6/−4
- Z/Data/MessagePack.hs +255/−10
- Z/Data/MessagePack/Base.hs +40/−244
- Z/Data/MessagePack/Builder.hs +32/−32
- Z/Data/MessagePack/Value.hs +1/−2
- Z/IO/RPC/MessagePack.hs +272/−0
CHANGELOG.md view
@@ -1,5 +1,8 @@ # Revision history for Z-Redis -## 0.1.0.0 -- YYYY-mm-dd+## 0.3.0.0 -- 2021-02-25 -* First version. Released on an unsuspecting world.+* Add `Z.IO.RPC.MessagePack` module.+* Move some instances to `Z.Data.MessagePack` to make package buildable under constrained memory.+* Remove `decodeChunks'`.+* Change `Data.Version.Version`'s instance to use array.
Z-MessagePack.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: Z-MessagePack-version: 0.1.0.0+version: 0.3.0.0 synopsis: MessagePack description: MessagePack binary serialization format. license: BSD3@@ -20,10 +20,11 @@ Z.Data.MessagePack.Base Z.Data.MessagePack.Builder Z.Data.MessagePack.Value+ Z.IO.RPC.MessagePack -- other-modules: -- other-extensions:- build-depends: base >=4.14 && <4.15+ build-depends: base >= 4.12 && <5 , deepseq >= 1.4 && < 1.5 , primitive >= 0.7.1 && < 0.7.2 , QuickCheck >= 2.10@@ -34,8 +35,8 @@ , integer-gmp == 1.* , tagged == 0.8.* , time >= 1.9 && < 2.0- , Z-Data == 0.4.*- , Z-IO == 0.4.*+ , Z-Data == 0.6.*+ , Z-IO == 0.6.* -- hs-source-dirs: default-language: Haskell2010@@ -52,6 +53,7 @@ ExistentialQuantification FlexibleContexts FlexibleInstances+ GADTs GeneralizedNewtypeDeriving KindSignatures MagicHash
Z/Data/MessagePack.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+ {-| Module : Z.Data.MessagePack Description : Fast MessagePack serialization/deserialization@@ -7,7 +9,7 @@ Stability : experimental Portability : non-portable -This module provides an interface similar to 'Z.Data.JSON', to work with MessagePack binary format.+This module provides an interface similar to "Z.Data.JSON", to work with MessagePack binary format. * @Maybe a@ convert to 'Nil' in 'Nothing' case, and @a@ in 'Just' case. * Use 'Int64'(signed) or 'Word64'(unsigned) type to marshall int type format, smaller types will sliently truncate when overflow.@@ -43,7 +45,7 @@ deriving (Show, Generic) deriving anyclass (MessagePack.MessagePack) -> MessagePack.encode Person{ name="Alice", age=16 }+> MessagePack.encode Person{ name=\"Alice\", age=16 } > [130,164,110,97,109,101,165,65,108,105,99,101,163,97,103,101,16] @ @@ -56,8 +58,7 @@ > 2kvs 4bytes 5bytes 3bytes -This property makes it suitable for passing data across language boundary, e.g. from a static typed language to a dynamic one,-at the cost of a lower space efficiency(i.e. type tag and field label).+This property makes it suitable for passing data across language boundary, e.g. from a static typed language to a dynamic one, at the cost of a lower space efficiency(i.e. type tag and field label). -} @@ -66,7 +67,7 @@ MessagePack(..), Value(..), defaultSettings, Settings(..), JSON.snakeCase, JSON.trainCase -- * Encode & Decode , readMessagePackFile, writeMessagePackFile- , decode, decode', decodeChunks, decodeChunks', encode, encodeChunks+ , decode, decode', decodeChunks, encode, encodeChunks , DecodeError, ParseError -- * parse into MessagePack Value , parseValue, parseValue', parseValueChunks, parseValueChunks'@@ -82,16 +83,260 @@ , (.=), object, (.!), object', KVItem ) where -import Z.Data.MessagePack.Base-import qualified Z.Data.JSON as JSON-import Z.Data.CBytes (CBytes)-import Z.IO+import Data.Char+import Data.Functor.Compose+import Data.Functor.Const+import Data.Functor.Identity+import Data.Functor.Product+import Data.Functor.Sum+import qualified Data.Monoid as Monoid+import Data.Proxy (Proxy (..))+import Data.Scientific (Scientific, toBoundedInteger)+import qualified Data.Semigroup as Semigroup+import Data.Tagged (Tagged (..))+import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime,+ TimeOfDay, UTCTime, ZonedTime)+import Data.Time.Calendar (CalendarDiffDays (..), DayOfWeek (..))+import Data.Time.LocalTime (CalendarDiffTime (..))+import Data.Time.Clock.System (SystemTime (..), utcToSystemTime, systemToUTCTime)+import Data.Version (Version(versionBranch), makeVersion)+import Foreign.C.Types+import System.Exit (ExitCode(..))+import qualified Z.Data.Builder as B+import Z.Data.MessagePack.Base+import qualified Z.Data.MessagePack.Builder as MB+import qualified Z.Data.JSON as JSON+import qualified Z.Data.Parser as P+import qualified Z.Data.Text as T+import Z.Data.CBytes (CBytes)+import Z.IO import qualified Z.IO.FileSystem as FS -- | Decode a 'MessagePack' instance from file. readMessagePackFile :: (HasCallStack, MessagePack a) => CBytes -> IO a-readMessagePackFile p = unwrap . decode' =<< FS.readFile p+readMessagePackFile p = unwrap "EPARSE" . decode' =<< FS.readFile p -- | Encode a 'MessagePack' instance to file. writeMessagePackFile :: (HasCallStack, MessagePack a) => CBytes -> a -> IO () writeMessagePackFile p x = FS.writeFile p (encode x)++--------------------------------------------------------------------------------++instance MessagePack ExitCode where+ {-# INLINE fromValue #-}+ fromValue (Str "ExitSuccess") = return ExitSuccess+ fromValue (Int x) = return (ExitFailure (fromIntegral x))+ fromValue _ = fail' "converting ExitCode failed, expected a string or number"++ {-# INLINE toValue #-}+ toValue ExitSuccess = Str "ExitSuccess"+ toValue (ExitFailure n) = Int (fromIntegral n)++ {-# INLINE encodeMessagePack #-}+ encodeMessagePack ExitSuccess = MB.str "ExitSuccess"+ encodeMessagePack (ExitFailure n) = B.int n++-- | Only round trip 'versionBranch' as MessagePack array.+instance MessagePack Version where+ {-# INLINE fromValue #-}+ fromValue v = makeVersion <$> fromValue v+ {-# INLINE toValue #-}+ toValue = toValue . versionBranch+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = encodeMessagePack . versionBranch++--------------------------------------------------------------------------------++-- | MessagePack extension type @Ext 0xFF@+instance MessagePack UTCTime where+ {-# INLINE fromValue #-}+ fromValue = withSystemTime "UTCTime" $ pure . systemToUTCTime+ {-# INLINE toValue #-}+ toValue t = let (MkSystemTime s ns) = utcToSystemTime t in MB.timestampValue s (fromIntegral ns)+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack t = let (MkSystemTime s ns) = utcToSystemTime t in MB.timestamp s (fromIntegral ns)++-- | MessagePack extension type @Ext 0xFF@+instance MessagePack SystemTime where+ {-# INLINE fromValue #-}+ fromValue = withSystemTime "UTCTime" $ pure+ {-# INLINE toValue #-}+ toValue (MkSystemTime s ns) = MB.timestampValue s (fromIntegral ns)+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack (MkSystemTime s ns) = MB.timestamp s (fromIntegral ns)++-- | @YYYY-MM-DDTHH:MM:SS.SSSZ@+instance MessagePack ZonedTime where+ {-# INLINE fromValue #-}+ fromValue = withStr "ZonedTime" $ \ t ->+ case P.parse' (P.zonedTime <* P.endOfInput) (T.getUTF8Bytes t) of+ Left err -> fail' $ "could not parse date as ZonedTime: " <> T.toText err+ Right r -> return r+ {-# INLINE toValue #-}+ toValue t = Str (B.unsafeBuildText (B.zonedTime t))+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack t = MB.str (B.unsafeBuildText (B.zonedTime t))++-- | @YYYY-MM-DD@+instance MessagePack Day where+ {-# INLINE fromValue #-}+ fromValue = withStr "Day" $ \ t ->+ case P.parse' (P.day <* P.endOfInput) (T.getUTF8Bytes t) of+ Left err -> fail' $ "could not parse date as Day: " <> T.toText err+ Right r -> return r+ {-# INLINE toValue #-}+ toValue t = Str (B.unsafeBuildText (B.day t))+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack t = MB.str (B.unsafeBuildText (B.day t))++-- | @YYYY-MM-DDTHH:MM:SS.SSSZ@+instance MessagePack LocalTime where+ {-# INLINE fromValue #-}+ fromValue = withStr "LocalTime" $ \ t ->+ case P.parse' (P.localTime <* P.endOfInput) (T.getUTF8Bytes t) of+ Left err -> fail' $ "could not parse date as LocalTime: " <> T.toText err+ Right r -> return r+ {-# INLINE toValue #-}+ toValue t = Str (B.unsafeBuildText (B.localTime t))+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack t = MB.str (B.unsafeBuildText (B.localTime t))++-- | @HH:MM:SS.SSS@+instance MessagePack TimeOfDay where+ {-# INLINE fromValue #-}+ fromValue = withStr "TimeOfDay" $ \ t ->+ case P.parse' (P.timeOfDay <* P.endOfInput) (T.getUTF8Bytes t) of+ Left err -> fail' $ "could not parse time as TimeOfDay: " <> T.toText err+ Right r -> return r+ {-# INLINE toValue #-}+ toValue t = Str (B.unsafeBuildText (B.timeOfDay t))+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack t = MB.str (B.unsafeBuildText (B.timeOfDay t))++-- | This instance includes a bounds check to prevent maliciously+-- large inputs to fill up the memory of the target system. You can+-- newtype 'NominalDiffTime' and provide your own instance using+-- 'withScientific' if you want to allow larger inputs.+instance MessagePack NominalDiffTime where+ {-# INLINE fromValue #-}+ fromValue = withBoundedScientific "NominalDiffTime" $ pure . realToFrac+ {-# INLINE toValue #-}+ toValue = toValue @Scientific . realToFrac+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = encodeMessagePack @Scientific . realToFrac++-- | This instance includes a bounds check to prevent maliciously+-- large inputs to fill up the memory of the target system. You can+-- newtype 'DiffTime' and provide your own instance using+-- 'withScientific' if you want to allow larger inputs.+instance MessagePack DiffTime where+ {-# INLINE fromValue #-}+ fromValue = withBoundedScientific "DiffTime" $ pure . realToFrac+ {-# INLINE toValue #-}+ toValue = toValue @Scientific . realToFrac+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = encodeMessagePack @Scientific . realToFrac++instance MessagePack CalendarDiffTime where+ {-# INLINE fromValue #-}+ fromValue = withFlatMapR "CalendarDiffTime" $ \ v ->+ CalendarDiffTime <$> v .: "months" <*> v .: "time"+ {-# INLINE toValue #-}+ toValue (CalendarDiffTime m nt) = object [ "months" .= m , "time" .= nt ]+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack (CalendarDiffTime m nt) = object' ("months" .! m <> "time" .! nt)++instance MessagePack CalendarDiffDays where+ {-# INLINE fromValue #-}+ fromValue = withFlatMapR "CalendarDiffDays" $ \ v ->+ CalendarDiffDays <$> v .: "months" <*> v .: "days"+ {-# INLINE toValue #-}+ toValue (CalendarDiffDays m d) = object ["months" .= m, "days" .= d]+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack (CalendarDiffDays m d) = object' ("months" .! m <> "days" .! d)++instance MessagePack DayOfWeek where+ {-# INLINE fromValue #-}+ fromValue (Str "monday" ) = pure Monday+ fromValue (Str "tuesday" ) = pure Tuesday+ fromValue (Str "wednesday") = pure Wednesday+ fromValue (Str "thursday" ) = pure Thursday+ fromValue (Str "friday" ) = pure Friday+ fromValue (Str "saturday" ) = pure Saturday+ fromValue (Str "sunday" ) = pure Sunday+ fromValue (Str _ ) = fail' "converting DayOfWeek failed, value should be one of weekdays"+ fromValue v = typeMismatch "DayOfWeek" "String" v+ {-# INLINE toValue #-}+ toValue Monday = Str "monday"+ toValue Tuesday = Str "tuesday"+ toValue Wednesday = Str "wednesday"+ toValue Thursday = Str "thursday"+ toValue Friday = Str "friday"+ toValue Saturday = Str "saturday"+ toValue Sunday = Str "sunday"+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack Monday = MB.str "monday"+ encodeMessagePack Tuesday = MB.str "tuesday"+ encodeMessagePack Wednesday = MB.str "wednesday"+ encodeMessagePack Thursday = MB.str "thursday"+ encodeMessagePack Friday = MB.str "friday"+ encodeMessagePack Saturday = MB.str "saturday"+ encodeMessagePack Sunday = MB.str "sunday"+++--------------------------------------------------------------------------------++deriving newtype instance MessagePack (f (g a)) => MessagePack (Compose f g a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.Min a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.Max a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.First a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.Last a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.WrappedMonoid a)+deriving newtype instance MessagePack a => MessagePack (Semigroup.Dual a)+deriving newtype instance MessagePack a => MessagePack (Monoid.First a)+deriving newtype instance MessagePack a => MessagePack (Monoid.Last a)+deriving newtype instance MessagePack a => MessagePack (Identity a)+deriving newtype instance MessagePack a => MessagePack (Const a b)+deriving newtype instance MessagePack b => MessagePack (Tagged a b)++--------------------------------------------------------------------------------++deriving newtype instance MessagePack CChar+deriving newtype instance MessagePack CSChar+deriving newtype instance MessagePack CUChar+deriving newtype instance MessagePack CShort+deriving newtype instance MessagePack CUShort+deriving newtype instance MessagePack CInt+deriving newtype instance MessagePack CUInt+deriving newtype instance MessagePack CLong+deriving newtype instance MessagePack CULong+deriving newtype instance MessagePack CPtrdiff+deriving newtype instance MessagePack CSize+deriving newtype instance MessagePack CWchar+deriving newtype instance MessagePack CSigAtomic+deriving newtype instance MessagePack CLLong+deriving newtype instance MessagePack CULLong+deriving newtype instance MessagePack CBool+deriving newtype instance MessagePack CIntPtr+deriving newtype instance MessagePack CUIntPtr+deriving newtype instance MessagePack CIntMax+deriving newtype instance MessagePack CUIntMax+deriving newtype instance MessagePack CClock+deriving newtype instance MessagePack CTime+deriving newtype instance MessagePack CUSeconds+deriving newtype instance MessagePack CSUSeconds+deriving newtype instance MessagePack CFloat+deriving newtype instance MessagePack CDouble++--------------------------------------------------------------------------------++deriving anyclass instance (MessagePack (f a), MessagePack (g a), MessagePack a) => MessagePack (Sum f g a)+deriving anyclass instance (MessagePack a, MessagePack b) => MessagePack (Either a b)+deriving anyclass instance (MessagePack (f a), MessagePack (g a)) => MessagePack (Product f g a)++deriving anyclass instance (MessagePack a, MessagePack b) => MessagePack (a, b)+deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c) => MessagePack (a, b, c)+deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d) => MessagePack (a, b, c, d)+deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e) => MessagePack (a, b, c, d, e)+deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e, MessagePack f) => MessagePack (a, b, c, d, e, f)+deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e, MessagePack f, MessagePack g) => MessagePack (a, b, c, d, e, f, g)
Z/Data/MessagePack/Base.hs view
@@ -7,7 +7,7 @@ Stability : experimental Portability : non-portable -This module provides 'Converter' to convert 'Value' to haskell data types, and various tools to help user define 'MessagePack' instance.+This module provides various tools to help user define 'MessagePack' instance, please import `Z.Data.MessagePack` to get more instances. -} @@ -15,8 +15,8 @@ ( -- * MessagePack Class MessagePack(..), Value(..), defaultSettings, Settings(..) -- * Encode & Decode- , decode, decode', decodeChunks, decodeChunks', encode, encodeChunks- , DecodeError, P.ParseError+ , decode, decode', decodeChunks, encode, encodeChunks+ , DecodeError, P.ParseError, P.ParseChunks -- * parse into MessagePack Value , MV.parseValue, MV.parseValue', MV.parseValueChunks, MV.parseValueChunks' -- * Generic FromValue, ToValue & EncodeMessagePack@@ -26,6 +26,7 @@ , PathElement(..), ConvertError(..) , typeMismatch, fromNil, withBool , withStr, withBin, withArray, withKeyValues, withFlatMap, withFlatMapR+ , withBoundedScientific, withSystemTime , (.:), (.:?), (.:!), convertField, convertFieldMaybe, convertFieldMaybe' -- * Helper for manually writing instance. , (.=), object, (.!), object', KVItem@@ -81,6 +82,7 @@ import Text.ParserCombinators.ReadP (readP_to_S) import qualified Z.Data.Array as A import qualified Z.Data.Builder as B+import qualified Z.Data.CBytes as CBytes import Z.Data.Generics.Utils import Z.Data.JSON.Converter import qualified Z.Data.MessagePack.Builder as MB@@ -155,18 +157,6 @@ Left cErr -> pure (bs', Left (Right cErr)) Right r -> pure (bs', Right r) --- | Decode MessagePack doc chunks, trailing bytes are not allowed.-decodeChunks' :: (MessagePack a, Monad m) => m V.Bytes -> V.Bytes -> m (Either DecodeError a)-{-# INLINE decodeChunks' #-}-decodeChunks' mb bs = do- mr <- P.parseChunks (MV.value <* P.endOfInput) mb bs- case mr of- (_, Left pErr) -> pure (Left (Left pErr))- (_, Right v) ->- case convertValue v of- Left cErr -> pure (Left (Right cErr))- Right r -> pure (Right r)- -- | Directly encode data to MessagePack bytes. encode :: MessagePack a => a -> V.Bytes {-# INLINE encode #-}@@ -996,6 +986,24 @@ {-# INLINE encodeMessagePack #-} encodeMessagePack = MB.array encodeMessagePack +-- | This is an INCOHERENT instance, write 'Bytes' as Bin.+instance {-# INCOHERENT #-} MessagePack V.Bytes where+ {-# INLINE fromValue #-}+ fromValue = withBin "Z.Data.Vector.Bytes" pure+ {-# INLINE toValue #-}+ toValue = Bin+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = MB.bin++-- | Write 'CBytes' as Bin not Str.+instance MessagePack CBytes.CBytes where+ {-# INLINE fromValue #-}+ fromValue = withBin "Z.Data.CBytes" (pure . CBytes.fromBytes)+ {-# INLINE toValue #-}+ toValue = Bin . CBytes.toBytes+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = MB.bin . CBytes.toBytes+ instance MessagePack a => MessagePack (V.Vector a) where {-# INLINE fromValue #-} fromValue = withArray "Z.Data.Vector.Vector"@@ -1024,6 +1032,15 @@ {-# INLINE encodeMessagePack #-} encodeMessagePack = MB.array' encodeMessagePack +-- | This is an INCOHERENT instance, encode 'String' with 'Str'.+instance {-# INCOHERENT #-} MessagePack String where+ {-# INLINE fromValue #-}+ fromValue = withStr "String" (pure . T.unpack)+ {-# INLINE toValue #-}+ toValue = Str . T.pack+ {-# INLINE encodeMessagePack #-}+ encodeMessagePack = MB.str . T.pack+ instance MessagePack a => MessagePack (NonEmpty a) where {-# INLINE fromValue #-} fromValue = withArray "NonEmpty" $ \ vs -> do@@ -1071,16 +1088,16 @@ instance MessagePack typ where \ {-# INLINE fromValue #-}; \ fromValue (Int x) = pure $! fromIntegral x; \- fromValue v = typeMismatch "##typ##" "Int" v; \+ fromValue v = typeMismatch " typ " "Int" v; \ {-# INLINE toValue #-}; toValue = Int . fromIntegral; \ {-# INLINE encodeMessagePack #-}; encodeMessagePack = MB.int . fromIntegral;-INT_MessagePack_INSTANCE(Int )-INT_MessagePack_INSTANCE(Int8 )-INT_MessagePack_INSTANCE(Int16 )-INT_MessagePack_INSTANCE(Int32 )-INT_MessagePack_INSTANCE(Int64 )-INT_MessagePack_INSTANCE(Word )-INT_MessagePack_INSTANCE(Word8 )+INT_MessagePack_INSTANCE(Int)+INT_MessagePack_INSTANCE(Int8)+INT_MessagePack_INSTANCE(Int16)+INT_MessagePack_INSTANCE(Int32)+INT_MessagePack_INSTANCE(Int64)+INT_MessagePack_INSTANCE(Word)+INT_MessagePack_INSTANCE(Word8) INT_MessagePack_INSTANCE(Word16) INT_MessagePack_INSTANCE(Word32) INT_MessagePack_INSTANCE(Word64)@@ -1152,32 +1169,6 @@ {-# INLINE encodeMessagePack #-} encodeMessagePack () = MB.arrayHeader 0 -instance MessagePack ExitCode where- {-# INLINE fromValue #-}- fromValue (Str "ExitSuccess") = return ExitSuccess- fromValue (Int x) = return (ExitFailure (fromIntegral x))- fromValue _ = fail' "converting ExitCode failed, expected a string or number"-- {-# INLINE toValue #-}- toValue ExitSuccess = Str "ExitSuccess"- toValue (ExitFailure n) = Int (fromIntegral n)-- {-# INLINE encodeMessagePack #-}- encodeMessagePack ExitSuccess = MB.str "ExitSuccess"- encodeMessagePack (ExitFailure n) = B.int n--instance MessagePack Version where- {-# INLINE fromValue #-}- fromValue = withStr "Version" (go . readP_to_S parseVersion . T.unpack)- where- go [(v,[])] = pure v- go (_ : xs) = go xs- go _ = fail "converting Version failed"- {-# INLINE toValue #-}- toValue = Str . T.pack . show- {-# INLINE encodeMessagePack #-}- encodeMessagePack = MB.str' . show- instance MessagePack a => MessagePack (Maybe a) where {-# INLINE fromValue #-} fromValue Nil = pure Nothing@@ -1213,198 +1204,3 @@ toValue = toValue @Scientific . realToFrac {-# INLINE encodeMessagePack #-} encodeMessagePack = encodeMessagePack @Scientific . realToFrac-------------------------------------------------------------------------------------- | MessagePack extension type @Ext 0xFF@-instance MessagePack UTCTime where- {-# INLINE fromValue #-}- fromValue = withSystemTime "UTCTime" $ pure . systemToUTCTime- {-# INLINE toValue #-}- toValue t = let (MkSystemTime s ns) = utcToSystemTime t in MB.timestampValue s (fromIntegral ns)- {-# INLINE encodeMessagePack #-}- encodeMessagePack t = let (MkSystemTime s ns) = utcToSystemTime t in MB.timestamp s (fromIntegral ns)---- | MessagePack extension type @Ext 0xFF@-instance MessagePack SystemTime where- {-# INLINE fromValue #-}- fromValue = withSystemTime "UTCTime" $ pure- {-# INLINE toValue #-}- toValue (MkSystemTime s ns) = MB.timestampValue s (fromIntegral ns)- {-# INLINE encodeMessagePack #-}- encodeMessagePack (MkSystemTime s ns) = MB.timestamp s (fromIntegral ns)---- | @YYYY-MM-DDTHH:MM:SS.SSSZ@-instance MessagePack ZonedTime where- {-# INLINE fromValue #-}- fromValue = withStr "ZonedTime" $ \ t ->- case P.parse' (P.zonedTime <* P.endOfInput) (T.getUTF8Bytes t) of- Left err -> fail' $ "could not parse date as ZonedTime: " <> T.toText err- Right r -> return r- {-# INLINE toValue #-}- toValue t = Str (B.unsafeBuildText (B.zonedTime t))- {-# INLINE encodeMessagePack #-}- encodeMessagePack t = MB.str (B.unsafeBuildText (B.zonedTime t))---- | @YYYY-MM-DD@-instance MessagePack Day where- {-# INLINE fromValue #-}- fromValue = withStr "Day" $ \ t ->- case P.parse' (P.day <* P.endOfInput) (T.getUTF8Bytes t) of- Left err -> fail' $ "could not parse date as Day: " <> T.toText err- Right r -> return r- {-# INLINE toValue #-}- toValue t = Str (B.unsafeBuildText (B.day t))- {-# INLINE encodeMessagePack #-}- encodeMessagePack t = MB.str (B.unsafeBuildText (B.day t))---- | @YYYY-MM-DDTHH:MM:SS.SSSZ@-instance MessagePack LocalTime where- {-# INLINE fromValue #-}- fromValue = withStr "LocalTime" $ \ t ->- case P.parse' (P.localTime <* P.endOfInput) (T.getUTF8Bytes t) of- Left err -> fail' $ "could not parse date as LocalTime: " <> T.toText err- Right r -> return r- {-# INLINE toValue #-}- toValue t = Str (B.unsafeBuildText (B.localTime t))- {-# INLINE encodeMessagePack #-}- encodeMessagePack t = MB.str (B.unsafeBuildText (B.localTime t))---- | @HH:MM:SS.SSS@-instance MessagePack TimeOfDay where- {-# INLINE fromValue #-}- fromValue = withStr "TimeOfDay" $ \ t ->- case P.parse' (P.timeOfDay <* P.endOfInput) (T.getUTF8Bytes t) of- Left err -> fail' $ "could not parse time as TimeOfDay: " <> T.toText err- Right r -> return r- {-# INLINE toValue #-}- toValue t = Str (B.unsafeBuildText (B.timeOfDay t))- {-# INLINE encodeMessagePack #-}- encodeMessagePack t = MB.str (B.unsafeBuildText (B.timeOfDay t))---- | This instance includes a bounds check to prevent maliciously--- large inputs to fill up the memory of the target system. You can--- newtype 'NominalDiffTime' and provide your own instance using--- 'withScientific' if you want to allow larger inputs.-instance MessagePack NominalDiffTime where- {-# INLINE fromValue #-}- fromValue = withBoundedScientific "NominalDiffTime" $ pure . realToFrac- {-# INLINE toValue #-}- toValue = toValue @Scientific . realToFrac- {-# INLINE encodeMessagePack #-}- encodeMessagePack = encodeMessagePack @Scientific . realToFrac---- | This instance includes a bounds check to prevent maliciously--- large inputs to fill up the memory of the target system. You can--- newtype 'DiffTime' and provide your own instance using--- 'withScientific' if you want to allow larger inputs.-instance MessagePack DiffTime where- {-# INLINE fromValue #-}- fromValue = withBoundedScientific "DiffTime" $ pure . realToFrac- {-# INLINE toValue #-}- toValue = toValue @Scientific . realToFrac- {-# INLINE encodeMessagePack #-}- encodeMessagePack = encodeMessagePack @Scientific . realToFrac--instance MessagePack CalendarDiffTime where- {-# INLINE fromValue #-}- fromValue = withFlatMapR "CalendarDiffTime" $ \ v ->- CalendarDiffTime <$> v .: "months" <*> v .: "time"- {-# INLINE toValue #-}- toValue (CalendarDiffTime m nt) = object [ "months" .= m , "time" .= nt ]- {-# INLINE encodeMessagePack #-}- encodeMessagePack (CalendarDiffTime m nt) = object' ("months" .! m <> "time" .! nt)--instance MessagePack CalendarDiffDays where- {-# INLINE fromValue #-}- fromValue = withFlatMapR "CalendarDiffDays" $ \ v ->- CalendarDiffDays <$> v .: "months" <*> v .: "days"- {-# INLINE toValue #-}- toValue (CalendarDiffDays m d) = object ["months" .= m, "days" .= d]- {-# INLINE encodeMessagePack #-}- encodeMessagePack (CalendarDiffDays m d) = object' ("months" .! m <> "days" .! d)--instance MessagePack DayOfWeek where- {-# INLINE fromValue #-}- fromValue (Str "monday" ) = pure Monday- fromValue (Str "tuesday" ) = pure Tuesday- fromValue (Str "wednesday") = pure Wednesday- fromValue (Str "thursday" ) = pure Thursday- fromValue (Str "friday" ) = pure Friday- fromValue (Str "saturday" ) = pure Saturday- fromValue (Str "sunday" ) = pure Sunday- fromValue (Str _ ) = fail' "converting DayOfWeek failed, value should be one of weekdays"- fromValue v = typeMismatch "DayOfWeek" "String" v- {-# INLINE toValue #-}- toValue Monday = Str "monday"- toValue Tuesday = Str "tuesday"- toValue Wednesday = Str "wednesday"- toValue Thursday = Str "thursday"- toValue Friday = Str "friday"- toValue Saturday = Str "saturday"- toValue Sunday = Str "sunday"- {-# INLINE encodeMessagePack #-}- encodeMessagePack Monday = MB.str "monday"- encodeMessagePack Tuesday = MB.str "tuesday"- encodeMessagePack Wednesday = MB.str "wednesday"- encodeMessagePack Thursday = MB.str "thursday"- encodeMessagePack Friday = MB.str "friday"- encodeMessagePack Saturday = MB.str "saturday"- encodeMessagePack Sunday = MB.str "sunday"------------------------------------------------------------------------------------deriving newtype instance MessagePack (f (g a)) => MessagePack (Compose f g a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.Min a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.Max a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.First a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.Last a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.WrappedMonoid a)-deriving newtype instance MessagePack a => MessagePack (Semigroup.Dual a)-deriving newtype instance MessagePack a => MessagePack (Monoid.First a)-deriving newtype instance MessagePack a => MessagePack (Monoid.Last a)-deriving newtype instance MessagePack a => MessagePack (Identity a)-deriving newtype instance MessagePack a => MessagePack (Const a b)-deriving newtype instance MessagePack b => MessagePack (Tagged a b)------------------------------------------------------------------------------------deriving newtype instance MessagePack CChar-deriving newtype instance MessagePack CSChar-deriving newtype instance MessagePack CUChar-deriving newtype instance MessagePack CShort-deriving newtype instance MessagePack CUShort-deriving newtype instance MessagePack CInt-deriving newtype instance MessagePack CUInt-deriving newtype instance MessagePack CLong-deriving newtype instance MessagePack CULong-deriving newtype instance MessagePack CPtrdiff-deriving newtype instance MessagePack CSize-deriving newtype instance MessagePack CWchar-deriving newtype instance MessagePack CSigAtomic-deriving newtype instance MessagePack CLLong-deriving newtype instance MessagePack CULLong-deriving newtype instance MessagePack CBool-deriving newtype instance MessagePack CIntPtr-deriving newtype instance MessagePack CUIntPtr-deriving newtype instance MessagePack CIntMax-deriving newtype instance MessagePack CUIntMax-deriving newtype instance MessagePack CClock-deriving newtype instance MessagePack CTime-deriving newtype instance MessagePack CUSeconds-deriving newtype instance MessagePack CSUSeconds-deriving newtype instance MessagePack CFloat-deriving newtype instance MessagePack CDouble------------------------------------------------------------------------------------deriving anyclass instance (MessagePack (f a), MessagePack (g a), MessagePack a) => MessagePack (Sum f g a)-deriving anyclass instance (MessagePack a, MessagePack b) => MessagePack (Either a b)-deriving anyclass instance (MessagePack (f a), MessagePack (g a)) => MessagePack (Product f g a)--deriving anyclass instance (MessagePack a, MessagePack b) => MessagePack (a, b)-deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c) => MessagePack (a, b, c)-deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d) => MessagePack (a, b, c, d)-deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e) => MessagePack (a, b, c, d, e)-deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e, MessagePack f) => MessagePack (a, b, c, d, e, f)-deriving anyclass instance (MessagePack a, MessagePack b, MessagePack c, MessagePack d, MessagePack e, MessagePack f, MessagePack g) => MessagePack (a, b, c, d, e, f, g)
Z/Data/MessagePack/Builder.hs view
@@ -5,7 +5,7 @@ , (c) Dong Han 2020 License : BSD3 -'Builder's to encode in MessagePack format.+'Builder's to encode Haskell data types in MessagePack format. -} @@ -51,24 +51,23 @@ int :: Int64 -> B.Builder () {-# INLINE int #-} int n- | -0x20 <= n && n < 0x80 = B.word8 (fromIntegral n)- | 0 <= n && n < 0x100 = B.word8 0xCC >> B.word8 (fromIntegral n)- | 0 <= n && n < 0x10000 = B.word8 0xCD >> B.encodePrimBE @Word16 (fromIntegral n)- | 0 <= n && n < 0x100000000 = B.word8 0xCE >> B.encodePrimBE @Word32 (fromIntegral n)- | 0 <= n = B.word8 0xCF >> B.encodePrimBE @Word64 (fromIntegral n)- | -0x80 <= n = B.word8 0xD0 >> B.word8 (fromIntegral n)- | -0x8000 <= n = B.word8 0xD1 >> B.encodePrimBE @Word16 (fromIntegral n)- | -0x80000000 <= n = B.word8 0xD2 >> B.encodePrimBE @Word32 (fromIntegral n)- | otherwise = B.word8 0xD3 >> B.encodePrimBE @Word64 (fromIntegral n)+ | -0x20 <= n && n < 0x80 = B.encodePrim (fromIntegral n :: Word8)+ | 0 <= n && n < 0x100 = B.encodePrim (0xCC :: Word8, fromIntegral n :: Word8)+ | 0 <= n && n < 0x10000 = B.encodePrim (0xCD :: Word8, BE (fromIntegral n :: Word16))+ | 0 <= n && n < 0x100000000 = B.encodePrim (0xCE :: Word8, BE (fromIntegral n :: Word32))+ | 0 <= n = B.encodePrim (0xCF :: Word8, BE (fromIntegral n :: Word64))+ | -0x80 <= n = B.encodePrim (0xD0 :: Word8, fromIntegral n :: Word8)+ | -0x8000 <= n = B.encodePrim (0xD1 :: Word8, BE (fromIntegral n :: Word16))+ | -0x80000000 <= n = B.encodePrim (0xD2 :: Word8, BE (fromIntegral n :: Word32))+ | otherwise = B.encodePrim (0xD3 :: Word8, BE (fromIntegral n :: Word64)) float :: Float -> B.Builder () {-# INLINE float #-}-float f = B.word8 0xCA >> B.encodePrimBE f+float f = B.encodePrim (0xCA :: Word8, BE f) double :: Double -> B.Builder () {-# INLINE double #-}-double d = B.word8 0xCB >> B.encodePrimBE d-+double d = B.encodePrim (0xCB :: Word8, BE d) -- | Construct a scientific value, see 'scientific'. scientificValue :: Integer -> Int64 -> Value@@ -93,7 +92,7 @@ -- +--------+--------+--------+-----------------------------------------+---------------------------------------+ -- scientific :: Integer -> Int64 -> B.Builder ()-{-# INLINE scientific #-}+{-# INLINABLE scientific #-} scientific 0 _ = B.encodePrim @(Word8, Word8, Word8, Word8) (0xD5, 0x00, 0x00, 0x00) scientific c e = do case (I# (word2Int# siz#)) + intSiz e of@@ -102,9 +101,9 @@ 4 -> B.word8 0xD6 8 -> B.word8 0xD7 16 -> B.word8 0xD8- siz' | siz' < 0x100 -> B.word8 0xC7 >> B.word8 (fromIntegral siz')- | siz' < 0x10000 -> B.word8 0xC8 >> B.encodePrimBE @Word16 (fromIntegral siz')- | otherwise -> B.word8 0xC9 >> B.encodePrimBE @Word32 (fromIntegral siz')+ siz' | siz' < 0x100 -> B.encodePrim (0xC7 :: Word8, fromIntegral siz' :: Word8)+ | siz' < 0x10000 -> B.encodePrim (0xC8 :: Word8, BE (fromIntegral siz' :: Word16))+ | otherwise -> B.encodePrim (0xC9 :: Word8, BE (fromIntegral siz' :: Word32)) B.word8 (if c > 0 then 0x00 else 0x01) int e B.writeN (I# (word2Int# siz#)) $ \ (MutablePrimArray mba#) (I# off#) ->@@ -126,12 +125,13 @@ -- | Construct a timestamp(seconds, nanoseconds) value. timestampValue :: Int64 -> Int32 -> Value {-# INLINE timestampValue #-}-timestampValue s ns = Ext 0xFF (B.build $ B.encodePrimBE ns >> B.encodePrimBE s)+timestampValue s ns = Ext 0xFF (B.build $ B.encodePrim (BE ns, BE s)) -- | Write a timestamp(seconds, nanoseconds) in ext 0xFF format, e.g. timestamp :: Int64 -> Int32 -> B.Builder () {-# INLINE timestamp #-}-timestamp s ns = B.encodePrim @(Word8, Word8, Word8, (BE Int32), (BE Int64)) (0xC7, 0x0C, 0xFF, (BE ns), (BE s))+timestamp s ns = B.encodePrim+ (0xC7 :: Word8, 0x0C :: Word8, 0xFF :: Word8, (BE ns :: BE Int32), (BE s :: BE Int64)) str' :: String -> B.Builder () {-# INLINE str' #-}@@ -143,18 +143,18 @@ let bs = T.getUTF8Bytes t case V.length bs of len | len <= 31 -> B.word8 (0xA0 .|. fromIntegral len)- | len < 0x100 -> B.word8 0xD9 >> B.word8 (fromIntegral len)- | len < 0x10000 -> B.word8 0xDA >> B.encodePrimBE @Word16 (fromIntegral len)- | otherwise -> B.word8 0xDB >> B.encodePrimBE @Word32 (fromIntegral len)+ | len < 0x100 -> B.encodePrim (0xD9 :: Word8, fromIntegral len :: Word8)+ | len < 0x10000 -> B.encodePrim (0xDA :: Word8, BE (fromIntegral len :: Word16))+ | otherwise -> B.encodePrim (0xDB :: Word8, BE (fromIntegral len :: Word32)) B.bytes bs bin :: V.Bytes -> B.Builder () {-# INLINE bin #-} bin bs = do case V.length bs of- len | len < 0x100 -> B.word8 0xC4 >> B.word8 (fromIntegral len)- | len < 0x10000 -> B.word8 0xC5 >> B.encodePrimBE @Word16 (fromIntegral len)- | otherwise -> B.word8 0xC6 >> B.encodePrimBE @Word32 (fromIntegral len)+ len | len < 0x100 -> B.encodePrim (0xC4 :: Word8, fromIntegral len :: Word8)+ | len < 0x10000 -> B.encodePrim (0xC5 :: Word8, BE (fromIntegral len :: Word16))+ | otherwise -> B.encodePrim (0xC6 :: Word8, BE (fromIntegral len :: Word32)) B.bytes bs array :: V.Vec v a => (a -> B.Builder ()) -> v a -> B.Builder ()@@ -173,8 +173,8 @@ {-# INLINE arrayHeader #-} arrayHeader len | len <= 15 = B.word8 (0x90 .|. fromIntegral len)- | len < 0x10000 = B.word8 0xDC >> B.encodePrimBE @Word16 (fromIntegral len)- | otherwise = B.word8 0xDD >> B.encodePrimBE @Word32 (fromIntegral len)+ | len < 0x10000 = B.encodePrim (0xDC :: Word8, BE (fromIntegral len :: Word16))+ | otherwise = B.encodePrim (0xDD :: Word8, BE (fromIntegral len :: Word32)) map :: (a -> B.Builder ()) -> (b -> B.Builder ()) -> V.Vector (a, b) -> B.Builder () {-# INLINE map #-}@@ -192,8 +192,8 @@ {-# INLINE mapHeader #-} mapHeader len | len <= 15 = B.word8 (0x80 .|. fromIntegral len)- | len < 0x10000 = B.word8 0xDE >> B.encodePrimBE @Word16 (fromIntegral len)- | otherwise = B.word8 0xDF >> B.encodePrimBE @Word32 (fromIntegral len)+ | len < 0x10000 = B.encodePrim (0xDE :: Word8, BE (fromIntegral len :: Word16))+ | otherwise = B.encodePrim (0xDF :: Word8, BE (fromIntegral len :: Word32)) ext :: Word8 -> V.Bytes -> B.Builder () {-# INLINABLE ext #-}@@ -204,8 +204,8 @@ 4 -> B.word8 0xD6 8 -> B.word8 0xD7 16 -> B.word8 0xD8- len | len < 0x100 -> B.word8 0xC7 >> B.word8 (fromIntegral len)- | len < 0x10000 -> B.word8 0xC8 >> B.encodePrimBE @Word16 (fromIntegral len)- | otherwise -> B.word8 0xC9 >> B.encodePrimBE @Word32 (fromIntegral len)+ len | len < 0x100 -> B.encodePrim (0xC7 :: Word8, fromIntegral len :: Word8)+ | len < 0x10000 -> B.encodePrim (0xC8 :: Word8, BE (fromIntegral len :: Word16))+ | otherwise -> B.encodePrim (0xC9 :: Word8, BE (fromIntegral len :: Word32)) B.word8 typ B.bytes dat
Z/Data/MessagePack/Value.hs view
@@ -8,7 +8,7 @@ module Z.Data.MessagePack.Value( -- * MessagePack Value Value(..)- -- * parse into Message Value+ -- * parse into MessagePack Value , parseValue , parseValue' , parseValueChunks@@ -29,7 +29,6 @@ import qualified Z.Data.Text as T import qualified Z.Data.Parser as P import qualified Z.Data.Vector as V- -- | Representation of MessagePack data. data Value
+ Z/IO/RPC/MessagePack.hs view
@@ -0,0 +1,272 @@+{-|+Module : Z.Data.MessagePack+Description : Fast MessagePack serialization/deserialization+Copyright : (c) Dong Han, 2019+License : BSD+Maintainer : winterland1989@gmail.com+Stability : experimental+Portability : non-portable++This module provides <https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md MessagePack-RPC> implementation.++@+-- server+import Z.IO.RPC.MessagePack+import Z.IO.Network+import Z.IO+import qualified Z.Data.Text as T++serveRPC (startTCPServer defaultTCPServerConfig) . simpleRouter $+ [ ("foo", CallHandler $ \\ (req :: Int) -> do+ return (req + 1))+ , ("bar", NotifyHandler $ \\ (req :: T.Text) -> do+ printStd (req <> "world"))+ ]++-- client+import Z.IO.RPC.MessagePack+import Z.IO.Network+import Z.IO+import qualified Z.Data.Text as T++withResource (initTCPClient defaultTCPClientConfig) $ \\ uvs -> do+ c <- rpcClient uvs+ call \@Int \@Int c "foo" 1+ call \@T.Text \@T.Text c "bar" "hello"+@++-}++module Z.IO.RPC.MessagePack where++import Control.Monad+import Data.Bits+import Z.Data.PrimRef.PrimIORef+import qualified Z.Data.MessagePack.Builder as MB+import qualified Z.Data.MessagePack.Value as MV+import Z.Data.MessagePack (MessagePack)+import qualified Z.Data.MessagePack as MP+import qualified Z.Data.Parser as P+import qualified Z.Data.Text as T+import qualified Z.Data.Vector.FlatIntMap as FIM+import qualified Z.Data.Vector.FlatMap as FM+import qualified Z.Data.Vector as V+import Z.IO+import Z.IO.Network++data Client = Client+ { _clientSeqRef :: Counter+ , _clientPipelineReqNum :: Counter+ , _clientBufferedInput :: BufferedInput+ , _clientBufferedOutput :: BufferedOutput+ }++-- | Open a RPC client from input/output device.+rpcClient :: (Input dev, Output dev) => dev -> IO Client+rpcClient uvs = rpcClient' uvs uvs V.defaultChunkSize V.defaultChunkSize++-- | Open a RPC client with more control.+rpcClient' :: (Input i, Output o)+ => i+ -> o+ -> Int -- ^ recv buffer size+ -> Int -- ^ send buffer size+ -> IO Client+rpcClient' i o recvBufSiz sendBufSiz = do+ seqRef <- newCounter 0+ reqNum <- newCounter 0+ bi <- newBufferedInput' recvBufSiz i+ bo <- newBufferedOutput' sendBufSiz o+ return (Client seqRef reqNum bi bo)++-- | Send a single RPC call and get result.+call:: (MessagePack req, MessagePack res) => Client -> T.Text -> req -> IO res+call cli name req = do+ msgid <- callPipeline cli name req+ fetchPipeline msgid =<< execPipeline cli++-- | Send a single notification RPC call without getting result.+notify :: MessagePack req => Client -> T.Text -> req -> IO ()+notify c@(Client _ _ _ bo) name req = notifyPipeline c name req >> flushBuffer bo++type PipelineId = Int+type PipelineResult = FIM.FlatIntMap MV.Value++-- | Make a call inside a pipeline, which will be sent in batch when `execPipeline`.+--+-- @+-- ...+-- fooId <- callPipeline client "foo" $ ...+-- barId <- callPipeline client "bar" $ ...+-- notifyPipeline client "qux" $ ...+--+-- r <- execPipeline client+--+-- fooResult <- fetchPipeline fooId r+-- barResult <- fetchPipeline barId r+-- @+--+callPipeline :: HasCallStack => MessagePack req => Client -> T.Text -> req -> IO PipelineId+callPipeline (Client seqRef reqNum _ bo) name req = do+ msgid <- readPrimIORef seqRef+ writePrimIORef seqRef (msgid+1)+ modifyPrimIORef reqNum (+1)+ let !msgid' = msgid .&. 0xFFFFFFFF -- shrink to unsiged 32bits+ writeBuilder bo $ do+ MB.arrayHeader 4+ MB.int 0 -- type request+ MB.int (fromIntegral msgid') -- msgid+ MB.str name -- method name+ MP.encodeMessagePack req -- param+ return msgid'++-- | Make a notify inside a pipeline, which will be sent in batch when `execPipeline`.+--+-- Notify calls doesn't affect execution's result.+notifyPipeline :: HasCallStack => MessagePack req => Client -> T.Text -> req -> IO ()+notifyPipeline (Client _ _ _ bo) name req = do+ writeBuilder bo $ do+ MB.arrayHeader 3+ MB.int 2 -- type notification+ MB.str name -- method name+ MP.encodeMessagePack req -- param++-- | Exception thrown when remote endpoint return errors.+data RPCException = RPCException MV.Value CallStack deriving Show+instance Exception RPCException++-- | Sent request in batch and get result in a map identified by 'PipelineId'.+execPipeline :: HasCallStack => Client -> IO PipelineResult+execPipeline (Client _ reqNum bi bo) = do+ flushBuffer bo+ n <- readPrimIORef reqNum+ writePrimIORef reqNum 0+ FIM.packN n <$> replicateM n (do+ (msgid, err, v) <- readParser (do+ tag <- P.anyWord8+ when (tag /= 0x94) (P.fail' $ "wrong response tag: " <> T.toText tag)+ !typ <- MV.value+ !seq <- MV.value+ !err <- MV.value+ !v <- MV.value+ case typ of+ MV.Int 1 -> case seq of+ MV.Int msgid | msgid >= 0 && msgid <= 0xFFFFFFFF ->+ return (msgid, err, v)+ _ -> P.fail' $ "wrong msgid: " <> T.toText seq+ _ -> P.fail' $ "wrong response type: " <> T.toText typ+ ) bi+ when (err /= MV.Nil) $ throwIO (RPCException err callStack)+ return (V.IPair (fromIntegral msgid) v))++-- | Use the `PipelineId` returned when `callPipeline` to fetch call's result.+fetchPipeline :: HasCallStack => MessagePack res => PipelineId -> PipelineResult -> IO res+fetchPipeline msgid r = do+ unwrap "EPARSE" . MP.convertValue =<<+ unwrap' "ENOMSG" ("missing message in response: " <> T.toText msgid)+ (FIM.lookup msgid r)++--------------------------------------------------------------------------------++type ServerLoop = (UVStream -> IO ()) -> IO ()+type ServerService = T.Text -> Maybe ServerHandler+data ServerHandler where+ CallHandler :: (MessagePack req, MessagePack res) => (req -> IO res) -> ServerHandler+ NotifyHandler :: MessagePack req => (req -> IO ()) -> ServerHandler++-- | Simple router using `FlatMap`, lookup name in /O(log(N))/.+--+-- @+-- import Z.IO.PRC.MessagePack+-- import Z.IO.Network+-- import Z.IO+--+-- serveRPC (startTCPServer defaultTCPServerConfig) . simpleRouter $+-- [ ("foo", CallHandler $ \\ req -> do+-- ... )+-- , ("bar", CallHandler $ \\ req -> do+-- ... )+-- ]+--+-- @+simpleRouter :: [(T.Text, ServerHandler)] -> ServerService+simpleRouter handles name = FM.lookup name handleMap+ where+ handleMap = FM.packR handles++-- | Serve a RPC service.+serveRPC :: ServerLoop -> ServerService -> IO ()+serveRPC serve = serveRPC' serve V.defaultChunkSize V.defaultChunkSize++-- | Serve a RPC service with more control.+serveRPC' :: ServerLoop+ -> Int -- ^ recv buffer size+ -> Int -- ^ send buffer size+ -> ServerService -> IO ()+serveRPC' serve recvBufSiz sendBufSiz handle = serve $ \ uvs -> do+ bi <- newBufferedInput' recvBufSiz uvs+ bo <- newBufferedOutput' sendBufSiz uvs+ loop bi bo+ where+ loop bi bo = do+ req <- pull (sourceParserFromBuffered (do+ tag <- P.anyWord8+ case tag of+ -- notify+ 0x93 -> do+ !typ <- MV.value+ !name <- MV.value+ !v <- MV.value+ case typ of+ MV.Int 2 -> case name of+ MV.Str name' -> return (Left (name', v))+ _ -> P.fail' $ "wrong RPC name: " <> T.toText name+ _ -> P.fail' $ "wrong notification type: " <> T.toText typ+ -- call+ 0x94 -> do+ !typ <- MV.value+ !seq <- MV.value+ !name <- MV.value+ !v <- MV.value+ case typ of+ MV.Int 0 -> case seq of+ MV.Int msgid | msgid >= 0 && msgid <= 0xFFFFFFFF -> case name of+ MV.Str name' -> return (Right (msgid, name', v))+ _ -> P.fail' $ "wrong RPC name: " <> T.toText name+ _ -> P.fail' $ "wrong msgid: " <> T.toText seq+ _ -> P.fail' $ "wrong request type: " <> T.toText typ+ _ -> P.fail' $ "wrong request tag: " <> T.toText tag+ ) bi)+ case req of+ Just (Left (name, v)) -> do+ case handle name of+ Just (NotifyHandler f) -> do+ f =<< unwrap "EPARSE" (MP.convertValue v)+ _ -> throwOtherError "ENOTFOUND" "notification method not found"+ loop bi bo+ Just (Right (msgid, name, v)) -> do+ case handle name of+ Just (CallHandler f) -> do+ res <- try (f =<< unwrap "EPARSE" (MP.convertValue v))+ writeBuilder bo $ do+ MB.arrayHeader 4+ MB.int 1 -- type response+ MB.int (fromIntegral msgid) -- msgid+ case res of+ Left e -> do+ MB.str (T.pack $ show (e :: SomeException))+ MB.nil+ Right res -> do+ MB.nil+ MP.encodeMessagePack res+ flushBuffer bo+ _ -> do+ writeBuilder bo $ do+ MB.arrayHeader 4+ MB.int 1 -- type response+ MB.int (fromIntegral msgid) -- msgid+ MB.str $ "request method: " <> name <> " not found"+ MB.nil+ flushBuffer bo+ loop bi bo+ _ -> return ()