pinch-0.3.0.2: An alternative implementation of Thrift for Haskell.

Copyright(c) Abhinav Gupta 2015
LicenseBSD3
MaintainerAbhinav Gupta <mail@abhinavg.net>
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Pinch

Contents

Description

Pinch defines machinery to specify how types can be encoded into or decoded from Thrift payloads.

Synopsis

Serializing and deserializing

Types that can be serialized and deserialized into/from Thrift values implement the Pinchable typeclass. Instances may be derived automatically using generics, or written out by hand.

The Pinchable typeclass converts objects into and from Value objects, which act as a direct mapping to the Thrift wire representation. A Protocol is responsible for converting Value objects to and from bytestrings.

The encode and decode methods may be used on objects that implement the Pinchable typeclass to get the wire representation directly.

+------------+   Pinchable                    Protocol    +------------+
|            |               +------------+               |            |
|            +----pinch------>            +---serialize--->            |
| Your Type  |               |  Value a   |               | ByteString |
|            <---unpinch-----+            <--deserialize--+            |
|            |               +------------+               |            |
|            |                                            |            |
|            +-------------------encode------------------->            |
|            |                                            |            |
|            <-------------------decode-------------------+            |
+------------+                                            +------------+

encode :: Pinchable a => Protocol -> a -> ByteString Source #

Encode the given Pinchable value using the given Protocol.

>>> unpack $ encode binaryProtocol ["a" :: ByteString, "b"]
[11,0,0,0,2,0,0,0,1,97,0,0,0,1,98]

decode :: Pinchable a => Protocol -> ByteString -> Either String a Source #

Decode a Pinchable value from the using the given Protocol.

>>> let s = pack [11,0,0,0,2,0,0,0,1,97,0,0,0,1,98]
>>> decode binaryProtocol s :: Either String [ByteString]
Right ["a","b"]

RPC

Thrift requests implicitly form a struct and responses implicitly form a union. To send/receive the request/response, it must be wrapped inside a Message. The Message contains information like the method name, the message ID (to match out of order responses with requests), and whether it contains a request or a response.

Requests and responses may be wrapped into Message objects using the mkMessage function. The message body can be retrieved back using the getMessageBody function. The encodeMessage and decodeMessage functions may be used to encode and decode messages into/from bytestrings.

Consider the service method,

User getUser(1: string userName, 2: list<Attribute> attributes)
  throws (1: UserDoesNotExist doesNotExist,
          2: InternalError internalError)

The request and response for this method implictly take the form:

struct getUserRequest {
  1: string userName
  2: list<Attribute> attributes
}
union getUserResponse {
  0: User success
  1: UserDoesNotExist doesNotExist
  2: InternalError InternalError
}

(Note that the field ID 0 is reserved for the return value of the method.)

Given corresponding data types GetUserRequest and GetUserResponse, the client can do something similar to,

let req = GetUserRequest "jsmith" []
    msg = mkMessage "getUser" Call 0 req
response <- sendToServer (encodeMessage msg)
case decodeMessage response of
    Left err -> handleError err
    Right msg -> case getMessageBody msg of
        Left err -> handleError err
        Right (res :: GetUserResponse) -> handleResponse res

Similarly, on the server side,

case decodeMessage request of
    Left err -> handleError err
    Right msg -> case messageName msg of
        "getUser" -> case getMessageBody msg of
            Left err -> handleError err
            Right (req :: GetUserRequest) -> do
                let mid = messageId msg
                res <- handleGetUser req
                return (mkMessage "getUser" Reply mid res)
                -- Note that the response MUST contain the same
                -- message ID as its request.
        _ -> handleUnknownMethod

encodeMessage :: Protocol -> Message -> ByteString Source #

Encode the Message using the given Protocol.

let request = GetUserRequest (putField "jsmith") (putField [])
    message = mkMessage "getUser" Call 42 request
in encodeMessage binaryProtocol message

