{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

module Simplex.FileTransfer.Types where

import qualified Data.Aeson.TH as J
import qualified Data.Attoparsec.ByteString.Char8 as A
import Data.ByteString.Char8 (ByteString)
import Data.Int (Int64)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Word (Word32)
import Simplex.FileTransfer.Client (XFTPChunkSpec (..))
import Simplex.FileTransfer.Description
import Simplex.Messaging.Agent.Store.DB (FromField (..), ToField (..), fromTextField_)
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.File (CryptoFile (..))
import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers
import Simplex.Messaging.Protocol (XFTPServer)
import System.FilePath ((</>))

type RcvFileId = ByteString -- Agent entity ID

type SndFileId = ByteString -- Agent entity ID

authTagSize :: Int64
authTagSize :: Int64
authTagSize = Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
C.authTagSize

-- fileExtra is added to allow header extension in future versions
data FileHeader = FileHeader
  { FileHeader -> String
fileName :: String,
    FileHeader -> Maybe String
fileExtra :: Maybe String
  }
  deriving (FileHeader -> FileHeader -> Bool
(FileHeader -> FileHeader -> Bool)
-> (FileHeader -> FileHeader -> Bool) -> Eq FileHeader
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileHeader -> FileHeader -> Bool
== :: FileHeader -> FileHeader -> Bool
$c/= :: FileHeader -> FileHeader -> Bool
/= :: FileHeader -> FileHeader -> Bool
Eq, Int -> FileHeader -> ShowS
[FileHeader] -> ShowS
FileHeader -> String
(Int -> FileHeader -> ShowS)
-> (FileHeader -> String)
-> ([FileHeader] -> ShowS)
-> Show FileHeader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileHeader -> ShowS
showsPrec :: Int -> FileHeader -> ShowS
$cshow :: FileHeader -> String
show :: FileHeader -> String
$cshowList :: [FileHeader] -> ShowS
showList :: [FileHeader] -> ShowS
Show)

instance Encoding FileHeader where
  smpEncode :: FileHeader -> ByteString
smpEncode FileHeader {String
fileName :: FileHeader -> String
fileName :: String
fileName, Maybe String
fileExtra :: FileHeader -> Maybe String
fileExtra :: Maybe String
fileExtra} = (String, Maybe String) -> ByteString
forall a. Encoding a => a -> ByteString
smpEncode (String
fileName, Maybe String
fileExtra)
  smpP :: Parser FileHeader
smpP = do
    (String
fileName, Maybe String
fileExtra) <- Parser (String, Maybe String)
forall a. Encoding a => Parser a
smpP
    FileHeader -> Parser FileHeader
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileHeader {String
fileName :: String
fileName :: String
fileName, Maybe String
fileExtra :: Maybe String
fileExtra :: Maybe String
fileExtra}

type DBRcvFileId = Int64

data RcvFile = RcvFile
  { RcvFile -> Int64
rcvFileId :: DBRcvFileId,
    RcvFile -> ByteString
rcvFileEntityId :: RcvFileId,
    RcvFile -> Int64
userId :: Int64,
    RcvFile -> FileSize Int64
size :: FileSize Int64,
    RcvFile -> FileDigest
digest :: FileDigest,
    RcvFile -> SbKey
key :: C.SbKey,
    RcvFile -> CbNonce
nonce :: C.CbNonce,
    RcvFile -> FileSize Word32
chunkSize :: FileSize Word32,
    RcvFile -> Maybe RcvFileRedirect
redirect :: Maybe RcvFileRedirect,
    RcvFile -> [RcvFileChunk]
chunks :: [RcvFileChunk],
    RcvFile -> String
prefixPath :: FilePath,
    RcvFile -> Maybe String
tmpPath :: Maybe FilePath,
    RcvFile -> CryptoFile
saveFile :: CryptoFile,
    RcvFile -> RcvFileStatus
status :: RcvFileStatus,
    RcvFile -> Bool
deleted :: Bool
  }
  deriving (Int -> RcvFile -> ShowS
[RcvFile] -> ShowS
RcvFile -> String
(Int -> RcvFile -> ShowS)
-> (RcvFile -> String) -> ([RcvFile] -> ShowS) -> Show RcvFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvFile -> ShowS
showsPrec :: Int -> RcvFile -> ShowS
$cshow :: RcvFile -> String
show :: RcvFile -> String
$cshowList :: [RcvFile] -> ShowS
showList :: [RcvFile] -> ShowS
Show)

data RcvFileStatus
  = RFSReceiving
  | RFSReceived
  | RFSDecrypting
  | RFSComplete
  | RFSError
  deriving (RcvFileStatus -> RcvFileStatus -> Bool
(RcvFileStatus -> RcvFileStatus -> Bool)
-> (RcvFileStatus -> RcvFileStatus -> Bool) -> Eq RcvFileStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RcvFileStatus -> RcvFileStatus -> Bool
== :: RcvFileStatus -> RcvFileStatus -> Bool
$c/= :: RcvFileStatus -> RcvFileStatus -> Bool
/= :: RcvFileStatus -> RcvFileStatus -> Bool
Eq, Int -> RcvFileStatus -> ShowS
[RcvFileStatus] -> ShowS
RcvFileStatus -> String
(Int -> RcvFileStatus -> ShowS)
-> (RcvFileStatus -> String)
-> ([RcvFileStatus] -> ShowS)
-> Show RcvFileStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvFileStatus -> ShowS
showsPrec :: Int -> RcvFileStatus -> ShowS
$cshow :: RcvFileStatus -> String
show :: RcvFileStatus -> String
$cshowList :: [RcvFileStatus] -> ShowS
showList :: [RcvFileStatus] -> ShowS
Show)

instance FromField RcvFileStatus where fromField :: FieldParser RcvFileStatus
fromField = (Text -> Maybe RcvFileStatus) -> FieldParser RcvFileStatus
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe RcvFileStatus
forall a. TextEncoding a => Text -> Maybe a
textDecode

instance ToField RcvFileStatus where toField :: RcvFileStatus -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (RcvFileStatus -> Text) -> RcvFileStatus -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RcvFileStatus -> Text
forall a. TextEncoding a => a -> Text
textEncode

instance TextEncoding RcvFileStatus where
  textDecode :: Text -> Maybe RcvFileStatus
textDecode = \case
    Text
"receiving" -> RcvFileStatus -> Maybe RcvFileStatus
forall a. a -> Maybe a
Just RcvFileStatus
RFSReceiving
    Text
"received" -> RcvFileStatus -> Maybe RcvFileStatus
forall a. a -> Maybe a
Just RcvFileStatus
RFSReceived
    Text
"decrypting" -> RcvFileStatus -> Maybe RcvFileStatus
forall a. a -> Maybe a
Just RcvFileStatus
RFSDecrypting
    Text
"complete" -> RcvFileStatus -> Maybe RcvFileStatus
forall a. a -> Maybe a
Just RcvFileStatus
RFSComplete
    Text
"error" -> RcvFileStatus -> Maybe RcvFileStatus
forall a. a -> Maybe a
Just RcvFileStatus
RFSError
    Text
_ -> Maybe RcvFileStatus
forall a. Maybe a
Nothing
  textEncode :: RcvFileStatus -> Text
textEncode = \case
    RcvFileStatus
RFSReceiving -> Text
"receiving"
    RcvFileStatus
RFSReceived -> Text
"received"
    RcvFileStatus
RFSDecrypting -> Text
"decrypting"
    RcvFileStatus
RFSComplete -> Text
"complete"
    RcvFileStatus
RFSError -> Text
"error"

data RcvFileChunk = RcvFileChunk
  { RcvFileChunk -> Int64
rcvFileId :: DBRcvFileId,
    RcvFileChunk -> ByteString
rcvFileEntityId :: RcvFileId,
    RcvFileChunk -> Int64
userId :: Int64,
    RcvFileChunk -> Int64
rcvChunkId :: Int64,
    RcvFileChunk -> Int
chunkNo :: Int,
    RcvFileChunk -> FileSize Word32
chunkSize :: FileSize Word32,
    RcvFileChunk -> FileDigest
digest :: FileDigest,
    RcvFileChunk -> [RcvFileChunkReplica]
replicas :: [RcvFileChunkReplica],
    RcvFileChunk -> String
fileTmpPath :: FilePath,
    RcvFileChunk -> Maybe String
chunkTmpPath :: Maybe FilePath
  }
  deriving (Int -> RcvFileChunk -> ShowS
[RcvFileChunk] -> ShowS
RcvFileChunk -> String
(Int -> RcvFileChunk -> ShowS)
-> (RcvFileChunk -> String)
-> ([RcvFileChunk] -> ShowS)
-> Show RcvFileChunk
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvFileChunk -> ShowS
showsPrec :: Int -> RcvFileChunk -> ShowS
$cshow :: RcvFileChunk -> String
show :: RcvFileChunk -> String
$cshowList :: [RcvFileChunk] -> ShowS
showList :: [RcvFileChunk] -> ShowS
Show)

data RcvFileChunkReplica = RcvFileChunkReplica
  { RcvFileChunkReplica -> Int64
rcvChunkReplicaId :: Int64,
    RcvFileChunkReplica -> XFTPServer
server :: XFTPServer,
    RcvFileChunkReplica -> ChunkReplicaId
replicaId :: ChunkReplicaId,
    RcvFileChunkReplica -> APrivateAuthKey
replicaKey :: C.APrivateAuthKey,
    RcvFileChunkReplica -> Bool
received :: Bool,
    RcvFileChunkReplica -> Maybe Int64
delay :: Maybe Int64,
    RcvFileChunkReplica -> Int
retries :: Int
  }
  deriving (Int -> RcvFileChunkReplica -> ShowS
[RcvFileChunkReplica] -> ShowS
RcvFileChunkReplica -> String
(Int -> RcvFileChunkReplica -> ShowS)
-> (RcvFileChunkReplica -> String)
-> ([RcvFileChunkReplica] -> ShowS)
-> Show RcvFileChunkReplica
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvFileChunkReplica -> ShowS
showsPrec :: Int -> RcvFileChunkReplica -> ShowS
$cshow :: RcvFileChunkReplica -> String
show :: RcvFileChunkReplica -> String
$cshowList :: [RcvFileChunkReplica] -> ShowS
showList :: [RcvFileChunkReplica] -> ShowS
Show)

data RcvFileRedirect = RcvFileRedirect
  { RcvFileRedirect -> Int64
redirectDbId :: DBRcvFileId,
    RcvFileRedirect -> ByteString
redirectEntityId :: RcvFileId,
    RcvFileRedirect -> RedirectFileInfo
redirectFileInfo :: RedirectFileInfo
  }
  deriving (Int -> RcvFileRedirect -> ShowS
[RcvFileRedirect] -> ShowS
RcvFileRedirect -> String
(Int -> RcvFileRedirect -> ShowS)
-> (RcvFileRedirect -> String)
-> ([RcvFileRedirect] -> ShowS)
-> Show RcvFileRedirect
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RcvFileRedirect -> ShowS
showsPrec :: Int -> RcvFileRedirect -> ShowS
$cshow :: RcvFileRedirect -> String
show :: RcvFileRedirect -> String
$cshowList :: [RcvFileRedirect] -> ShowS
showList :: [RcvFileRedirect] -> ShowS
Show)

-- Sending files

type DBSndFileId = Int64

data SndFile = SndFile
  { SndFile -> Int64
sndFileId :: DBSndFileId,
    SndFile -> ByteString
sndFileEntityId :: SndFileId,
    SndFile -> Int64
userId :: Int64,
    SndFile -> Int
numRecipients :: Int,
    SndFile -> Maybe FileDigest
digest :: Maybe FileDigest,
    SndFile -> SbKey
key :: C.SbKey,
    SndFile -> CbNonce
nonce :: C.CbNonce,
    SndFile -> [SndFileChunk]
chunks :: [SndFileChunk],
    SndFile -> CryptoFile
srcFile :: CryptoFile,
    SndFile -> Maybe String
prefixPath :: Maybe FilePath,
    SndFile -> SndFileStatus
status :: SndFileStatus,
    SndFile -> Bool
deleted :: Bool,
    SndFile -> Maybe RedirectFileInfo
redirect :: Maybe RedirectFileInfo
  }
  deriving (Int -> SndFile -> ShowS
[SndFile] -> ShowS
SndFile -> String
(Int -> SndFile -> ShowS)
-> (SndFile -> String) -> ([SndFile] -> ShowS) -> Show SndFile
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndFile -> ShowS
showsPrec :: Int -> SndFile -> ShowS
$cshow :: SndFile -> String
show :: SndFile -> String
$cshowList :: [SndFile] -> ShowS
showList :: [SndFile] -> ShowS
Show)

sndFileEncPath :: FilePath -> FilePath
sndFileEncPath :: ShowS
sndFileEncPath String
prefixPath = String
prefixPath String -> ShowS
</> String
"xftp.encrypted"

data SndFileStatus
  = SFSNew -- db record created
  | SFSEncrypting -- encryption started
  | SFSEncrypted -- encryption complete
  | SFSUploading -- all chunk replicas are created on servers
  | SFSComplete -- all chunk replicas are uploaded
  | SFSError -- permanent error
  deriving (SndFileStatus -> SndFileStatus -> Bool
(SndFileStatus -> SndFileStatus -> Bool)
-> (SndFileStatus -> SndFileStatus -> Bool) -> Eq SndFileStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SndFileStatus -> SndFileStatus -> Bool
== :: SndFileStatus -> SndFileStatus -> Bool
$c/= :: SndFileStatus -> SndFileStatus -> Bool
/= :: SndFileStatus -> SndFileStatus -> Bool
Eq, Int -> SndFileStatus -> ShowS
[SndFileStatus] -> ShowS
SndFileStatus -> String
(Int -> SndFileStatus -> ShowS)
-> (SndFileStatus -> String)
-> ([SndFileStatus] -> ShowS)
-> Show SndFileStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndFileStatus -> ShowS
showsPrec :: Int -> SndFileStatus -> ShowS
$cshow :: SndFileStatus -> String
show :: SndFileStatus -> String
$cshowList :: [SndFileStatus] -> ShowS
showList :: [SndFileStatus] -> ShowS
Show)

instance FromField SndFileStatus where fromField :: FieldParser SndFileStatus
fromField = (Text -> Maybe SndFileStatus) -> FieldParser SndFileStatus
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe SndFileStatus
forall a. TextEncoding a => Text -> Maybe a
textDecode

instance ToField SndFileStatus where toField :: SndFileStatus -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (SndFileStatus -> Text) -> SndFileStatus -> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SndFileStatus -> Text
forall a. TextEncoding a => a -> Text
textEncode

instance TextEncoding SndFileStatus where
  textDecode :: Text -> Maybe SndFileStatus
textDecode = \case
    Text
"new" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSNew
    Text
"encrypting" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSEncrypting
    Text
"encrypted" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSEncrypted
    Text
"uploading" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSUploading
    Text
"complete" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSComplete
    Text
"error" -> SndFileStatus -> Maybe SndFileStatus
forall a. a -> Maybe a
Just SndFileStatus
SFSError
    Text
_ -> Maybe SndFileStatus
forall a. Maybe a
Nothing
  textEncode :: SndFileStatus -> Text
textEncode = \case
    SndFileStatus
SFSNew -> Text
"new"
    SndFileStatus
SFSEncrypting -> Text
"encrypting"
    SndFileStatus
SFSEncrypted -> Text
"encrypted"
    SndFileStatus
SFSUploading -> Text
"uploading"
    SndFileStatus
SFSComplete -> Text
"complete"
    SndFileStatus
SFSError -> Text
"error"

data SndFileChunk = SndFileChunk
  { SndFileChunk -> Int64
sndFileId :: DBSndFileId,
    SndFileChunk -> ByteString
sndFileEntityId :: SndFileId,
    SndFileChunk -> Int64
userId :: Int64,
    SndFileChunk -> Int
numRecipients :: Int,
    SndFileChunk -> Int64
sndChunkId :: Int64,
    SndFileChunk -> Int
chunkNo :: Int,
    SndFileChunk -> XFTPChunkSpec
chunkSpec :: XFTPChunkSpec,
    SndFileChunk -> String
filePrefixPath :: FilePath,
    SndFileChunk -> FileDigest
digest :: FileDigest,
    SndFileChunk -> [SndFileChunkReplica]
replicas :: [SndFileChunkReplica]
  }
  deriving (Int -> SndFileChunk -> ShowS
[SndFileChunk] -> ShowS
SndFileChunk -> String
(Int -> SndFileChunk -> ShowS)
-> (SndFileChunk -> String)
-> ([SndFileChunk] -> ShowS)
-> Show SndFileChunk
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndFileChunk -> ShowS
showsPrec :: Int -> SndFileChunk -> ShowS
$cshow :: SndFileChunk -> String
show :: SndFileChunk -> String
$cshowList :: [SndFileChunk] -> ShowS
showList :: [SndFileChunk] -> ShowS
Show)

sndChunkSize :: SndFileChunk -> Word32
sndChunkSize :: SndFileChunk -> Word32
sndChunkSize SndFileChunk {chunkSpec :: SndFileChunk -> XFTPChunkSpec
chunkSpec = XFTPChunkSpec {Word32
chunkSize :: Word32
chunkSize :: XFTPChunkSpec -> Word32
chunkSize}} = Word32
chunkSize

data NewSndChunkReplica = NewSndChunkReplica
  { NewSndChunkReplica -> XFTPServer
server :: XFTPServer,
    NewSndChunkReplica -> ChunkReplicaId
replicaId :: ChunkReplicaId,
    NewSndChunkReplica -> APrivateAuthKey
replicaKey :: C.APrivateAuthKey,
    NewSndChunkReplica -> [(ChunkReplicaId, APrivateAuthKey)]
rcvIdsKeys :: [(ChunkReplicaId, C.APrivateAuthKey)]
  }
  deriving (Int -> NewSndChunkReplica -> ShowS
[NewSndChunkReplica] -> ShowS
NewSndChunkReplica -> String
(Int -> NewSndChunkReplica -> ShowS)
-> (NewSndChunkReplica -> String)
-> ([NewSndChunkReplica] -> ShowS)
-> Show NewSndChunkReplica
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NewSndChunkReplica -> ShowS
showsPrec :: Int -> NewSndChunkReplica -> ShowS
$cshow :: NewSndChunkReplica -> String
show :: NewSndChunkReplica -> String
$cshowList :: [NewSndChunkReplica] -> ShowS
showList :: [NewSndChunkReplica] -> ShowS
Show)

data SndFileChunkReplica = SndFileChunkReplica
  { SndFileChunkReplica -> Int64
sndChunkReplicaId :: Int64,
    SndFileChunkReplica -> XFTPServer
server :: XFTPServer,
    SndFileChunkReplica -> ChunkReplicaId
replicaId :: ChunkReplicaId,
    SndFileChunkReplica -> APrivateAuthKey
replicaKey :: C.APrivateAuthKey,
    SndFileChunkReplica -> [(ChunkReplicaId, APrivateAuthKey)]
rcvIdsKeys :: [(ChunkReplicaId, C.APrivateAuthKey)],
    SndFileChunkReplica -> SndFileReplicaStatus
replicaStatus :: SndFileReplicaStatus,
    SndFileChunkReplica -> Maybe Int64
delay :: Maybe Int64,
    SndFileChunkReplica -> Int
retries :: Int
  }
  deriving (Int -> SndFileChunkReplica -> ShowS
[SndFileChunkReplica] -> ShowS
SndFileChunkReplica -> String
(Int -> SndFileChunkReplica -> ShowS)
-> (SndFileChunkReplica -> String)
-> ([SndFileChunkReplica] -> ShowS)
-> Show SndFileChunkReplica
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndFileChunkReplica -> ShowS
showsPrec :: Int -> SndFileChunkReplica -> ShowS
$cshow :: SndFileChunkReplica -> String
show :: SndFileChunkReplica -> String
$cshowList :: [SndFileChunkReplica] -> ShowS
showList :: [SndFileChunkReplica] -> ShowS
Show)

data SndFileReplicaStatus
  = SFRSCreated
  | SFRSUploaded
  deriving (SndFileReplicaStatus -> SndFileReplicaStatus -> Bool
(SndFileReplicaStatus -> SndFileReplicaStatus -> Bool)
-> (SndFileReplicaStatus -> SndFileReplicaStatus -> Bool)
-> Eq SndFileReplicaStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SndFileReplicaStatus -> SndFileReplicaStatus -> Bool
== :: SndFileReplicaStatus -> SndFileReplicaStatus -> Bool
$c/= :: SndFileReplicaStatus -> SndFileReplicaStatus -> Bool
/= :: SndFileReplicaStatus -> SndFileReplicaStatus -> Bool
Eq, Int -> SndFileReplicaStatus -> ShowS
[SndFileReplicaStatus] -> ShowS
SndFileReplicaStatus -> String
(Int -> SndFileReplicaStatus -> ShowS)
-> (SndFileReplicaStatus -> String)
-> ([SndFileReplicaStatus] -> ShowS)
-> Show SndFileReplicaStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SndFileReplicaStatus -> ShowS
showsPrec :: Int -> SndFileReplicaStatus -> ShowS
$cshow :: SndFileReplicaStatus -> String
show :: SndFileReplicaStatus -> String
$cshowList :: [SndFileReplicaStatus] -> ShowS
showList :: [SndFileReplicaStatus] -> ShowS
Show)

instance FromField SndFileReplicaStatus where fromField :: FieldParser SndFileReplicaStatus
fromField = (Text -> Maybe SndFileReplicaStatus)
-> FieldParser SndFileReplicaStatus
forall a. Typeable a => (Text -> Maybe a) -> Field -> Ok a
fromTextField_ Text -> Maybe SndFileReplicaStatus
forall a. TextEncoding a => Text -> Maybe a
textDecode

instance ToField SndFileReplicaStatus where toField :: SndFileReplicaStatus -> SQLData
toField = Text -> SQLData
forall a. ToField a => a -> SQLData
toField (Text -> SQLData)
-> (SndFileReplicaStatus -> Text)
-> SndFileReplicaStatus
-> SQLData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SndFileReplicaStatus -> Text
forall a. TextEncoding a => a -> Text
textEncode

instance TextEncoding SndFileReplicaStatus where
  textDecode :: Text -> Maybe SndFileReplicaStatus
textDecode = \case
    Text
"created" -> SndFileReplicaStatus -> Maybe SndFileReplicaStatus
forall a. a -> Maybe a
Just SndFileReplicaStatus
SFRSCreated
    Text
"uploaded" -> SndFileReplicaStatus -> Maybe SndFileReplicaStatus
forall a. a -> Maybe a
Just SndFileReplicaStatus
SFRSUploaded
    Text
_ -> Maybe SndFileReplicaStatus
forall a. Maybe a
Nothing
  textEncode :: SndFileReplicaStatus -> Text
textEncode = \case
    SndFileReplicaStatus
SFRSCreated -> Text
"created"
    SndFileReplicaStatus
SFRSUploaded -> Text
"uploaded"

data DeletedSndChunkReplica = DeletedSndChunkReplica
  { DeletedSndChunkReplica -> Int64
deletedSndChunkReplicaId :: Int64,
    DeletedSndChunkReplica -> Int64
userId :: Int64,
    DeletedSndChunkReplica -> XFTPServer
server :: XFTPServer,
    DeletedSndChunkReplica -> ChunkReplicaId
replicaId :: ChunkReplicaId,
    DeletedSndChunkReplica -> APrivateAuthKey
replicaKey :: C.APrivateAuthKey,
    DeletedSndChunkReplica -> FileDigest
chunkDigest :: FileDigest,
    DeletedSndChunkReplica -> Maybe Int64
delay :: Maybe Int64,
    DeletedSndChunkReplica -> Int
retries :: Int
  }
  deriving (Int -> DeletedSndChunkReplica -> ShowS
[DeletedSndChunkReplica] -> ShowS
DeletedSndChunkReplica -> String
(Int -> DeletedSndChunkReplica -> ShowS)
-> (DeletedSndChunkReplica -> String)
-> ([DeletedSndChunkReplica] -> ShowS)
-> Show DeletedSndChunkReplica
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DeletedSndChunkReplica -> ShowS
showsPrec :: Int -> DeletedSndChunkReplica -> ShowS
$cshow :: DeletedSndChunkReplica -> String
show :: DeletedSndChunkReplica -> String
$cshowList :: [DeletedSndChunkReplica] -> ShowS
showList :: [DeletedSndChunkReplica] -> ShowS
Show)

data SentRecipientReplica = SentRecipientReplica
  { SentRecipientReplica -> Int
chunkNo :: Int,
    SentRecipientReplica -> XFTPServer
server :: XFTPServer,
    SentRecipientReplica -> Int
rcvNo :: Int,
    SentRecipientReplica -> ChunkReplicaId
replicaId :: ChunkReplicaId,
    SentRecipientReplica -> APrivateAuthKey
replicaKey :: C.APrivateAuthKey,
    SentRecipientReplica -> FileDigest
digest :: FileDigest,
    SentRecipientReplica -> FileSize Word32
chunkSize :: FileSize Word32
  }

data FileErrorType
  = -- | cannot proceed with download from not approved relays without proxy
    NOT_APPROVED
  | -- | max file size exceeded
    SIZE
  | -- | bad redirect data
    REDIRECT {FileErrorType -> String
redirectError :: String}
  | -- | file crypto error
    FILE_IO {FileErrorType -> String
fileIOError :: String}
  | -- | file not found or was deleted
    NO_FILE
  deriving (FileErrorType -> FileErrorType -> Bool
(FileErrorType -> FileErrorType -> Bool)
-> (FileErrorType -> FileErrorType -> Bool) -> Eq FileErrorType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileErrorType -> FileErrorType -> Bool
== :: FileErrorType -> FileErrorType -> Bool
$c/= :: FileErrorType -> FileErrorType -> Bool
/= :: FileErrorType -> FileErrorType -> Bool
Eq, Int -> FileErrorType -> ShowS
[FileErrorType] -> ShowS
FileErrorType -> String
(Int -> FileErrorType -> ShowS)
-> (FileErrorType -> String)
-> ([FileErrorType] -> ShowS)
-> Show FileErrorType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileErrorType -> ShowS
showsPrec :: Int -> FileErrorType -> ShowS
$cshow :: FileErrorType -> String
show :: FileErrorType -> String
$cshowList :: [FileErrorType] -> ShowS
showList :: [FileErrorType] -> ShowS
Show)

instance StrEncoding FileErrorType where
  strP :: Parser FileErrorType
strP =
    (Char -> Bool) -> Parser ByteString
A.takeTill (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ')
      Parser ByteString
-> (ByteString -> Parser FileErrorType) -> Parser FileErrorType
forall a b.
Parser ByteString a
-> (a -> Parser ByteString b) -> Parser ByteString b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        ByteString
"NOT_APPROVED" -> FileErrorType -> Parser FileErrorType
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileErrorType
NOT_APPROVED
        ByteString
"SIZE" -> FileErrorType -> Parser FileErrorType
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileErrorType
SIZE
        ByteString
"REDIRECT" -> String -> FileErrorType
REDIRECT (String -> FileErrorType)
-> Parser ByteString String -> Parser FileErrorType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
A.space Parser Char -> Parser ByteString String -> Parser ByteString String
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString String
textP)
        ByteString
"FILE_IO" -> String -> FileErrorType
FILE_IO (String -> FileErrorType)
-> Parser ByteString String -> Parser FileErrorType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
A.space Parser Char -> Parser ByteString String -> Parser ByteString String
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString String
textP)
        ByteString
"NO_FILE" -> FileErrorType -> Parser FileErrorType
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileErrorType
NO_FILE
        ByteString
_ -> String -> Parser FileErrorType
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"bad FileErrorType"
  strEncode :: FileErrorType -> ByteString
strEncode = \case
    FileErrorType
NOT_APPROVED -> ByteString
"NOT_APPROVED"
    FileErrorType
SIZE -> ByteString
"SIZE"
    REDIRECT String
e -> ByteString
"REDIRECT " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
encodeUtf8 (String -> Text
T.pack String
e)
    FILE_IO String
e -> ByteString
"FILE_IO " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
encodeUtf8 (String -> Text
T.pack String
e)
    FileErrorType
NO_FILE -> ByteString
"NO_FILE"

$(J.deriveJSON (sumTypeJSON id) ''FileErrorType)