Safe Haskell | None |
---|---|
Language | Haskell2010 |
Stateful codec. This module is intended to be imported qualified.
Synopsis
- data Codec ps failure (f :: ps -> Type) (m :: Type -> Type) bytes = Codec {
- encode :: forall (st :: ps) (st' :: ps). (StateTokenI st, ActiveState st) => f st -> Message ps st st' -> bytes
- decode :: forall (st :: ps). ActiveState st => StateToken st -> f st -> m (DecodeStep bytes failure m (SomeMessage st))
- hoistCodec :: forall n m ps failure (f :: ps -> Type) bytes. Functor n => (forall x. m x -> n x) -> Codec ps failure f m bytes -> Codec ps failure f n bytes
- isoCodec :: forall (m :: Type -> Type) bytes bytes' ps failure (f :: ps -> Type). Functor m => (bytes -> bytes') -> (bytes' -> bytes) -> Codec ps failure f m bytes -> Codec ps failure f m bytes'
- mapFailureCodec :: forall (m :: Type -> Type) failure failure' ps (f :: ps -> Type) bytes. Functor m => (failure -> failure') -> Codec ps failure f m bytes -> Codec ps failure' f m bytes
- liftCodec :: forall ps failure (m :: Type -> Type) bytes (f :: ps -> Type). Codec ps failure m bytes -> Codec ps failure f m bytes
- data DecodeStep bytes failure (m :: Type -> Type) a
- = DecodePartial (Maybe bytes -> m (DecodeStep bytes failure m a))
- | DecodeDone a (Maybe bytes)
- | DecodeFail failure
- runDecoder :: Monad m => [bytes] -> DecodeStep bytes failure m a -> m (Either failure a)
- runDecoderPure :: Monad m => (forall b. m b -> b) -> m (DecodeStep bytes failure m a) -> [bytes] -> Either failure a
- data SomeMessage (st :: ps) where
- SomeMessage :: forall ps (st :: ps) (st' :: ps). (StateTokenI st, StateTokenI st', ActiveState st) => Message ps st st' -> SomeMessage st
- type family StateToken :: ps -> Type
- class StateTokenI (st :: ps) where
- stateToken :: StateToken st
- type ActiveState (st :: ps) = IsActiveState st (StateAgency st)
- data PeerRole
- data CodecFailure
- data AnyMessage ps (f :: ps -> Type) where
- AnyMessage :: forall ps (f :: ps -> Type) (st :: ps) (st' :: ps). (StateTokenI st, ActiveState st) => f st -> Message ps st st' -> AnyMessage ps f
- pattern AnyMessageAndAgency :: forall ps f (st :: ps) (st' :: ps). () => (StateTokenI st, ActiveState st) => StateToken st -> f st -> Message ps st st' -> AnyMessage ps f
- showAnyMessage :: forall ps (f :: ps -> Type). (forall (st :: ps) (st' :: ps). Show (Message ps st st'), forall (st :: ps). Show (f st)) => AnyMessage ps f -> String
- prop_codecM :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => Codec ps failure f m bytes -> AnyMessage ps f -> m Bool
- prop_codec :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => (forall a. m a -> a) -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool
- prop_codec_splitsM :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => (bytes -> [[bytes]]) -> Codec ps failure f m bytes -> AnyMessage ps f -> m Bool
- prop_codec_splits :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => (bytes -> [[bytes]]) -> (forall a. m a -> a) -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool
- prop_codecs_compatM :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f), forall a. Monoid a => Monoid (m a)) => Codec ps failure f m bytes -> Codec ps failure f m bytes -> AnyMessage ps f -> m Bool
- prop_codecs_compat :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f), forall a. Monoid a => Monoid (m a)) => (forall a. m a -> a) -> Codec ps failure f m bytes -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool
Defining and using Codecs
data Codec ps failure (f :: ps -> Type) (m :: Type -> Type) bytes Source #
A stateful codec.
Codec | |
|
hoistCodec :: forall n m ps failure (f :: ps -> Type) bytes. Functor n => (forall x. m x -> n x) -> Codec ps failure f m bytes -> Codec ps failure f n bytes Source #
isoCodec :: forall (m :: Type -> Type) bytes bytes' ps failure (f :: ps -> Type). Functor m => (bytes -> bytes') -> (bytes' -> bytes) -> Codec ps failure f m bytes -> Codec ps failure f m bytes' Source #
mapFailureCodec :: forall (m :: Type -> Type) failure failure' ps (f :: ps -> Type) bytes. Functor m => (failure -> failure') -> Codec ps failure f m bytes -> Codec ps failure' f m bytes Source #
liftCodec :: forall ps failure (m :: Type -> Type) bytes (f :: ps -> Type). Codec ps failure m bytes -> Codec ps failure f m bytes Source #
Incremental decoding
data DecodeStep bytes failure (m :: Type -> Type) a #
An incremental decoder with return a value of type a
.
This interface is not designed to be used directly for implementing decoders, only for running them. In real applications it is expected to use libraries for text or binary decoding and to implement appropriate wrappers to match up with this incremental decoder interface.
This style of interface already closely matches that provided by libraries
such as attoparsec
for text formats, and binary
, cereal
and cborg
for binary formats.
DecodePartial (Maybe bytes -> m (DecodeStep bytes failure m a)) | The decoder has consumed the available input and needs more
to continue. Provide |
DecodeDone a (Maybe bytes) | The decoder has successfully finished. This provides the decoded result value plus any unused input. |
DecodeFail failure | The decoder ran into an error. The decoder either used
|
:: Monad m | |
=> [bytes] | bytes to be fed into the incremental |
-> DecodeStep bytes failure m a | decoder |
-> m (Either failure a) |
Run a codec incremental decoder DecodeStep
against a list of input.
It ignores any unused trailing data. This is useful for demos, quick experiments and tests.
See also runDecoderWithChannel
:: Monad m | |
=> (forall b. m b -> b) | run monad |
-> m (DecodeStep bytes failure m a) | |
-> [bytes] | input bytes |
-> Either failure a |
A variant of runDecoder
that is suitable for "pure" monads that have
a run function. This includes ST
, using runST
.
Related types
SomeMessage
data SomeMessage (st :: ps) where #
When decoding a Message
we only know the expected "from" state. We
cannot know the "to" state as this depends on the message we decode. To
resolve this we use the SomeMessage
wrapper which uses an existential
type to hide the "to" state.
SomeMessage :: forall ps (st :: ps) (st' :: ps). (StateTokenI st, StateTokenI st', ActiveState st) => Message ps st st' -> SomeMessage st |
StateToken
type family StateToken :: ps -> Type #
A type family for protocol state token, e.g. term level representation of type level state (also known as singleton).
This type family is similar to Sing
type class in the "singletons"
package, but specific for protocol states.
class StateTokenI (st :: ps) where #
A type class which hides a state token / singleton inside a class dictionary.
This is similar to the SingI
instance, but specific to protocol state
singletons.
stateToken :: StateToken st #
ActiveState
type ActiveState (st :: ps) = IsActiveState st (StateAgency st) #
A constraint which provides an evidence that the protocol isn't in a terminal state.
PeerRole
Types for client and server peer roles. As protocol can be viewed from either client or server side.
Note that technically "client" and "server" are arbitrary labels. The framework is completely symmetric between the two peers.
This definition is only used as promoted types and kinds, never as values.
Instances
SingI 'AsClient | |
Defined in Network.TypedProtocol.Core | |
SingI 'AsServer | |
Defined in Network.TypedProtocol.Core | |
type Sing | |
Defined in Network.TypedProtocol.Core |
CodecFailure
data CodecFailure #
Each Codec
can use whatever failure
type is appropriate. This simple
exception type is provided for use by simple codecs (e.g. "identity") when
nothing more than a String
is needed. It is an instance of Exception
.
Instances
Exception CodecFailure | |
Defined in Network.TypedProtocol.Codec | |
Show CodecFailure | |
Defined in Network.TypedProtocol.Codec showsPrec :: Int -> CodecFailure -> ShowS # show :: CodecFailure -> String # showList :: [CodecFailure] -> ShowS # | |
Eq CodecFailure | |
Defined in Network.TypedProtocol.Codec (==) :: CodecFailure -> CodecFailure -> Bool # (/=) :: CodecFailure -> CodecFailure -> Bool # |
Testing codec properties
data AnyMessage ps (f :: ps -> Type) where Source #
Any message for a protocol, with a StateTokenI
constraint which gives access
to protocol state.
Used where we don't know statically what the state type is, but need the agency and message to match each other.
AnyMessage | |
|
pattern AnyMessageAndAgency :: forall ps f (st :: ps) (st' :: ps). () => (StateTokenI st, ActiveState st) => StateToken st -> f st -> Message ps st st' -> AnyMessage ps f | A convenient pattern synonym which unwrap |
showAnyMessage :: forall ps (f :: ps -> Type). (forall (st :: ps) (st' :: ps). Show (Message ps st st'), forall (st :: ps). Show (f st)) => AnyMessage ps f -> String Source #
showAnyMessage
is can be used to provide Show
instance for
AnyMessage
if showing Message
is independent of the state or one accepts
showing only partial information included in message constructors or accepts
message constructors to carry Show
instances for its arguments. Note that
the proper solution is to define a custom `Show (AnyMessage ps f)` instance
for a protocol ps
, which give access to the state functor f
in scope of
show
.
prop_codecM :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => Codec ps failure f m bytes -> AnyMessage ps f -> m Bool Source #
The Codec
round-trip property: decode after encode gives the same
message. Every codec must satisfy this property.
prop_codec :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => (forall a. m a -> a) -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool Source #
The Codec
round-trip property in a pure monad.
:: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) | |
=> (bytes -> [[bytes]]) | alternative re-chunkings of serialised form |
-> Codec ps failure f m bytes | |
-> AnyMessage ps f | |
-> m Bool |
A variant on the codec round-trip property: given the encoding of a message, check that decode always gives the same result irrespective of how the chunks of input are fed to the incremental decoder.
This property guards against boundary errors in incremental decoders. It is not necessary to check this for every message type, just for each generic codec construction. For example given some binary serialisation library one would write a generic adaptor to the codec interface. This adaptor has to deal with the incremental decoding and this is what needs to be checked.
prop_codec_splits :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f)) => (bytes -> [[bytes]]) -> (forall a. m a -> a) -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool Source #
Like
but run in a pure monad prop_codec_splitsM
m
, e.g. Identity
.
prop_codecs_compatM :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f), forall a. Monoid a => Monoid (m a)) => Codec ps failure f m bytes -> Codec ps failure f m bytes -> AnyMessage ps f -> m Bool Source #
Compatibility between two codecs of the same protocol. Encode a message with one codec and decode it with the other one, then compare if the result is the same as initial message.
prop_codecs_compat :: forall ps failure (f :: ps -> Type) m bytes. (Monad m, Eq (AnyMessage ps f), forall a. Monoid a => Monoid (m a)) => (forall a. m a -> a) -> Codec ps failure f m bytes -> Codec ps failure f m bytes -> AnyMessage ps f -> Bool Source #
Like
but run in a pure monad prop_codecs_compatM
m
, e.g. Identity
.