decodeMessage :: Protocol -> ByteString -> Either String Message Source #

Decode a Message using the given Protocol.

>>> decodeMessage binaryProtocol bs >>= getMessageBody :: Either String GetUserRequest
Right (GetUserRequest {userName = Field "jsmith", userAttributes = Field []})

Pinchable

class IsTType (Tag a) => Pinchable a where Source #

The Pinchable type class is implemented by types that can be sent or received over the wire as Thrift payloads.

Associated Types

type Tag a Source #

TType tag for this type.

For most custom types, this will be TStruct, TUnion, or TException. For enums, it will be TEnum. If the instance automatically derived with use of Generic, this is not required because it is automatically determined by use of Field or Enumeration.

Methods

pinch :: a -> Value (Tag a) Source #

Convert an a into a Value.

For structs, struct, .=, and ?= may be used to construct Value objects tagged with TStruct.

unpinch :: Value (Tag a) -> Parser a Source #

Read a Value back into an a.

For structs, .: and .:? may be used to retrieve field values.

pinch :: (Generic a, GPinchable (Rep a)) => a -> Value (GTag (Rep a)) Source #

Convert an a into a Value.

For structs, struct, .=, and ?= may be used to construct Value objects tagged with TStruct.

unpinch :: (Generic a, GPinchable (Rep a)) => Value (GTag (Rep a)) -> Parser a Source #

Read a Value back into an a.

For structs, .: and .:? may be used to retrieve field values.

Instances

Pinchable Bool Source # 

Associated Types

type Tag Bool :: * Source #

Pinchable Double Source # 

Associated Types

type Tag Double :: * Source #

Pinchable Int8 Source # 

Associated Types

type Tag Int8 :: * Source #

Pinchable Int16 Source # 

Associated Types

type Tag Int16 :: * Source #

Pinchable Int32 Source # 

Associated Types

type Tag Int32 :: * Source #

Pinchable Int64 Source # 

Associated Types

type Tag Int64 :: * Source #

Pinchable ByteString Source # 
Pinchable ByteString Source # 
Pinchable Text Source # 

Associated Types

type Tag Text :: * Source #

Pinchable Text Source # 

Associated Types

type Tag Text :: * Source #

Pinchable a => Pinchable [a] Source # 

Associated Types

type Tag [a] :: * Source #

Methods

pinch :: [a] -> Value (Tag [a]) Source #

unpinch :: Value (Tag [a]) -> Parser [a] Source #

(Ord a, Pinchable a) => Pinchable (Set a) Source # 

Associated Types

type Tag (Set a) :: * Source #

Methods

pinch :: Set a -> Value (Tag (Set a)) Source #

unpinch :: Value (Tag (Set a)) -> Parser (Set a) Source #

(Eq a, Hashable a, Pinchable a) => Pinchable (HashSet a) Source # 

Associated Types

type Tag (HashSet a) :: * Source #

Pinchable a => Pinchable (Vector a) Source # 

Associated Types

type Tag (Vector a) :: * Source #

Methods

pinch :: Vector a -> Value (Tag (Vector a)) Source #

unpinch :: Value (Tag (Vector a)) -> Parser (Vector a) Source #

IsTType a => Pinchable (Value a) Source # 

Associated Types

type Tag (Value a) :: * Source #

Methods

pinch :: Value a -> Value (Tag (Value a)) Source #

unpinch :: Value (Tag (Value a)) -> Parser (Value a) Source #

(Ord k, Pinchable k, Pinchable v) => Pinchable (Map k v) Source # 

Associated Types

type Tag (Map k v) :: * Source #

Methods

pinch :: Map k v -> Value (Tag (Map k v)) Source #

unpinch :: Value (Tag (Map k v)) -> Parser (Map k v) Source #

(Eq k, Hashable k, Pinchable k, Pinchable v) => Pinchable (HashMap k v) Source # 

Associated Types

