module Signet.Unstable.Type.Message where

import qualified Data.Bifunctor as Bifunctor
import qualified Data.ByteString as ByteString
import qualified Signet.Unstable.Exception.InvalidMessage as InvalidMessage
import qualified Signet.Unstable.Type.Id as Id
import qualified Signet.Unstable.Type.Payload as Payload
import qualified Signet.Unstable.Type.Timestamp as Timestamp

data Message = MkMessage
  { Message -> Id
id_ :: Id.Id,
    Message -> Timestamp
timestamp :: Timestamp.Timestamp,
    Message -> Payload
payload :: Payload.Payload
  }
  deriving (Message -> Message -> Bool
(Message -> Message -> Bool)
-> (Message -> Message -> Bool) -> Eq Message
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Message -> Message -> Bool
== :: Message -> Message -> Bool
$c/= :: Message -> Message -> Bool
/= :: Message -> Message -> Bool
Eq, Int -> Message -> ShowS
[Message] -> ShowS
Message -> String
(Int -> Message -> ShowS)
-> (Message -> String) -> ([Message] -> ShowS) -> Show Message
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Message -> ShowS
showsPrec :: Int -> Message -> ShowS
$cshow :: Message -> String
show :: Message -> String
$cshowList :: [Message] -> ShowS
showList :: [Message] -> ShowS
Show)

parse :: ByteString.ByteString -> Either InvalidMessage.InvalidMessage Message
parse :: ByteString -> Either InvalidMessage Message
parse ByteString
x = do
  let (ByteString
rawId, ByteString
y) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
ByteString.break (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Id.separator) ByteString
x
  theId <- (InvalidId -> InvalidMessage)
-> Either InvalidId Id -> Either InvalidMessage Id
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
Bifunctor.first InvalidId -> InvalidMessage
InvalidMessage.InvalidId (Either InvalidId Id -> Either InvalidMessage Id)
-> Either InvalidId Id -> Either InvalidMessage Id
forall a b. (a -> b) -> a -> b
$ ByteString -> Either InvalidId Id
Id.parse ByteString
rawId
  let (rawTimestamp, z) =
        ByteString.break (== Id.separator) $
          ByteString.drop 1 y
  theTimestamp <-
    Bifunctor.first InvalidMessage.InvalidTimestamp $
      Timestamp.parse rawTimestamp
  let thePayload = ByteString -> Payload
Payload.MkPayload (ByteString -> Payload) -> ByteString -> Payload
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
ByteString.drop Int
1 ByteString
z
  pure MkMessage {id_ = theId, timestamp = theTimestamp, payload = thePayload}

render :: Message -> ByteString.ByteString
render :: Message -> ByteString
render Message
message =
  Id -> ByteString
Id.render (Message -> Id
id_ Message
message)
    ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Word8 -> ByteString
ByteString.singleton Word8
Id.separator
    ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Timestamp -> ByteString
Timestamp.render (Message -> Timestamp
timestamp Message
message)
    ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Word8 -> ByteString
ByteString.singleton Word8
Id.separator
    ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Payload -> ByteString
Payload.unwrap (Message -> Payload
payload Message
message)