packages feed

grpc-spec 1.1.0 → 1.1.1

raw patch · 4 files changed

+105/−2 lines, 4 filesdep +cborgdep +serialisedep ~QuickCheckPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: cborg, serialise

Dependency ranges changed: QuickCheck

API changes (from Hackage documentation)

+ Network.GRPC.Spec: data CborRpc (serv :: Symbol) (meth :: Symbol)
- Network.GRPC.Spec: NextElem :: !a -> NextElem a
+ Network.GRPC.Spec: NextElem :: a -> NextElem a

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for grpc-spec +## 1.1.1 -- 2026-10-30++* Support for (non-standard) CBOR RPC [#383, Finley McIlwaine]+ ## 1.1.0 -- 2026-09-02  * Trivial `BuildMetadata` and `ParseMetadata` instances for `[CustomMetadata]`
grpc-spec.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               grpc-spec-version:            1.1.0+version:            1.1.1 synopsis:           Implementation of the pure part of the gRPC spec description:        This is an implementation of the pure part of the core gRPC                     spec at <https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md>.@@ -105,6 +105,7 @@       Network.GRPC.Spec.OrcaLoadReport       Network.GRPC.Spec.PercentEncoding       Network.GRPC.Spec.RPC+      Network.GRPC.Spec.RPC.CBOR       Network.GRPC.Spec.RPC.JSON       Network.GRPC.Spec.RPC.Protobuf       Network.GRPC.Spec.RPC.Raw@@ -134,6 +135,7 @@     , binary                    >= 0.8     && < 0.9     , bytestring                >= 0.10.12 && < 0.13     , case-insensitive          >= 1.2     && < 1.3+    , cborg                     >= 0.2     && < 0.3     , containers                >= 0.6     && < 0.9     , data-default              >= 0.7     && < 0.9     , deepseq                   >= 1.4     && < 1.6@@ -147,6 +149,7 @@     , proto-lens-protobuf-types >= 0.7     && < 0.8     , proto-lens-runtime        >= 0.7     && < 0.8     , record-hasfield           >= 1.0     && < 1.1+    , serialise                 >= 0.2     && < 0.3     , text                      >= 1.2     && < 2.2     , utf8-string               >= 1.0     && < 1.1     , vector                    >= 0.13    && < 0.14@@ -198,7 +201,7 @@       -- Additional dependencies     , prettyprinter               >= 1.7   && < 1.8     , prettyprinter-ansi-terminal >= 1.1   && < 1.2-    , QuickCheck                  >= 2.14  && < 2.19+    , QuickCheck                  >= 2.14  && < 2.20     , quickcheck-instances        >= 0.3   && < 0.5     , tasty                       >= 1.4   && < 1.6     , tasty-quickcheck            >= 0.10  && < 0.12
src/Network/GRPC/Spec.hs view
@@ -27,6 +27,8 @@   , EncodeFields -- opaque     -- *** Raw   , RawRpc+    -- *** CBOR+  , CborRpc     -- * Streaming types   , StreamingType(..)   , SStreamingType(..)@@ -187,6 +189,7 @@ import Network.GRPC.Spec.MessageMeta import Network.GRPC.Spec.OrcaLoadReport import Network.GRPC.Spec.RPC+import Network.GRPC.Spec.RPC.CBOR import Network.GRPC.Spec.RPC.JSON import Network.GRPC.Spec.RPC.Protobuf import Network.GRPC.Spec.RPC.Raw
+ src/Network/GRPC/Spec/RPC/CBOR.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.GRPC.Spec.RPC.CBOR (CborRpc) where++import Codec.CBOR.Read qualified as CBOR+import Codec.Serialise+import Control.DeepSeq (NFData)+import Control.Exception (displayException)+import Data.ByteString.Char8 qualified as BS.Char8+import Data.ByteString.Lazy qualified as BS.Lazy+import Data.ByteString.Lazy qualified as Lazy (ByteString)+import Data.Proxy+import GHC.TypeLits++import Network.GRPC.Spec.CustomMetadata.Typed+import Network.GRPC.Spec.RPC+import Network.GRPC.Spec.RPC.StreamType++{-------------------------------------------------------------------------------+  CBOR format+-------------------------------------------------------------------------------}++-- | gRPC using CBOR as the message encoding+--+-- You will need to manually provide 'Input' and 'Output' instances for each+-- RPC you use, along with 'Serialise' instances for those types.+data CborRpc (serv :: Symbol) (meth :: Symbol)++instance ( KnownSymbol serv+         , KnownSymbol meth++           -- Serialization+         , NFData (Input  (CborRpc serv meth))+         , NFData (Output (CborRpc serv meth))++           -- Debugging constraints+         , Show (Input  (CborRpc serv meth))+         , Show (Output (CborRpc serv meth))+         , Show (RequestMetadata (CborRpc serv meth))+         , Show (ResponseInitialMetadata (CborRpc serv meth))+         , Show (ResponseTrailingMetadata (CborRpc serv meth))+         ) => IsRPC (CborRpc serv meth) where+  rpcContentType _ = defaultRpcContentType "cbor"+  rpcServiceName _ = BS.Char8.pack $ symbolVal (Proxy @serv)+  rpcMethodName  _ = BS.Char8.pack $ symbolVal (Proxy @meth)+  rpcMessageType _ = Nothing++instance ( IsRPC (CborRpc serv meth)++           -- Serialization constraints+         , Serialise (Input  (CborRpc serv meth))+         , Serialise (Output (CborRpc serv meth))++           -- Metadata constraints+         , BuildMetadata (RequestMetadata          (CborRpc serv meth))+         , ParseMetadata (ResponseInitialMetadata  (CborRpc serv meth))+         , ParseMetadata (ResponseTrailingMetadata (CborRpc serv meth))+         ) => SupportsClientRpc (CborRpc serv meth) where+  rpcSerializeInput    _ = serialise+  rpcDeserializeOutput _ = deserialiseExactly++instance ( IsRPC (CborRpc serv meth)++           -- Serialization constraints+         , Serialise (Input  (CborRpc serv meth))+         , Serialise (Output (CborRpc serv meth))++           -- Metadata constraints+         , ParseMetadata (RequestMetadata          (CborRpc serv meth))+         , BuildMetadata (ResponseInitialMetadata  (CborRpc serv meth))+         , BuildMetadata (ResponseTrailingMetadata (CborRpc serv meth))+         ) => SupportsServerRpc (CborRpc serv meth) where+  rpcDeserializeInput _ = deserialiseExactly+  rpcSerializeOutput  _ = serialise++-- | For CBOR protocol we do not check communication protocols+instance ValidStreamingType styp+      => SupportsStreamingType (CborRpc serv meth) styp++-- | Decode the CBOR-encoded value in the given 'Lazy.ByteString'+--+-- Fails if the decoder fails or if there are any bytes leftover after a+-- successful decode.+deserialiseExactly :: Serialise a => Lazy.ByteString -> Either String a+deserialiseExactly bs =+    case CBOR.deserialiseFromBytes decode bs of+      Left err ->+        Left $ displayException err+      Right (unconsumed, a) ->+        if BS.Lazy.null unconsumed then+          Right a+        else+          Left "Not all bytes consumed"