type Tag (HashMap k v) :: * Source #

Methods

pinch :: HashMap k v -> Value (Tag (HashMap k v)) Source #

unpinch :: Value (Tag (HashMap k v)) -> Parser (HashMap k v) Source #

data Parser a Source #

A simple continuation-based parser.

This is just Either e a in continuation-passing style.

Instances

Monad Parser Source # 

Methods

(>>=) :: Parser a -> (a -> Parser b) -> Parser b #

(>>) :: Parser a -> Parser b -> Parser b #

return :: a -> Parser a #

fail :: String -> Parser a #

Functor Parser Source # 

Methods

fmap :: (a -> b) -> Parser a -> Parser b #

(<$) :: a -> Parser b -> Parser a #

Applicative Parser Source # 

Methods

pure :: a -> Parser a #

(<*>) :: Parser (a -> b) -> Parser a -> Parser b #

(*>) :: Parser a -> Parser b -> Parser b #

(<*) :: Parser a -> Parser b -> Parser a #

Alternative Parser Source # 

Methods

empty :: Parser a #

(<|>) :: Parser a -> Parser a -> Parser a #

some :: Parser a -> Parser [a] #

many :: Parser a -> Parser [a] #

MonadPlus Parser Source # 

Methods

mzero :: Parser a #

mplus :: Parser a -> Parser a -> Parser a #

runParser :: Parser a -> Either String a Source #

Run a Parser and return the result inside an Either.

Automatically deriving instances

Pinch supports deriving instances of Pinchable automatically for types that implement the Generic typeclass provided that they follow the outlined patterns in their constructors.

Structs and exceptions

Given the struct,

struct User {
  1: required string name
  2: optional string emailAddress
}

A Pinchable instance for it can be automatically derived by wrapping fields of the data type with the Field type and specifying the field identifier as a type-level numeral. Fields which hold a Maybe value are considered optional.

data User = User
    { userName         :: Field 1 Text
    , userEmailAddress :: Field 2 (Maybe Text)
    }
  deriving (Generic)

instance Pinchable User

The DeriveGeneric extension is required to automatically derive instances of the Generic typeclass and the DataKinds extension is required to use type-level numerals.

Unions

As with structs and exceptions, fields of the data type representing a union must be tagged with Field, but to satisfy the property of a union that only one value is set at a time, they must be on separate constructors.

For example, given the union,

union Item {
  1: binary bin
  2: string str
  3: i32    int
}

A Pinchable instance can be derived like so,

data Item
    = ItemBin (Field 1 ByteString)
    | ItemStr (Field 2 Text)
    | ItemInt (Field 3 Int32)
  deriving (Generic)

instance Pinchable Item

The DeriveGeneric extension is required to automatically derive instances of the Generic typeclass and the DataKinds extension is required to use type-level numerals.

If the union represents the response of a service method which returns a void result, the type Void may be used.

data GetFooResponse
  = GetFooDoesNotExist  (Field 1 FooDoesNotExist)
  | GetFooInternalError (Field 2 InternalError)
  | GetFooSuccess Void

newtype Field n a Source #

Fields of data types that represent structs, unions, and exceptions should be wrapped inside Field and tagged with the field identifier.

data Foo = Foo (Field 1 Text) (Field 2 (Maybe Int32)) deriving Generic
instance Pinchable Foo
data A = A (Field 1 Int32) | B (Field 2 Text) deriving Generic
instance Pinchable Foo

Fields which hold Maybe values are treated as optional. All fields values must be Pinchable to automatically derive a Pinchable instance for the new data type.

Constructors

Field a 

Instances

Functor (Field n) Source # 

Methods

fmap :: (a -> b) -> Field n a -> Field n b #

(<$) :: a -> Field n b -> Field n a #

Foldable (Field n) Source # 

Methods

fold :: Monoid m => Field n m -> m #

foldMap :: Monoid m => (a -> m) -> Field n a -> m #

