module Signet.Unstable.Type.Signature where

import qualified Data.Bifunctor as Bifunctor
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as Ascii
import qualified Data.Word as Word
import qualified Signet.Unstable.Exception.InvalidSignature as InvalidSignature
import qualified Signet.Unstable.Exception.UnknownSignature as UnknownSignature
import qualified Signet.Unstable.Type.AsymmetricSignature as AsymmetricSignature
import qualified Signet.Unstable.Type.SymmetricSignature as SymmetricSignature

data Signature
  = Asymmetric AsymmetricSignature.AsymmetricSignature
  | Symmetric SymmetricSignature.SymmetricSignature
  deriving (Signature -> Signature -> Bool
(Signature -> Signature -> Bool)
-> (Signature -> Signature -> Bool) -> Eq Signature
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Signature -> Signature -> Bool
== :: Signature -> Signature -> Bool
$c/= :: Signature -> Signature -> Bool
/= :: Signature -> Signature -> Bool
Eq, Int -> Signature -> ShowS
[Signature] -> ShowS
Signature -> String
(Int -> Signature -> ShowS)
-> (Signature -> String)
-> ([Signature] -> ShowS)
-> Show Signature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Signature -> ShowS
showsPrec :: Int -> Signature -> ShowS
$cshow :: Signature -> String
show :: Signature -> String
$cshowList :: [Signature] -> ShowS
showList :: [Signature] -> ShowS
Show)

separator :: Word.Word8
separator :: Word8
separator = Word8
0x2c

asymmetricPrefix :: ByteString.ByteString
asymmetricPrefix :: ByteString
asymmetricPrefix = String -> ByteString
Ascii.pack String
"v1a"

symmetricPrefix :: ByteString.ByteString
symmetricPrefix :: ByteString
symmetricPrefix = String -> ByteString
Ascii.pack String
"v1"

parse :: ByteString.ByteString -> Either InvalidSignature.InvalidSignature (Either UnknownSignature.UnknownSignature Signature)
parse :: ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
parse ByteString
prefixed = do
  let (ByteString
prefix, ByteString
rest) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
ByteString.break (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
separator) ByteString
prefixed
  case Int -> ByteString -> ByteString
ByteString.drop Int
1 ByteString
rest of
    ByteString
byteString
      | ByteString
prefix ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
asymmetricPrefix ->
          (InvalidAsymmetricSignature -> InvalidSignature)
-> (AsymmetricSignature -> Either UnknownSignature Signature)
-> Either InvalidAsymmetricSignature AsymmetricSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b c d. (a -> b) -> (c -> d) -> Either a c -> Either b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
Bifunctor.bimap InvalidAsymmetricSignature -> InvalidSignature
InvalidSignature.InvalidAsymmetricSignature (Signature -> Either UnknownSignature Signature
forall a b. b -> Either a b
Right (Signature -> Either UnknownSignature Signature)
-> (AsymmetricSignature -> Signature)
-> AsymmetricSignature
-> Either UnknownSignature Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AsymmetricSignature -> Signature
Asymmetric) (Either InvalidAsymmetricSignature AsymmetricSignature
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> Either InvalidAsymmetricSignature AsymmetricSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$
            ByteString -> Either InvalidAsymmetricSignature AsymmetricSignature
AsymmetricSignature.parse ByteString
byteString
      | ByteString
prefix ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
symmetricPrefix ->
          (InvalidSymmetricSignature -> InvalidSignature)
-> (SymmetricSignature -> Either UnknownSignature Signature)
-> Either InvalidSymmetricSignature SymmetricSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b c d. (a -> b) -> (c -> d) -> Either a c -> Either b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
Bifunctor.bimap InvalidSymmetricSignature -> InvalidSignature
InvalidSignature.InvalidSymmetricSignature (Signature -> Either UnknownSignature Signature
forall a b. b -> Either a b
Right (Signature -> Either UnknownSignature Signature)
-> (SymmetricSignature -> Signature)
-> SymmetricSignature
-> Either UnknownSignature Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymmetricSignature -> Signature
Symmetric) (Either InvalidSymmetricSignature SymmetricSignature
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> Either InvalidSymmetricSignature SymmetricSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$
            ByteString -> Either InvalidSymmetricSignature SymmetricSignature
SymmetricSignature.parse ByteString
byteString
    ByteString
_ -> Either UnknownSignature Signature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. b -> Either a b
Right (Either UnknownSignature Signature
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> (UnknownSignature -> Either UnknownSignature Signature)
-> UnknownSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnknownSignature -> Either UnknownSignature Signature
forall a b. a -> Either a b
Left (UnknownSignature
 -> Either InvalidSignature (Either UnknownSignature Signature))
-> UnknownSignature
-> Either InvalidSignature (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$ ByteString -> UnknownSignature
UnknownSignature.MkUnknownSignature ByteString
prefixed

render :: Signature -> ByteString.ByteString
render :: Signature -> ByteString
render Signature
signature =
  case Signature
signature of
    Asymmetric AsymmetricSignature
asymmetricSignature ->
      ByteString
asymmetricPrefix
        ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Word8 -> ByteString
ByteString.singleton Word8
separator
        ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> AsymmetricSignature -> ByteString
AsymmetricSignature.render AsymmetricSignature
asymmetricSignature
    Symmetric SymmetricSignature
symmetricSignature ->
      ByteString
symmetricPrefix
        ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> Word8 -> ByteString
ByteString.singleton Word8
separator
        ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> SymmetricSignature -> ByteString
SymmetricSignature.render SymmetricSignature
symmetricSignature