-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Wire.API.MLS.Capabilities where

import Imports
import Test.QuickCheck
import Wire.API.MLS.CipherSuite
import Wire.API.MLS.Serialisation
import Wire.Arbitrary

-- | https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol-20/draft-ietf-mls-protocol.html#section-7.2-2
data Capabilities = Capabilities
  { Capabilities -> [Word16]
versions :: [Word16],
    Capabilities -> [CipherSuite]
ciphersuites :: [CipherSuite],
    Capabilities -> [Word16]
extensions :: [Word16],
    Capabilities -> [Word16]
proposals :: [Word16],
    Capabilities -> [Word16]
credentials :: [Word16]
  }
  deriving (Int -> Capabilities -> ShowS
[Capabilities] -> ShowS
Capabilities -> String
(Int -> Capabilities -> ShowS)
-> (Capabilities -> String)
-> ([Capabilities] -> ShowS)
-> Show Capabilities
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Capabilities -> ShowS
showsPrec :: Int -> Capabilities -> ShowS
$cshow :: Capabilities -> String
show :: Capabilities -> String
$cshowList :: [Capabilities] -> ShowS
showList :: [Capabilities] -> ShowS
Show, Capabilities -> Capabilities -> Bool
(Capabilities -> Capabilities -> Bool)
-> (Capabilities -> Capabilities -> Bool) -> Eq Capabilities
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Capabilities -> Capabilities -> Bool
== :: Capabilities -> Capabilities -> Bool
$c/= :: Capabilities -> Capabilities -> Bool
/= :: Capabilities -> Capabilities -> Bool
Eq, (forall x. Capabilities -> Rep Capabilities x)
-> (forall x. Rep Capabilities x -> Capabilities)
-> Generic Capabilities
forall x. Rep Capabilities x -> Capabilities
forall x. Capabilities -> Rep Capabilities x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Capabilities -> Rep Capabilities x
from :: forall x. Capabilities -> Rep Capabilities x
$cto :: forall x. Rep Capabilities x -> Capabilities
to :: forall x. Rep Capabilities x -> Capabilities
Generic)
  deriving (Gen Capabilities
Gen Capabilities
-> (Capabilities -> [Capabilities]) -> Arbitrary Capabilities
Capabilities -> [Capabilities]
forall a. Gen a -> (a -> [a]) -> Arbitrary a
$carbitrary :: Gen Capabilities
arbitrary :: Gen Capabilities
$cshrink :: Capabilities -> [Capabilities]
shrink :: Capabilities -> [Capabilities]
Arbitrary) via (GenericUniform Capabilities)

instance ParseMLS Capabilities where
  parseMLS :: Get Capabilities
parseMLS =
    [Word16]
-> [CipherSuite]
-> [Word16]
-> [Word16]
-> [Word16]
-> Capabilities
Capabilities
      ([Word16]
 -> [CipherSuite]
 -> [Word16]
 -> [Word16]
 -> [Word16]
 -> Capabilities)
-> Get [Word16]
-> Get
     ([CipherSuite] -> [Word16] -> [Word16] -> [Word16] -> Capabilities)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall w a. (Binary w, Integral w) => Get a -> Get [a]
parseMLSVector @VarInt Get Word16
forall a. ParseMLS a => Get a
parseMLS
      Get
  ([CipherSuite] -> [Word16] -> [Word16] -> [Word16] -> Capabilities)
-> Get [CipherSuite]
-> Get ([Word16] -> [Word16] -> [Word16] -> Capabilities)
forall a b. Get (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall w a. (Binary w, Integral w) => Get a -> Get [a]
parseMLSVector @VarInt Get CipherSuite
forall a. ParseMLS a => Get a
parseMLS
      Get ([Word16] -> [Word16] -> [Word16] -> Capabilities)
-> Get [Word16] -> Get ([Word16] -> [Word16] -> Capabilities)
forall a b. Get (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall w a. (Binary w, Integral w) => Get a -> Get [a]
parseMLSVector @VarInt Get Word16
forall a. ParseMLS a => Get a
parseMLS
      Get ([Word16] -> [Word16] -> Capabilities)
-> Get [Word16] -> Get ([Word16] -> Capabilities)
forall a b. Get (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall w a. (Binary w, Integral w) => Get a -> Get [a]
parseMLSVector @VarInt Get Word16
forall a. ParseMLS a => Get a
parseMLS
      Get ([Word16] -> Capabilities) -> Get [Word16] -> Get Capabilities
forall a b. Get (a -> b) -> Get a -> Get b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall w a. (Binary w, Integral w) => Get a -> Get [a]
parseMLSVector @VarInt Get Word16
forall a. ParseMLS a => Get a
parseMLS

instance SerialiseMLS Capabilities where
  serialiseMLS :: Capabilities -> Put
serialiseMLS Capabilities
caps = do
    forall w a. (Binary w, Integral w) => (a -> Put) -> [a] -> Put
serialiseMLSVector @VarInt Word16 -> Put
forall a. SerialiseMLS a => a -> Put
serialiseMLS Capabilities
caps.versions
    forall w a. (Binary w, Integral w) => (a -> Put) -> [a] -> Put
serialiseMLSVector @VarInt CipherSuite -> Put
forall a. SerialiseMLS a => a -> Put
serialiseMLS Capabilities
caps.ciphersuites
    forall w a. (Binary w, Integral w) => (a -> Put) -> [a] -> Put
serialiseMLSVector @VarInt Word16 -> Put
forall a. SerialiseMLS a => a -> Put
serialiseMLS Capabilities
caps.extensions
    forall w a. (Binary w, Integral w) => (a -> Put) -> [a] -> Put
serialiseMLSVector @VarInt Word16 -> Put
forall a. SerialiseMLS a => a -> Put
serialiseMLS Capabilities
caps.proposals
    forall w a. (Binary w, Integral w) => (a -> Put) -> [a] -> Put
serialiseMLSVector @VarInt Word16 -> Put
forall a. SerialiseMLS a => a -> Put
serialiseMLS Capabilities
caps.credentials