foldr :: (a -> b -> b) -> b -> Field n a -> b #

foldr' :: (a -> b -> b) -> b -> Field n a -> b #

foldl :: (b -> a -> b) -> b -> Field n a -> b #

foldl' :: (b -> a -> b) -> b -> Field n a -> b #

foldr1 :: (a -> a -> a) -> Field n a -> a #

foldl1 :: (a -> a -> a) -> Field n a -> a #

toList :: Field n a -> [a] #

null :: Field n a -> Bool #

length :: Field n a -> Int #

elem :: Eq a => a -> Field n a -> Bool #

maximum :: Ord a => Field n a -> a #

minimum :: Ord a => Field n a -> a #

sum :: Num a => Field n a -> a #

product :: Num a => Field n a -> a #

Traversable (Field n) Source # 

Methods

traverse :: Applicative f => (a -> f b) -> Field n a -> f (Field n b) #

sequenceA :: Applicative f => Field n (f a) -> f (Field n a) #

mapM :: Monad m => (a -> m b) -> Field n a -> m (Field n b) #

sequence :: Monad m => Field n (m a) -> m (Field n a) #

Bounded a => Bounded (Field n a) Source # 

Methods

minBound :: Field n a #

maxBound :: Field n a #

Enum a => Enum (Field n a) Source # 

Methods

succ :: Field n a -> Field n a #

pred :: Field n a -> Field n a #

toEnum :: Int -> Field n a #

fromEnum :: Field n a -> Int #

enumFrom :: Field n a -> [Field n a] #

enumFromThen :: Field n a -> Field n a -> [Field n a] #

enumFromTo :: Field n a -> Field n a -> [Field n a] #

enumFromThenTo :: Field n a -> Field n a -> Field n a -> [Field n a] #

Eq a => Eq (Field n a) Source # 

Methods

(==) :: Field n a -> Field n a -> Bool #

(/=) :: Field n a -> Field n a -> Bool #

Ord a => Ord (Field n a) Source # 

Methods

compare :: Field n a -> Field n a -> Ordering #

(<) :: Field n a -> Field n a -> Bool #

(<=) :: Field n a -> Field n a -> Bool #

(>) :: Field n a -> Field n a -> Bool #

(>=) :: Field n a -> Field n a -> Bool #

max :: Field n a -> Field n a -> Field n a #

min :: Field n a -> Field n a -> Field n a #

Show a => Show (Field n a) Source # 

Methods

showsPrec :: Int -> Field n a -> ShowS #

show :: Field n a -> String #

showList :: [Field n a] -> ShowS #

Generic (Field n a) Source # 

Associated Types

type Rep (Field n a) :: * -> * #

Methods

from :: Field n a -> Rep (Field n a) x #

to :: Rep (Field n a) x -> Field n a #

Monoid a => Monoid (Field n a) Source # 

Methods

mempty :: Field n a #

mappend :: Field n a -> Field n a -> Field n a #

mconcat :: [Field n a] -> Field n a #

NFData a => NFData (Field n a) Source # 

Methods

rnf :: Field n a -> () #

(Pinchable a, KnownNat n) => GPinchable (K1 i (Field n (Maybe a))) Source # 

Associated Types

type GTag (K1 i (Field n (Maybe a)) :: * -> *) :: * Source #

Methods

gPinch :: K1 i (Field n (Maybe a)) a -> Value (GTag (K1 i (Field n (Maybe a)))) Source #

gUnpinch :: Value (GTag (K1 i (Field n (Maybe a)))) -> Parser (K1 i (Field n (Maybe a)) a) Source #

(Pinchable a, KnownNat n) => GPinchable (K1 i (Field n a)) Source # 

Associated Types

type GTag (K1 i (Field n a) :: * -> *) :: * Source #

Methods

gPinch :: K1 i (Field n a) a -> Value (GTag (K1 i (Field n a))) Source #

