{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Proto3.Suite.Form
( NamesOf
, NumberOf
, ProtoTypeOf
, OneOfOf
, CardinalityOf
, FieldNotFound
, FieldOrOneOfNotFound
, Packing(..)
, Cardinality(..)
, ProtoType(..)
, Association
, CardinalityOfMapped
, Wrapper
, RecoverCardinality
, RecoverProtoType
, MessageFieldType
, OptionalMessageFieldType
, RepeatedMessageFieldType
) where
import Data.Int (Int32, Int64)
import Data.Kind (Type)
import Data.Map qualified as M
import Data.Word (Word32, Word64)
import GHC.Exts (Constraint)
import GHC.TypeLits (ErrorMessage(..), Nat, Symbol, TypeError)
import Prelude hiding (String)
import Proto3.Suite.Types (Bytes, Enumerated, Commented, Fixed, ForceEmit, Nested,
NestedVec, PackedVec, Signed, String, UnpackedVec)
type family NamesOf (message :: Type) :: [Symbol]
type family NumberOf (message :: Type) (name :: Symbol) :: Nat
type family ProtoTypeOf (message :: Type) (name :: Symbol) :: ProtoType
type family OneOfOf (message :: Type) (name :: Symbol) :: Symbol
type family CardinalityOf (message :: Type) (name :: Symbol) :: Cardinality
type FieldNotFound (message :: Type) (name :: Symbol) =
'Text "Field " ':<>: 'ShowType name ':<>:
'Text " not found in message:" ':$$: 'ShowType message
type FieldOrOneOfNotFound (message :: Type) (name :: Symbol) =
'Text "Field or oneof " ':<>: 'ShowType name ':<>:
'Text " not found in message:" ':$$: 'ShowType message
data Packing
= Unpacked
| Packed
data Cardinality
= Implicit
| Optional
| Repeated Packing
data ProtoType
= Int32
| Int64
| SInt32
| SInt64
| UInt32
| UInt64
| Fixed32
| Fixed64
| SFixed32
| SFixed64
| String
| Bytes
| Bool
| Float
| Double
| Enumeration Type
| Message Type
| Map ProtoType ProtoType
data Association (key :: ProtoType) (value :: ProtoType)
type instance NamesOf (Association _ _) = '[ "key", "value" ]
type instance NumberOf (Association _ _) "key" = 1
type instance NumberOf (Association _ _) "value" = 2
type instance ProtoTypeOf (Association key _) "key" = key
type instance ProtoTypeOf (Association _ value) "value" = value
type instance OneOfOf (Association _ _) "key" = ""
type instance OneOfOf (Association _ _) "value" = ""
type instance CardinalityOf (Association _ _) "key" = 'Implicit
type instance CardinalityOf (Association _ value) "value" = CardinalityOfMapped value
type family CardinalityOfMapped (protoType :: ProtoType) :: Cardinality
where
CardinalityOfMapped ('Message _) = 'Optional
CardinalityOfMapped ('Map k v) = TypeError
( 'Text "Nested maps are disallowed, so this cannot be a mapped type:"
':$$: 'ShowType ('Map k v) )
CardinalityOfMapped _ = 'Implicit
data Wrapper (protoType :: ProtoType)
type instance NamesOf (Wrapper protoType) = '[ "value" ]
type instance NumberOf (Wrapper protoType) "value" = 1
type instance ProtoTypeOf (Wrapper protoType) "value" = protoType
type instance OneOfOf (Wrapper protoType) "value" = ""
type instance CardinalityOf (Wrapper protoType) "value" = 'Implicit
type family RecoverCardinality (haskellType :: Type) :: Cardinality
where
RecoverCardinality (Commented _ haskellType) = RecoverCardinality haskellType
RecoverCardinality (Maybe (ForceEmit _)) = 'Optional
RecoverCardinality (PackedVec _) = 'Repeated 'Packed
RecoverCardinality (UnpackedVec _) = 'Repeated 'Unpacked
RecoverCardinality (NestedVec _) = 'Repeated 'Unpacked
RecoverCardinality (Nested _) = 'Optional
RecoverCardinality (Enumerated _) = 'Implicit
RecoverCardinality (M.Map _ _) = 'Repeated 'Unpacked
RecoverCardinality Int32 = 'Implicit
RecoverCardinality Int64 = 'Implicit
RecoverCardinality (Signed Int32) = 'Implicit
RecoverCardinality (Signed Int64) = 'Implicit
RecoverCardinality Word32 = 'Implicit
RecoverCardinality Word64 = 'Implicit
RecoverCardinality (Fixed Word32) = 'Implicit
RecoverCardinality (Fixed Word64) = 'Implicit
RecoverCardinality (Signed (Fixed Int32)) = 'Implicit
RecoverCardinality (Signed (Fixed Int64)) = 'Implicit
RecoverCardinality (String _) = 'Implicit
RecoverCardinality (Bytes _) = 'Implicit
RecoverCardinality Bool = 'Implicit
RecoverCardinality Float = 'Implicit
RecoverCardinality Double = 'Implicit
type family RecoverProtoType (haskellType :: Type) :: ProtoType
where
RecoverProtoType Int32 = 'Int32
RecoverProtoType Int64 = 'Int64
RecoverProtoType (Signed Int32) = 'SInt32
RecoverProtoType (Signed Int64) = 'SInt64
RecoverProtoType Word32 = 'UInt32
RecoverProtoType Word64 = 'UInt64
RecoverProtoType (Fixed Word32) = 'Fixed32
RecoverProtoType (Fixed Word64) = 'Fixed64
RecoverProtoType (Signed (Fixed Int32)) = 'SFixed32
RecoverProtoType (Signed (Fixed Int64)) = 'SFixed64
RecoverProtoType (String _) = 'String
RecoverProtoType (Bytes _) = 'Bytes
RecoverProtoType Bool = 'Bool
RecoverProtoType Float = 'Float
RecoverProtoType Double = 'Double
RecoverProtoType (Commented _ haskellType) = RecoverProtoType haskellType
RecoverProtoType (Maybe (ForceEmit haskellType)) = RecoverProtoType haskellType
RecoverProtoType (PackedVec haskellType) = RecoverProtoType haskellType
RecoverProtoType (UnpackedVec haskellType) = RecoverProtoType haskellType
RecoverProtoType (Enumerated e) = 'Enumeration e
RecoverProtoType (Nested m) = 'Message m
RecoverProtoType (NestedVec m) = 'Message m
RecoverProtoType (M.Map k v) = 'Map (RecoverProtoType k) (RecoverProtoType v)
RecoverProtoType m = 'Message m
class ( RecoverCardinality haskellType ~ cardinality
, RecoverProtoType haskellType ~ protoType
) =>
MessageFieldType (cardinality :: Cardinality) (protoType :: ProtoType) (haskellType :: Type)
instance MessageFieldType 'Implicit 'Int32 Int32
instance MessageFieldType 'Implicit 'Int64 Int64
instance MessageFieldType 'Implicit 'SInt32 (Signed Int32)
instance MessageFieldType 'Implicit 'SInt64 (Signed Int64)
instance MessageFieldType 'Implicit 'UInt32 (Word32)
instance MessageFieldType 'Implicit 'UInt64 (Word64)
instance MessageFieldType 'Implicit 'Fixed32 (Fixed Word32)
instance MessageFieldType 'Implicit 'Fixed64 (Fixed Word64)
instance MessageFieldType 'Implicit 'SFixed32 (Signed (Fixed Int32))
instance MessageFieldType 'Implicit 'SFixed64 (Signed (Fixed Int64))
instance MessageFieldType 'Implicit 'String (String a)
instance MessageFieldType 'Implicit 'Bytes (Bytes a)
instance MessageFieldType 'Implicit 'Bool Bool
instance MessageFieldType 'Implicit 'Float Float
instance MessageFieldType 'Implicit 'Double Double
instance MessageFieldType 'Implicit ('Enumeration e) (Enumerated e)
instance MessageFieldType 'Optional 'Int32 (Maybe (ForceEmit Int32))
instance MessageFieldType 'Optional 'Int64 (Maybe (ForceEmit Int64))
instance MessageFieldType 'Optional 'SInt32 (Maybe (ForceEmit (Signed Int32)))
instance MessageFieldType 'Optional 'SInt64 (Maybe (ForceEmit (Signed Int64)))
instance MessageFieldType 'Optional 'UInt32 (Maybe (ForceEmit Word32))
instance MessageFieldType 'Optional 'UInt64 (Maybe (ForceEmit Word64))
instance MessageFieldType 'Optional 'Fixed32 (Maybe (ForceEmit (Fixed Word32)))
instance MessageFieldType 'Optional 'Fixed64 (Maybe (ForceEmit (Fixed Word64)))
instance MessageFieldType 'Optional 'SFixed32 (Maybe (ForceEmit (Signed (Fixed Int32))))
instance MessageFieldType 'Optional 'SFixed64 (Maybe (ForceEmit (Signed (Fixed Int64))))
instance MessageFieldType 'Optional 'String (Maybe (ForceEmit (String a)))
instance MessageFieldType 'Optional 'Bytes (Maybe (ForceEmit (Bytes a)))
instance MessageFieldType 'Optional 'Bool (Maybe (ForceEmit Bool))
instance MessageFieldType 'Optional 'Float (Maybe (ForceEmit Float))
instance MessageFieldType 'Optional 'Double (Maybe (ForceEmit Double))
instance MessageFieldType 'Optional ('Enumeration e) (Maybe (ForceEmit (Enumerated e)))
type family OptionalMessageFieldType (m :: Type) (haskellType :: Type)
where
OptionalMessageFieldType m (Nested m) = (() :: Constraint)
OptionalMessageFieldType m (Nested a) = TypeError
( 'Text "Expected reflected protobuf submessage type " ':<>: 'ShowType m ':$$:
'Text "Actual type: " ':<>: 'ShowType a )
OptionalMessageFieldType m haskellType = TypeError
( 'Text "When using a Haskell type to specify an optional protobuf submessage" ':$$:
'Text "(as opposed to repeated one or a submessage within a oneof)" ':$$:
'Text "you must wrap the Haskell reflection type in Proto3.Suite.Nested." ':$$:
'Text "Expected reflected protobuf submessage type " ':<>: 'ShowType m ':$$:
'Text "Haskell type provided: " ':<>: 'ShowType haskellType )
instance ( OptionalMessageFieldType m haskellType
, RecoverCardinality haskellType ~ 'Optional
, RecoverProtoType haskellType ~ 'Message m
) =>
MessageFieldType 'Optional ('Message m) haskellType
instance MessageFieldType ('Repeated 'Unpacked) 'Int32 (UnpackedVec Int32)
instance MessageFieldType ('Repeated 'Unpacked) 'Int64 (UnpackedVec Int64)
instance MessageFieldType ('Repeated 'Unpacked) 'SInt32 (UnpackedVec (Signed Int32))
instance MessageFieldType ('Repeated 'Unpacked) 'SInt64 (UnpackedVec (Signed Int64))
instance MessageFieldType ('Repeated 'Unpacked) 'UInt32 (UnpackedVec (Word32))
instance MessageFieldType ('Repeated 'Unpacked) 'UInt64 (UnpackedVec (Word64))
instance MessageFieldType ('Repeated 'Unpacked) 'Fixed32 (UnpackedVec (Fixed Word32))
instance MessageFieldType ('Repeated 'Unpacked) 'Fixed64 (UnpackedVec (Fixed Word64))
instance MessageFieldType ('Repeated 'Unpacked) 'SFixed32 (UnpackedVec (Signed (Fixed Int32)))
instance MessageFieldType ('Repeated 'Unpacked) 'SFixed64 (UnpackedVec (Signed (Fixed Int64)))
instance MessageFieldType ('Repeated 'Unpacked) 'String (UnpackedVec (String a))
instance MessageFieldType ('Repeated 'Unpacked) 'Bytes (UnpackedVec (Bytes a))
instance MessageFieldType ('Repeated 'Unpacked) 'Bool (UnpackedVec Bool)
instance MessageFieldType ('Repeated 'Unpacked) 'Float (UnpackedVec Float)
instance MessageFieldType ('Repeated 'Unpacked) 'Double (UnpackedVec Double)
instance MessageFieldType ('Repeated 'Unpacked) ('Enumeration e) (UnpackedVec (Enumerated e))
type family RepeatedMessageFieldType (m :: Type) (haskellType :: Type)
where
RepeatedMessageFieldType m (NestedVec m) = (() :: Constraint)
RepeatedMessageFieldType m (NestedVec a) = TypeError
( 'Text "Expected reflected protobuf submessage type " ':<>: 'ShowType m ':$$:
'Text "Actual type: " ':<>: 'ShowType a )
RepeatedMessageFieldType m haskellType = TypeError
( 'Text "When using a Haskell type to specify a repeated protobuf submessage" ':$$:
'Text "(as opposed to an optional one or a submessage within a oneof)" ':$$:
'Text "you must wrap the Haskell reflection type in Proto3.Suite.NestedVec." ':$$:
'Text "Expected reflected protobuf submessage type " ':<>: 'ShowType m ':$$:
'Text "Haskell type provided: " ':<>: 'ShowType haskellType )
instance ( RepeatedMessageFieldType m haskellType
, RecoverCardinality haskellType ~ 'Repeated 'Unpacked
, RecoverProtoType haskellType ~ 'Message m
) =>
MessageFieldType ('Repeated 'Unpacked) ('Message m) haskellType
instance ( MessageFieldType 'Implicit k kh
, MessageFieldType (CardinalityOfMapped v) v vh
) =>
MessageFieldType ('Repeated 'Unpacked) ('Map k v) (M.Map kh vh)
instance MessageFieldType ('Repeated 'Packed) 'Int32 (PackedVec Int32)
instance MessageFieldType ('Repeated 'Packed) 'Int64 (PackedVec Int64)
instance MessageFieldType ('Repeated 'Packed) 'SInt32 (PackedVec (Signed Int32))
instance MessageFieldType ('Repeated 'Packed) 'SInt64 (PackedVec (Signed Int64))
instance MessageFieldType ('Repeated 'Packed) 'UInt32 (PackedVec (Word32))
instance MessageFieldType ('Repeated 'Packed) 'UInt64 (PackedVec (Word64))
instance MessageFieldType ('Repeated 'Packed) 'Fixed32 (PackedVec (Fixed Word32))
instance MessageFieldType ('Repeated 'Packed) 'Fixed64 (PackedVec (Fixed Word64))
instance MessageFieldType ('Repeated 'Packed) 'SFixed32 (PackedVec (Signed (Fixed Int32)))
instance MessageFieldType ('Repeated 'Packed) 'SFixed64 (PackedVec (Signed (Fixed Int64)))
instance MessageFieldType ('Repeated 'Packed) 'Bool (PackedVec Bool)
instance MessageFieldType ('Repeated 'Packed) 'Float (PackedVec Float)
instance MessageFieldType ('Repeated 'Packed) 'Double (PackedVec Double)
instance MessageFieldType ('Repeated 'Packed) ('Enumeration e) (PackedVec (Enumerated e))