websockets-0.3.1.0: src/Network/WebSockets/Types.hs
-- | Primary types
module Network.WebSockets.Types
( Headers
, Request (..)
, Response (..)
, FrameType (..)
, Frame (..)
, Message (..)
, ControlMessage (..)
, DataMessage (..)
, WebSocketsData (..)
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.CaseInsensitive as CI
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
-- | Request headers
type Headers = [(CI.CI B.ByteString, B.ByteString)]
-- | Simple request type
data Request = Request
{ requestPath :: !B.ByteString
, requestHeaders :: Headers
} deriving (Show)
-- | Response to a 'Request'
data Response = Response
{ responseCode :: !Int
, responseMessage :: !B.ByteString
, responseHeaders :: Headers
} deriving (Show)
-- | A frame
data Frame = Frame
{ frameFin :: !Bool
, frameType :: !FrameType
, framePayload :: !BL.ByteString
} deriving (Eq, Show)
-- | Type of a frame
data FrameType
= ContinuationFrame
| TextFrame
| BinaryFrame
| CloseFrame
| PingFrame
| PongFrame
deriving (Eq, Show)
-- | The kind of message a server application typically deals with
data Message
= ControlMessage ControlMessage
| DataMessage DataMessage
deriving (Show)
-- | Different control messages
data ControlMessage
= Close BL.ByteString
| Ping BL.ByteString
| Pong BL.ByteString
deriving (Show)
-- | For an end-user of this library, dealing with 'Frame's would be a bit
-- low-level. This is why define another type on top of it, which represents
-- data for the application layer.
data DataMessage
= Text BL.ByteString
| Binary BL.ByteString
deriving (Show)
-- | In order to have an even more high-level API, we define a typeclass for
-- values the user can receive from and send to the socket. A few warnings
-- apply:
--
-- * Natively, everything is represented as a 'BL.ByteString', so this is the
-- fastest instance
--
-- * You should only use the 'TL.Text' or the 'T.Text' instance when you are
-- sure that the data is UTF-8 encoded (which is the case for 'Text'
-- messages).
--
-- * Messages can be very large. If this is the case, it might be inefficient to
-- use the strict 'B.ByteString' and 'T.Text' instances.
class WebSocketsData a where
fromLazyByteString :: BL.ByteString -> a
toLazyByteString :: a -> BL.ByteString
instance WebSocketsData BL.ByteString where
fromLazyByteString = id
toLazyByteString = id
instance WebSocketsData B.ByteString where
fromLazyByteString = B.concat . BL.toChunks
toLazyByteString = BL.fromChunks . return
instance WebSocketsData TL.Text where
fromLazyByteString = TL.decodeUtf8
toLazyByteString = TL.encodeUtf8
instance WebSocketsData T.Text where
fromLazyByteString = T.concat . TL.toChunks . fromLazyByteString
toLazyByteString = toLazyByteString . TL.fromChunks . return