gUnpinch :: Value (GTag (K1 i (Field n a))) -> Parser (K1 i (Field n a) a) Source #

type Rep (Field n a) Source # 
type Rep (Field n a) = D1 (MetaData "Field" "Pinch.Internal.Generic" "pinch-0.3.0.2-777RSwXwMKV6kl5a1VTaAD" True) (C1 (MetaCons "Field" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a)))
type GTag (K1 i (Field n (Maybe a))) Source # 
type GTag (K1 i (Field n (Maybe a))) = TStruct
type GTag (K1 i (Field n a)) Source # 
type GTag (K1 i (Field n a)) = TStruct

getField :: Field n a -> a Source #

Gets the current value of a field.

let Foo a' _ = {- ... -}
    a = getField a'

putField :: a -> Field n a Source #

Puts a value inside a field.

Foo (putField "Hello") (putField (Just 42))

field :: Functor f => (a -> f b) -> Field n a -> f (Field n b) Source #

A lens on Field wrappers for use with the lens library.

person & name . field .~ "new value"

data Void Source #

Represents a void result for methods.

This should be used as an element in a response union along with Field tags.

For a method,

void setValue(..) throws
  (1: ValueAlreadyExists alreadyExists,
   2: InternalError internalError)

Something similar to the following can be used.

data SetValueResponse
  = SetValueAlreadyExists (Field 1 ValueAlreadyExists)
  | SetValueInternalError (Field 2 InternalError)
  | SetValueSuccess Void
  deriving (Generic)

instance Pinchable SetValueResponse

Constructors

Void 

Instances

Eq Void Source # 

Methods

(==) :: Void -> Void -> Bool #

(/=) :: Void -> Void -> Bool #

Ord Void Source # 

Methods

compare :: Void -> Void -> Ordering #

(<) :: Void -> Void -> Bool #

(<=) :: Void -> Void -> Bool #

(>) :: Void -> Void -> Bool #

(>=) :: Void -> Void -> Bool #

max :: Void -> Void -> Void #

min :: Void -> Void -> Void #

Show Void Source # 

Methods

showsPrec :: Int -> Void -> ShowS #

show :: Void -> String #

showList :: [Void] -> ShowS #

Generic Void Source # 

Associated Types

type Rep Void :: * -> * #

Methods

from :: Void -> Rep Void x #

to :: Rep Void x -> Void #

GPinchable (K1 i Void) Source # 

Associated Types

type GTag (K1 i Void :: * -> *) :: * Source #

Methods

gPinch :: K1 i Void a -> Value (GTag (K1 i Void)) Source #

gUnpinch :: Value (GTag (K1 i Void)) -> Parser (K1 i Void a) Source #

type Rep Void Source # 
type Rep Void = D1 (MetaData "Void" "Pinch.Internal.Generic" "pinch-0.3.0.2-777RSwXwMKV6kl5a1VTaAD" False) (C1 (MetaCons "Void" PrefixI False) U1)
type GTag (K1 i Void) Source # 
type GTag (K1 i Void) = TStruct

Enums

Given the enum,

enum Op {
  Add, Sub, Mul, Div
}

A Pinchable instance can be derived for it by creating one constructor for each of the enum values and providing it a single Enumeration argument tagged with the enum value.

data Op
    = OpAdd (Enumeration 0)
    | OpSub (Enumeration 1)
    | OpMul (Enumeration 2)
    | OpDiv (Enumeration 3)
  deriving (Generic)

instance Pinchable Op

Note that you need to know the values assigned to the enums. If not specified, Thrift automatically assigns incrementing values to the items in the order they appear starting at 0.

The DeriveGeneric extension is required to automatically derive instances of the Generic typeclass and the DataKinds extension is required to use type-level numerals.

data Enumeration n Source #

Data types that represent Thrift enums must have one constructor for each enum item accepting an Enumeration object tagged with the corresponding enum value.

