-- PacketClass.hs: OpenPGP (RFC9580) data types
-- Copyright © 2012-2026  Clint Adams
-- This software is released under the terms of the Expat license.
-- (See the LICENSE file).

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

module Codec.Encryption.OpenPGP.Types.Internal.PacketClass where

import Codec.Encryption.OpenPGP.Types.Internal.Base
import Codec.Encryption.OpenPGP.Types.Internal.PKITypes
import Codec.Encryption.OpenPGP.Types.Internal.Pkt

import Control.Lens (makeLenses)
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as BL
import Data.Data (Data)
import Data.List.NonEmpty (NonEmpty)
import Data.Text (Text)
import Data.Typeable (Typeable)
import Data.Word (Word8)
import qualified Data.Kind
import Prettyprinter (Pretty(..))

class Packet a where
  data PacketType a :: Data.Kind.Type
  packetType :: a -> PacketType a
  packetCode :: PacketType a -> Word8
  dynamicPacketCode :: a -> Word8
  toPkt :: a -> Pkt
  fromPktMaybe :: Pkt -> Maybe a
  fromPktEither :: Pkt -> Either String a
  
  fromPktMaybe = either (const Nothing) Just . fromPktEither
  dynamicPacketCode = packetCode . packetType

coercionError :: String -> Pkt -> Either String a
coercionError expected pkt =
  Left
    ("Cannot coerce non-" ++
     expected ++ " packet (tag " ++ show (pktTag pkt) ++ ")")

data PKESK (v :: PKESKPayloadVersion) where
  PKESK3Packet ::
       PacketVersion
    -> EightOctetKeyId
    -> PubKeyAlgorithm
    -> NonEmpty MPI
    -> PKESK 'PKESKV3
  PKESK6Packet ::
       BL.ByteString
    -> PubKeyAlgorithm
    -> BL.ByteString
    -> PKESK 'PKESKV6

deriving instance Eq (PKESK v)
deriving instance Show (PKESK v)