data Role = RoleUser (Enumeration 1) | RoleAdmin (Enumeration 2)
  deriving Generic
instance Pinchable Role

Constructors

Enumeration 

Instances

Eq (Enumeration n) Source # 
Ord (Enumeration n) Source # 
Show (Enumeration n) Source # 
Generic (Enumeration n) Source # 

Associated Types

type Rep (Enumeration n) :: * -> * #

Methods

from :: Enumeration n -> Rep (Enumeration n) x #

to :: Rep (Enumeration n) x -> Enumeration n #

NFData (Enumeration n) Source # 

Methods

rnf :: Enumeration n -> () #

KnownNat n => GPinchable (K1 i (Enumeration n)) Source # 

Associated Types

type GTag (K1 i (Enumeration n) :: * -> *) :: * Source #

Methods

gPinch :: K1 i (Enumeration n) a -> Value (GTag (K1 i (Enumeration n))) Source #

gUnpinch :: Value (GTag (K1 i (Enumeration n))) -> Parser (K1 i (Enumeration n) a) Source #

type Rep (Enumeration n) Source # 
type Rep (Enumeration n) = D1 (MetaData "Enumeration" "Pinch.Internal.Generic" "pinch-0.3.0.2-777RSwXwMKV6kl5a1VTaAD" False) (C1 (MetaCons "Enumeration" PrefixI False) U1)
type GTag (K1 i (Enumeration n)) Source # 
type GTag (K1 i (Enumeration n)) = TEnum

enum :: Enumeration n Source #

Convenience function to construct Enumeration objects.

let role = RoleUser enum

Manually writing instances

Instances of Pinchable can be constructed by composing together existing instances and using the .=, .:, etc. helpers.

Structs and exceptions

Given a Thrift struct,

struct Post {
  1: optional string subject
  2: required string body
}

The Pinchable instance for it will be,

data Post = Post
    { postSubject :: Maybe Text
    , postBody    :: Text
    }

instance Pinchable Post where
    type Tag Post = TStruct

    pinch (Post subject body) =
        struct [ 1 ?= subject
               , 2 .= body
               ]

    unpinch value =
        Post <$> value .:? 1
             <*> value .:  2

Unions

Given a Thrift union,

union PostBody {
  1: string markdown
  2: binary rtf
}

The Pinchable instance for it will be,

data PostBody
    = PostBodyMarkdown Text
    | PostBodyRtf ByteString

instance Pinchable PostBody where
    type Tag PostBody = TUnion

    pinch (PostBodyMarkdown markdownBody) =
        union 1 markdownBody
    pinch (PostBodyRtf rtfBody) =
        union 2 rtfBody

    unpinch v = PostBodyMarkdown <$> v .: 1
            <|> PostBodyRtf      <$> v .: 2

Enums

Given an enum,

enum Role {
  DISABLED = 0,
  USER,
  ADMIN,
}

The Pinchable instance for it will be,

data Role = RoleDisabled | RoleUser | RoleAdmin

instance Pinchable Role where
    type Tag Role = TEnum

    pinch RoleDisabled = pinch (0 :: Int32)
    pinch RoleUser     = pinch (1 :: Int32)
    pinch RoleAdmin    = pinch (2 :: Int32)

    unpinch v = do
       value <- unpinch v
       case (value :: Int32) of
           0 -> Right RoleDisabled
           1 -> Right RoleUser
           2 -> Right RoleAdmin
           _ -> Left $ "Unknown role: " ++ show value

Helpers

pinch

(.=) :: Pinchable a => Int16 -> a -> FieldPair Source #

Construct a FieldPair from a field identifier and a Pinchable value.

(?=) :: Pinchable a => Int16 -> Maybe a -> FieldPair Source #

Construct a FieldPair from a field identifier and an optional Pinchable value.

struct :: [FieldPair] -> Value TStruct Source #

Construct a Value tagged with a TStruct from the given key-value pairs. Optional fields whose values were omitted will be ignored.

struct [1 .= ("Hello" :: Text), 2 .= (42 :: Int16)]

union :: Pinchable a => Int16 -> a -> Value TUnion Source #

Constructs a Value tagged with TUnion.

union 1 ("foo" :: ByteString)

type FieldPair = (Int16, Maybe SomeValue) Source #

A pair of field identifier and maybe a value stored in the field. If the value is absent, the field will be ignored.

unpinch

(.:) :: forall a. Pinchable a => Value TStruct -> Int16 -> Parser a Source #

Given a field ID and a Value TStruct, get the value stored in the struct under that field ID. The lookup fails if the field is absent or if it's not the same type as expected by this call's context.

(.:?) :: forall a. Pinchable a => Value TStruct -> Int16 -> Parser (Maybe a) Source #

Given a field ID and a Value TStruct, get the optional value stored in the struct under the given field ID. The value returned is Nothing if it was absent or the wrong type. The lookup fails only if the value retrieved fails to unpinch.

Value

Value is an intermediate representation of Thrift payloads tagged with TType tags. Types that want to be serialized into/deserialized from Thrift payloads need only define a way to convert themselves to and from Value objects via Pinchable.

data Value a Source #

Value maps directly to serialized representation of Thrift types. It contains about as much information as what gets sent over the wire. Value objects are tagged with different TType values to indicate the type of the value.

Typical usage will not involve accessing the constructors for this type. Pinchable must be used to construct Value objects or convert them back to original types.

Instances

Eq (Value a) Source # 

Methods

(==) :: Value a -> Value a -> Bool #

(/=) :: Value a -> Value a -> Bool #

Show (Value a) Source # 

Methods

showsPrec :: Int -> Value a -> ShowS #

show :: Value a -> String #

showList :: [Value a] -> ShowS #

NFData (Value a) Source # 

Methods

rnf :: Value a -> () #

Hashable (Value a) Source # 

Methods

hashWithSalt :: Int -> Value a -> Int #

hash :: Value a -> Int #

IsTType a => Pinchable (Value a) Source # 

Associated Types

type Tag (Value a) :: * Source #

Methods

pinch :: Value a -> Value (Tag (Value a)) Source #

unpinch :: Value (Tag (Value a)) -> Parser (Value a) Source #

type Tag (Value a) Source # 
type Tag (Value a) = a

data SomeValue where Source #

SomeValue holds any value, regardless of type. This may be used when the type of the value is not necessarily known at compile time. Typically, this will be pattern matched on and code that depends on the value's TType will go inside the scope of the match.

Constructors

SomeValue :: IsTType a => !(Value a) -> SomeValue 

Messages

data Message Source #

Message envelope for Thrift payloads.

Instances

Eq Message Source # 

Methods

(==) :: Message -> Message -> Bool #

(/=) :: Message -> Message -> Bool #

Show Message Source # 
Generic Message Source # 

Associated Types

type Rep Message :: * -> * #

Methods

from :: Message -> Rep Message x #

to :: Rep Message x -> Message #

NFData Message Source # 

Methods

rnf :: Message -> () #

type Rep Message Source # 

mkMessage Source #

Arguments

:: (Pinchable a, Tag a ~ TStruct) 
=> Text

Name of the target method.

-> MessageType

Type of the message.

-> Int32

Message ID.

-> a

Message payload. This must be an object which serializes into a struct.

-> Message 

Build a Message.

messageName :: Message -> Text Source #

Name of the method to which this message is targeted.

messageType :: Message -> MessageType Source #

Type of the message.

messageId :: Message -> Int32 Source #

Sequence ID of the message.

If the clients expect to receive out-of-order responses, they may use the message ID to map responses back to their corresponding requests. If the client does not expect out-of-order responses, they are free to use the same message ID for all messages.

The server's contract regarding message IDs is that all responses must have the same message ID as their corresponding requests.