instance Packet (PKESK 'PKESKV3) where
  data PacketType (PKESK 'PKESKV3) = PKESKType
                                    deriving (Show, Eq)
  packetType _ = PKESKType
  packetCode _ = 1
  toPkt (PKESK3Packet version keyid pka mpis) =
    PKESKPkt (PKESKPayloadV3Packet (PKESKPayloadV3 version keyid pka mpis))
  fromPktEither (PKESKPkt (PKESKPayloadV3Packet (PKESKPayloadV3 _ keyid pka mpis))) =
    Right (PKESK3Packet 3 keyid pka mpis)
  fromPktEither (PKESKPkt (PKESKPayloadV6Packet (PKESKPayloadV6 _ _ _))) =
    Left "Cannot coerce PKESKv6 packet to PKESKv3"
  fromPktEither pkt = coercionError "PKESK" pkt

instance Pretty (PKESK 'PKESKV3) where
  pretty = pretty . toPkt

instance Packet (PKESK 'PKESKV6) where
  data PacketType (PKESK 'PKESKV6) = PKESK6Type
                                    deriving (Show, Eq)
  packetType _ = PKESK6Type
  packetCode _ = 1
  toPkt (PKESK6Packet recipientKeyIdentifier pka esk) =
    PKESKPkt (PKESKPayloadV6Packet (PKESKPayloadV6 recipientKeyIdentifier pka esk))
  fromPktEither (PKESKPkt (PKESKPayloadV6Packet (PKESKPayloadV6 recipientKeyIdentifier pka esk))) =
    Right (PKESK6Packet recipientKeyIdentifier pka esk)
  fromPktEither (PKESKPkt (PKESKPayloadV3Packet (PKESKPayloadV3 _ _ _ _))) =
    Left "Cannot coerce PKESKv3 packet to PKESKv6"
  fromPktEither pkt = coercionError "PKESKv6" pkt

instance Pretty (PKESK 'PKESKV6) where
  pretty = pretty . toPkt

newtype Signature =
  Signature
    { _signaturePayload :: SignaturePayload
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet Signature where
  data PacketType Signature = SignatureType
                              deriving (Show, Eq)
  packetType _ = SignatureType
  packetCode _ = 2
  toPkt (Signature a) = SignaturePkt a
  fromPktMaybe (SignaturePkt a) = Just (Signature a)
  fromPktMaybe _ = Nothing
  fromPktEither (SignaturePkt a) = Right (Signature a)
  fromPktEither pkt = coercionError "Signature" pkt

instance Pretty Signature where
  pretty = pretty . toPkt

data SignatureV (v :: SignaturePayloadVersion) where
  SignatureV3Packet :: SignaturePayloadV 'SigPayloadV3 -> SignatureV 'SigPayloadV3
  SignatureV4Packet :: SignaturePayloadV 'SigPayloadV4 -> SignatureV 'SigPayloadV4
  SignatureV6Packet :: SignaturePayloadV 'SigPayloadV6 -> SignatureV 'SigPayloadV6
  SignatureVOtherPacket :: SignaturePayloadV 'SigPayloadVOther -> SignatureV 'SigPayloadVOther

deriving instance Eq (SignatureV v)
deriving instance Show (SignatureV v)

data SomeSignatureV where
  SomeSignatureV :: SignatureV v -> SomeSignatureV

signaturePayloadFromSignatureV :: SignatureV v -> SignaturePayload
signaturePayloadFromSignatureV (SignatureV3Packet payload) = toSignaturePayload payload
signaturePayloadFromSignatureV (SignatureV4Packet payload) = toSignaturePayload payload
signaturePayloadFromSignatureV (SignatureV6Packet payload) = toSignaturePayload payload
signaturePayloadFromSignatureV (SignatureVOtherPacket payload) = toSignaturePayload payload

fromPktEitherSomeSignatureV :: Pkt -> Either String SomeSignatureV
fromPktEitherSomeSignatureV (SignaturePkt payload) =
  Right (someSignatureVFromPayload payload)
fromPktEitherSomeSignatureV pkt =
  coercionError "Signature" pkt

someSignatureVFromPayload :: SignaturePayload -> SomeSignatureV
someSignatureVFromPayload payload =
  case toSomeSignaturePayload payload of
    SomeSignaturePayload (typedPayload@SigPayloadV3Data {}) ->
      SomeSignatureV (SignatureV3Packet typedPayload)
    SomeSignaturePayload (typedPayload@SigPayloadV4Data {}) ->
      SomeSignatureV (SignatureV4Packet typedPayload)
    SomeSignaturePayload (typedPayload@SigPayloadV6Data {}) ->
      SomeSignatureV (SignatureV6Packet typedPayload)
    SomeSignaturePayload (typedPayload@SigPayloadOtherData {}) ->
      SomeSignatureV (SignatureVOtherPacket typedPayload)

instance Packet (SignatureV 'SigPayloadV3) where
  data PacketType (SignatureV 'SigPayloadV3) = SignatureV3Type
                                             deriving (Show, Eq)
  packetType _ = SignatureV3Type
  packetCode _ = 2
  toPkt = SignaturePkt . signaturePayloadFromSignatureV
  fromPktEither (SignaturePkt payload) =
    SignatureV3Packet <$> asSignaturePayloadV3 payload
  fromPktEither pkt = coercionError "SignatureV3" pkt

instance Pretty (SignatureV 'SigPayloadV3) where
  pretty = pretty . toPkt

instance Packet (SignatureV 'SigPayloadV4) where
  data PacketType (SignatureV 'SigPayloadV4) = SignatureV4Type
                                             deriving (Show, Eq)
  packetType _ = SignatureV4Type
  packetCode _ = 2
  toPkt = SignaturePkt . signaturePayloadFromSignatureV
  fromPktEither (SignaturePkt payload) =
    SignatureV4Packet <$> asSignaturePayloadV4 payload
  fromPktEither pkt = coercionError "SignatureV4" pkt

instance Pretty (SignatureV 'SigPayloadV4) where
  pretty = pretty . toPkt

instance Packet (SignatureV 'SigPayloadV6) where
  data PacketType (SignatureV 'SigPayloadV6) = SignatureV6Type
                                             deriving (Show, Eq)
  packetType _ = SignatureV6Type
  packetCode _ = 2
  toPkt = SignaturePkt . signaturePayloadFromSignatureV
  fromPktEither (SignaturePkt payload) =
    SignatureV6Packet <$> asSignaturePayloadV6 payload
  fromPktEither pkt = coercionError "SignatureV6" pkt

instance Pretty (SignatureV 'SigPayloadV6) where
  pretty = pretty . toPkt

instance Packet (SignatureV 'SigPayloadVOther) where
  data PacketType (SignatureV 'SigPayloadVOther) = SignatureVOtherType
                                                 deriving (Show, Eq)
  packetType _ = SignatureVOtherType
  packetCode _ = 2
  toPkt = SignaturePkt . signaturePayloadFromSignatureV
  fromPktEither (SignaturePkt payload) =
    SignatureVOtherPacket <$> asSignaturePayloadOther payload
  fromPktEither pkt = coercionError "SignatureVOther" pkt

instance Pretty (SignatureV 'SigPayloadVOther) where
  pretty = pretty . toPkt

data SKESK (v :: SKESKPayloadVersion) where
  SKESK4Packet ::
       SymmetricAlgorithm
    -> S2K
    -> Maybe BL.ByteString
    -> SKESK 'SKESKV4
  SKESK6Packet ::
       SymmetricAlgorithm
    -> AEADAlgorithm
    -> S2K
    -> BL.ByteString
    -> BL.ByteString
    -> BL.ByteString
    -> SKESK 'SKESKV6

deriving instance Eq (SKESK v)
deriving instance Show (SKESK v)

instance Packet (SKESK 'SKESKV4) where
  data PacketType (SKESK 'SKESKV4) = SKESKType
                                    deriving (Show, Eq)
  packetType _ = SKESKType
  packetCode _ = 3
  toPkt (SKESK4Packet symalgo s2k esk) =
    SKESKPkt (SKESKPayloadV4Packet (SKESKPayloadV4 symalgo s2k esk))
  fromPktEither (SKESKPkt (SKESKPayloadV4Packet (SKESKPayloadV4 symalgo s2k esk))) =
    Right (SKESK4Packet symalgo s2k esk)
  fromPktEither (SKESKPkt (SKESKPayloadV6Packet (SKESKPayloadV6 _ _ _ _ _ _))) =
    Left "Cannot coerce SKESKv6 packet to SKESKv4"
  fromPktEither pkt = coercionError "SKESK" pkt

instance Pretty (SKESK 'SKESKV4) where
  pretty = pretty . toPkt

instance Packet (SKESK 'SKESKV6) where
  data PacketType (SKESK 'SKESKV6) = SKESK6Type
                                    deriving (Show, Eq)
  packetType _ = SKESK6Type
  packetCode _ = 3
  toPkt (SKESK6Packet symalgo aead s2k iv esk tag) =
    SKESKPkt (SKESKPayloadV6Packet (SKESKPayloadV6 symalgo aead s2k iv esk tag))
  fromPktEither (SKESKPkt (SKESKPayloadV6Packet (SKESKPayloadV6 symalgo aead s2k iv esk tag))) =
    Right (SKESK6Packet symalgo aead s2k iv esk tag)
  fromPktEither (SKESKPkt (SKESKPayloadV4Packet (SKESKPayloadV4 _ _ _))) =
    Left "Cannot coerce SKESKv4 packet to SKESKv6"
  fromPktEither pkt = coercionError "SKESKv6" pkt

instance Pretty (SKESK 'SKESKV6) where
  pretty = pretty . toPkt

data OnePassSignature (v :: OnePassSignatureVersion) where
  OnePassSignatureV3Packet ::
       PacketVersion
    -> SigType
    -> HashAlgorithm
    -> PubKeyAlgorithm
    -> EightOctetKeyId
    -> NestedFlag
    -> OnePassSignature 'OPSV3
  OnePassSignatureV6Packet ::
       SigType
    -> HashAlgorithm
    -> PubKeyAlgorithm
    -> SignatureSalt
    -> ByteString
    -> NestedFlag
    -> OnePassSignature 'OPSV6

deriving instance Eq (OnePassSignature v)
deriving instance Show (OnePassSignature v)

instance Packet (OnePassSignature 'OPSV3) where
  data PacketType (OnePassSignature 'OPSV3) = OnePassSignatureType
                                            deriving (Show, Eq)
  packetType _ = OnePassSignatureType
  packetCode _ = 4
  toPkt (OnePassSignatureV3Packet a b c d e f) =
    OnePassSignaturePkt (OPSPayloadV3Packet (OPSPayloadV3 a b c d e f))
  fromPktEither (OnePassSignaturePkt (OPSPayloadV3Packet (OPSPayloadV3 a b c d e f))) =
    Right (OnePassSignatureV3Packet a b c d e f)
  fromPktEither pkt = coercionError "OnePassSignature" pkt

instance Pretty (OnePassSignature 'OPSV3) where
  pretty = pretty . toPkt

instance Packet (OnePassSignature 'OPSV6) where
  data PacketType (OnePassSignature 'OPSV6) = OnePassSignatureV6Type
                                            deriving (Show, Eq)
  packetType _ = OnePassSignatureV6Type
  packetCode _ = 4
  toPkt (OnePassSignatureV6Packet a b c d e f) =
    OnePassSignaturePkt (OPSPayloadV6Packet (OPSPayloadV6 a b c d e f))
  fromPktEither (OnePassSignaturePkt (OPSPayloadV6Packet (OPSPayloadV6 a b c d e f))) =
    Right (OnePassSignatureV6Packet a b c d e f)
  fromPktEither pkt = coercionError "OnePassSignatureV6" pkt

instance Pretty (OnePassSignature 'OPSV6) where
  pretty = pretty . toPkt

data SecretKey =
  SecretKey
    { _secretKeyPKPayload :: SomePKPayload
    , _secretKeySKAddendum :: SKAddendum
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet SecretKey where
  data PacketType SecretKey = SecretKeyType
                              deriving (Show, Eq)
  packetType _ = SecretKeyType
  packetCode _ = 5
  toPkt (SecretKey a b) = SecretKeyPkt a b
  fromPktEither (SecretKeyPkt a b) = Right (SecretKey a b)
  fromPktEither pkt = coercionError "SecretKey" pkt

instance Pretty SecretKey where
  pretty = pretty . toPkt

newtype PublicKey =
  PublicKey
    { _publicKeyPKPayload :: SomePKPayload
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet PublicKey where
  data PacketType PublicKey = PublicKeyType
                              deriving (Show, Eq)
  packetType _ = PublicKeyType
  packetCode _ = 6
  toPkt (PublicKey a) = PublicKeyPkt a
  fromPktEither (PublicKeyPkt a) = Right (PublicKey a)
  fromPktEither pkt = coercionError "PublicKey" pkt

instance Pretty PublicKey where
  pretty = pretty . toPkt

data SecretSubkey =
  SecretSubkey
    { _secretSubkeyPKPayload :: SomePKPayload
    , _secretSubkeySKAddendum :: SKAddendum
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet SecretSubkey where
  data PacketType SecretSubkey = SecretSubkeyType
                                 deriving (Show, Eq)
  packetType _ = SecretSubkeyType
  packetCode _ = 7
  toPkt (SecretSubkey a b) = SecretSubkeyPkt a b
  fromPktEither (SecretSubkeyPkt a b) = Right (SecretSubkey a b)
  fromPktEither pkt = coercionError "SecretSubkey" pkt

instance Pretty SecretSubkey where
  pretty = pretty . toPkt

data CompressedData =
  CompressedData
    { _compressedDataCompressionAlgorithm :: CompressionAlgorithm
    , _compressedDataPayload :: CompressedDataPayload
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet CompressedData where
  data PacketType CompressedData = CompressedDataType
                                   deriving (Show, Eq)
  packetType _ = CompressedDataType
  packetCode _ = 8
  toPkt (CompressedData a b) = CompressedDataPkt a b
  fromPktEither (CompressedDataPkt a b) = Right (CompressedData a b)
  fromPktEither pkt = coercionError "CompressedData" pkt

instance Pretty CompressedData where
  pretty = pretty . toPkt

newtype SymEncData =
  SymEncData
    { _symEncDataPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet SymEncData where
  data PacketType SymEncData = SymEncDataType
                               deriving (Show, Eq)
  packetType _ = SymEncDataType
  packetCode _ = 9
  toPkt (SymEncData a) = SymEncDataPkt a
  fromPktEither (SymEncDataPkt a) = Right (SymEncData a)
  fromPktEither pkt = coercionError "SymEncData" pkt

instance Pretty SymEncData where
  pretty = pretty . toPkt

newtype Marker =
  Marker
    { _markerPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet Marker where
  data PacketType Marker = MarkerType
                           deriving (Show, Eq)
  packetType _ = MarkerType
  packetCode _ = 10
  toPkt (Marker a) = MarkerPkt a
  fromPktEither (MarkerPkt a) = Right (Marker a)
  fromPktEither pkt = coercionError "Marker" pkt

instance Pretty Marker where
  pretty = pretty . toPkt

data LiteralData =
  LiteralData
    { _literalDataDataType :: DataType
    , _literalDataFileName :: FileName
    , _literalDataTimeStamp :: ThirtyTwoBitTimeStamp
    , _literalDataPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet LiteralData where
  data PacketType LiteralData = LiteralDataType
                                deriving (Show, Eq)
  packetType _ = LiteralDataType
  packetCode _ = 11
  toPkt (LiteralData a b c d) = LiteralDataPkt a b c d
  fromPktEither (LiteralDataPkt a b c d) = Right (LiteralData a b c d)
  fromPktEither pkt = coercionError "LiteralData" pkt

instance Pretty LiteralData where
  pretty = pretty . toPkt

newtype Trust =
  Trust
    { _trustPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet Trust where
  data PacketType Trust = TrustType
                          deriving (Show, Eq)
  packetType _ = TrustType
  packetCode _ = 12
  toPkt (Trust a) = TrustPkt a
  fromPktEither (TrustPkt a) = Right (Trust a)
  fromPktEither pkt = coercionError "Trust" pkt

instance Pretty Trust where
  pretty = pretty . toPkt

newtype UserId =
  UserId
    { _userIdPayload :: Text
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet UserId where
  data PacketType UserId = UserIdType
                           deriving (Show, Eq)
  packetType _ = UserIdType
  packetCode _ = 13
  toPkt (UserId a) = UserIdPkt a
  fromPktEither (UserIdPkt a) = Right (UserId a)
  fromPktEither pkt = coercionError "UserId" pkt

instance Pretty UserId where
  pretty = pretty . toPkt

newtype PublicSubkey =
  PublicSubkey
    { _publicSubkeyPKPayload :: SomePKPayload
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet PublicSubkey where
  data PacketType PublicSubkey = PublicSubkeyType
                                 deriving (Show, Eq)
  packetType _ = PublicSubkeyType
  packetCode _ = 14
  toPkt (PublicSubkey a) = PublicSubkeyPkt a
  fromPktEither (PublicSubkeyPkt a) = Right (PublicSubkey a)
  fromPktEither pkt = coercionError "PublicSubkey" pkt

instance Pretty PublicSubkey where
  pretty = pretty . toPkt

newtype UserAttribute =
  UserAttribute
    { _userAttributeSubPackets :: [UserAttrSubPacket]
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet UserAttribute where
  data PacketType UserAttribute = UserAttributeType
                                  deriving (Show, Eq)
  packetType _ = UserAttributeType
  packetCode _ = 17
  toPkt (UserAttribute a) = UserAttributePkt a
  fromPktEither (UserAttributePkt a) = Right (UserAttribute a)
  fromPktEither pkt = coercionError "UserAttribute" pkt

instance Pretty UserAttribute where
  pretty = pretty . toPkt

data SymEncIntegrityProtectedData =
  SymEncIntegrityProtectedData
    { _symEncIntegrityProtectedDataPacketVersion :: PacketVersion
    , _symEncIntegrityProtectedDataPayload :: ByteString
    }
  | SymEncIntegrityProtectedDataV2
      SymmetricAlgorithm
      AEADAlgorithm
      Word8
      Salt
      ByteString
  deriving (Data, Eq, Show, Typeable)

instance Packet SymEncIntegrityProtectedData where
  data PacketType
       SymEncIntegrityProtectedData = SymEncIntegrityProtectedDataType
                                        deriving (Show, Eq)
  packetType _ = SymEncIntegrityProtectedDataType
  packetCode _ = 18
  toPkt (SymEncIntegrityProtectedData a b) = SymEncIntegrityProtectedDataPkt (SEIPD1 a b)
  toPkt (SymEncIntegrityProtectedDataV2 a b c d e) =
    SymEncIntegrityProtectedDataPkt (SEIPD2 a b c d e)
  fromPktEither (SymEncIntegrityProtectedDataPkt (SEIPD1 a b)) =
    Right (SymEncIntegrityProtectedData a b)
  fromPktEither (SymEncIntegrityProtectedDataPkt (SEIPD2 a b c d e)) =
    Right (SymEncIntegrityProtectedDataV2 a b c d e)
  fromPktEither pkt = coercionError "SymEncIntegrityProtectedData" pkt

instance Pretty SymEncIntegrityProtectedData where
  pretty = pretty . toPkt

newtype ModificationDetectionCode =
  ModificationDetectionCode
    { _modificationDetectionCodePayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet ModificationDetectionCode where
  data PacketType
       ModificationDetectionCode = ModificationDetectionCodeType
                                     deriving (Show, Eq)
  packetType _ = ModificationDetectionCodeType
  packetCode _ = 19
  toPkt (ModificationDetectionCode a) = ModificationDetectionCodePkt a
  fromPktEither (ModificationDetectionCodePkt a) = Right (ModificationDetectionCode a)
  fromPktEither pkt = coercionError "ModificationDetectionCode" pkt

instance Pretty ModificationDetectionCode where
  pretty = pretty . toPkt

data OtherPacket =
  OtherPacket
    { _otherPacketType :: Word8
    , _otherPacketPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet OtherPacket where
  data PacketType OtherPacket = OtherPacketType
                                deriving (Show, Eq)
  packetType _ = OtherPacketType
  packetCode _ = error "OtherPacket has no static packet type code"
  dynamicPacketCode = _otherPacketType
  toPkt (OtherPacket a b) = OtherPacketPkt a b
  fromPktEither (OtherPacketPkt a b) = Right (OtherPacket a b)
  fromPktEither pkt = coercionError "OtherPacket" pkt

instance Pretty OtherPacket where
  pretty = pretty . toPkt

data BrokenPacket =
  BrokenPacket
    { _brokenPacketParseError :: String
    , _brokenPacketType :: Word8
    , _brokenPacketPayload :: ByteString
    }
  deriving (Data, Eq, Show, Typeable)

instance Packet BrokenPacket where
  data PacketType BrokenPacket = BrokenPacketType
                                 deriving (Show, Eq)
  packetType _ = BrokenPacketType
  packetCode _ = error "BrokenPacket has no static packet type code"
  dynamicPacketCode = _brokenPacketType
  toPkt (BrokenPacket a b c) = BrokenPacketPkt a b c
  fromPktEither (BrokenPacketPkt a b c) = Right (BrokenPacket a b c)
  fromPktEither pkt = coercionError "BrokenPacket" pkt

instance Pretty BrokenPacket where
  pretty = pretty . toPkt

$(makeLenses ''Signature)

$(makeLenses ''SecretKey)

$(makeLenses ''PublicKey)

$(makeLenses ''SecretSubkey)

$(makeLenses ''CompressedData)

$(makeLenses ''SymEncData)

$(makeLenses ''Marker)

$(makeLenses ''LiteralData)

$(makeLenses ''Trust)

$(makeLenses ''UserId)

$(makeLenses ''PublicSubkey)

$(makeLenses ''UserAttribute)

$(makeLenses ''SymEncIntegrityProtectedData)

$(makeLenses ''ModificationDetectionCode)

$(makeLenses ''OtherPacket)

$(makeLenses ''BrokenPacket)