getMessageBody :: (Pinchable a, Tag a ~ TStruct) => Message -> Either String a Source #

Read the message contents.

This returns a Left result if the message contents do not match the requested type.

data MessageType Source #

Type of message being sent.

Constructors

Call

A call to a specific method.

The message body is the request arguments struct.

Reply

Response to a call.

The message body is the response union.

Exception

Failure to make a call.

Note: This message type is not used for exceptions that are defined under the throws clause of a method. Those exceptions are part of the response union of the method and are received in a Reply. This message type is used for Thrift-level failures.

Oneway

One-way call that expects no response.

Instances

Eq MessageType Source # 
Data MessageType Source # 

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> MessageType -> c MessageType #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c MessageType #

toConstr :: MessageType -> Constr #

dataTypeOf :: MessageType -> DataType #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c MessageType) #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c MessageType) #

gmapT :: (forall b. Data b => b -> b) -> MessageType -> MessageType #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> MessageType -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> MessageType -> r #

gmapQ :: (forall d. Data d => d -> u) -> MessageType -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> MessageType -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> MessageType -> m MessageType #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> MessageType -> m MessageType #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> MessageType -> m MessageType #

Show MessageType Source # 
Generic MessageType Source # 

Associated Types

type Rep MessageType :: * -> * #

NFData MessageType Source # 

Methods

rnf :: MessageType -> () #

type Rep MessageType Source # 
type Rep MessageType = D1 (MetaData "MessageType" "Pinch.Internal.Message" "pinch-0.3.0.2-777RSwXwMKV6kl5a1VTaAD" False) ((:+:) ((:+:) (C1 (MetaCons "Call" PrefixI False) U1) (C1 (MetaCons "Reply" PrefixI False) U1)) ((:+:) (C1 (MetaCons "Exception" PrefixI False) U1) (C1 (MetaCons "Oneway" PrefixI False) U1)))

Protocols

data Protocol Source #

Protocols define a specific way to convert values into binary and back.

binaryProtocol :: Protocol Source #

Provides an implementation of the Thrift Binary Protocol.

compactProtocol :: Protocol Source #

Provides an implementation of the Thrift Compact Protocol.

TType

TType is used to refer to the Thrift protocol-level type of a value.

data TType a Source #

Represents the type of a Thrift value.

Objects of this type are tagged with one of the TType tags, so this type also acts as a singleton on the TTypes. It allows writing code that can enforce properties about the TType of values at compile time.

Instances

Eq (TType a) Source # 

Methods

(==) :: TType a -> TType a -> Bool #

(/=) :: TType a -> TType a -> Bool #

Show (TType a) Source # 

Methods

showsPrec :: Int -> TType a -> ShowS #

show :: TType a -> String #

showList :: [TType a] -> ShowS #

Hashable (TType a) Source # 

Methods

hashWithSalt :: Int -> TType a -> Int #

hash :: TType a -> Int #

class Typeable a => IsTType a where Source #

Typeclass used to map type-leve TTypes into TType objects. All TType tags are instances of this class.

Minimal complete definition

ttype

Methods

ttype :: TType a Source #

Based on the context in which this is used, it will automatically return the corresponding TType object.

Tags

TType tags allow writing code that depends on knowing the TType of values, or asserting conditions on it, at compile time.

For example, values in a map, list, or set must all have the same TType. This is enforced at the type level by parameterizing Value over these tags.

data TBool Source #

bool

Instances

data TByte Source #

byte

Instances

data TDouble Source #

double

type TEnum = TInt32 Source #

enum

data TInt16 Source #

i16

Instances

data TInt32 Source #

i32

Instances

data TInt64 Source #

i64

Instances

data TBinary Source #

binary

data TStruct Source #

struct

type TUnion = TStruct Source #

union

type TException = TStruct Source #

exception

data TMap Source #

map<k, v>

Instances

data TSet Source #

set<x>

Instances

data TList Source #

list<x>

Instances