{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
module Data.ProtoLens.Message (
Message(..),
Tag(..),
allFields,
FieldDescriptor(..),
fieldDescriptorName,
isRequired,
FieldAccessor(..),
WireDefault(..),
Packing(..),
FieldTypeDescriptor(..),
ScalarField(..),
MessageOrGroup(..),
FieldDefault(..),
MessageEnum(..),
build,
Registry,
register,
lookupRegistered,
SomeMessageType(..),
matchAnyMessage,
AnyMessageDescriptor(..),
maybeLens,
reverseRepeatedFields,
FieldSet,
TaggedValue(..),
discardUnknownFields,
) where
import qualified Data.ByteString as B
import Data.Int
import qualified Data.Map as Map
import Data.Map (Map)
import Data.Maybe (fromMaybe)
import Data.Proxy (Proxy(..))
import qualified Data.Text as T
import Data.Word
import Lens.Family2 (Lens', over, set)
import Lens.Family2.Unchecked (lens)
import qualified Data.Semigroup as Semigroup
import Data.ProtoLens.Encoding.Bytes (Builder, Parser)
import Data.ProtoLens.Encoding.Wire
( Tag(..)
, TaggedValue(..)
)
class Message msg where
messageName :: Proxy msg -> T.Text
packedMessageDescriptor :: Proxy msg -> B.ByteString
packedFileDescriptor :: Proxy msg -> B.ByteString
defMessage :: msg
fieldsByTag :: Map Tag (FieldDescriptor msg)
fieldsByTextFormatName :: Map String (FieldDescriptor msg)
fieldsByTextFormatName =
[(String, FieldDescriptor msg)] -> Map String (FieldDescriptor msg)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(String
n, FieldDescriptor msg
f) | f :: FieldDescriptor msg
f@(FieldDescriptor String
n FieldTypeDescriptor value
_ FieldAccessor msg value
_) <- [FieldDescriptor msg]
forall msg. Message msg => [FieldDescriptor msg]
allFields]
unknownFields :: Lens' msg FieldSet
parseMessage :: Parser msg
buildMessage :: msg -> Builder
allFields :: Message msg => [FieldDescriptor msg]
allFields :: forall msg. Message msg => [FieldDescriptor msg]
allFields = Map Tag (FieldDescriptor msg) -> [FieldDescriptor msg]
forall k a. Map k a -> [a]
Map.elems Map Tag (FieldDescriptor msg)
forall msg. Message msg => Map Tag (FieldDescriptor msg)
fieldsByTag
type FieldSet = [TaggedValue]
data FieldDescriptor msg where
FieldDescriptor :: String
-> FieldTypeDescriptor value -> FieldAccessor msg value
-> FieldDescriptor msg
fieldDescriptorName :: FieldDescriptor msg -> String
fieldDescriptorName :: forall msg. FieldDescriptor msg -> String
fieldDescriptorName (FieldDescriptor String
name FieldTypeDescriptor value
_ FieldAccessor msg value
_) = String
name
isRequired :: FieldDescriptor msg -> Bool
isRequired :: forall msg. FieldDescriptor msg -> Bool
isRequired (FieldDescriptor String
_ FieldTypeDescriptor value
_ (PlainField WireDefault value
Required Lens' msg value
_)) = Bool
True
isRequired FieldDescriptor msg
_ = Bool
False
data FieldAccessor msg value where
PlainField :: WireDefault value -> Lens' msg value
-> FieldAccessor msg value
OptionalField :: Lens' msg (Maybe value) -> FieldAccessor msg value
RepeatedField :: Packing -> Lens' msg [value] -> FieldAccessor msg value
MapField :: (Ord key, Message entry) => Lens' entry key -> Lens' entry value
-> Lens' msg (Map key value) -> FieldAccessor msg entry
data WireDefault value where
Required :: WireDefault value
Optional :: (FieldDefault value, Eq value) => WireDefault value
class FieldDefault value where
fieldDefault :: value
instance FieldDefault Bool where
fieldDefault :: Bool
fieldDefault = Bool
False
instance FieldDefault Int32 where
fieldDefault :: Int32
fieldDefault = Int32
0
instance FieldDefault Int64 where
fieldDefault :: Int64
fieldDefault = Int64
0
instance FieldDefault Word32 where
fieldDefault :: Word32
fieldDefault = Word32
0
instance FieldDefault Word64 where
fieldDefault :: Word64
fieldDefault = Word64
0
instance FieldDefault Float where
fieldDefault :: Float
fieldDefault = Float
0
instance FieldDefault Double where
fieldDefault :: Double
fieldDefault = Double
0
instance FieldDefault B.ByteString where
fieldDefault :: ByteString
fieldDefault = ByteString
B.empty
instance FieldDefault T.Text where
fieldDefault :: Text
fieldDefault = Text
T.empty
data Packing = Packed | Unpacked
data FieldTypeDescriptor value where
MessageField :: Message value => MessageOrGroup -> FieldTypeDescriptor value
ScalarField :: ScalarField value -> FieldTypeDescriptor value
deriving instance Show (FieldTypeDescriptor value)
data MessageOrGroup = MessageType | GroupType
deriving Int -> MessageOrGroup -> ShowS
[MessageOrGroup] -> ShowS
MessageOrGroup -> String
(Int -> MessageOrGroup -> ShowS)
-> (MessageOrGroup -> String)
-> ([MessageOrGroup] -> ShowS)
-> Show MessageOrGroup
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MessageOrGroup -> ShowS
showsPrec :: Int -> MessageOrGroup -> ShowS
$cshow :: MessageOrGroup -> String
show :: MessageOrGroup -> String
$cshowList :: [MessageOrGroup] -> ShowS
showList :: [MessageOrGroup] -> ShowS
Show
data ScalarField t where
EnumField :: MessageEnum value => ScalarField value
Int32Field :: ScalarField Int32
Int64Field :: ScalarField Int64
UInt32Field :: ScalarField Word32
UInt64Field :: ScalarField Word64
SInt32Field :: ScalarField Int32
SInt64Field :: ScalarField Int64
Fixed32Field :: ScalarField Word32
Fixed64Field :: ScalarField Word64
SFixed32Field :: ScalarField Int32
SFixed64Field :: ScalarField Int64
FloatField :: ScalarField Float
DoubleField :: ScalarField Double
BoolField :: ScalarField Bool
StringField :: ScalarField T.Text
BytesField :: ScalarField B.ByteString
deriving instance Show (ScalarField value)
matchAnyMessage :: forall value . FieldTypeDescriptor value -> Maybe (AnyMessageDescriptor value)
matchAnyMessage :: forall value.
FieldTypeDescriptor value -> Maybe (AnyMessageDescriptor value)
matchAnyMessage (MessageField MessageOrGroup
_)
| Proxy value -> Text
forall msg. Message msg => Proxy msg -> Text
messageName (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @value) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"google.protobuf.Any"
, Just (FieldDescriptor String
_ (ScalarField ScalarField value
StringField) (PlainField WireDefault value
Optional Lens' value value
typeUrlLens))
<- Tag
-> Map Tag (FieldDescriptor value) -> Maybe (FieldDescriptor value)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Tag
1 (forall msg. Message msg => Map Tag (FieldDescriptor msg)
fieldsByTag @value)
, Just (FieldDescriptor String
_ (ScalarField ScalarField value
BytesField) (PlainField WireDefault value
Optional Lens' value value
valueLens))
<- Tag
-> Map Tag (FieldDescriptor value) -> Maybe (FieldDescriptor value)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Tag
2 (forall msg. Message msg => Map Tag (FieldDescriptor msg)
fieldsByTag @value)
= AnyMessageDescriptor value -> Maybe (AnyMessageDescriptor value)
forall a. a -> Maybe a
Just (AnyMessageDescriptor value -> Maybe (AnyMessageDescriptor value))
-> AnyMessageDescriptor value -> Maybe (AnyMessageDescriptor value)
forall a b. (a -> b) -> a -> b
$ Lens' value Text
-> Lens' value ByteString -> AnyMessageDescriptor value
forall msg.
Lens' msg Text -> Lens' msg ByteString -> AnyMessageDescriptor msg
AnyMessageDescriptor LensLike' f value value
(Text -> f Text) -> value -> f value
Lens' value value
Lens' value Text
typeUrlLens LensLike' f value value
(ByteString -> f ByteString) -> value -> f value
Lens' value value
Lens' value ByteString
valueLens
matchAnyMessage FieldTypeDescriptor value
_ = Maybe (AnyMessageDescriptor value)
forall a. Maybe a
Nothing
data AnyMessageDescriptor msg
= AnyMessageDescriptor
{ forall msg. AnyMessageDescriptor msg -> Lens' msg Text
anyTypeUrlLens :: Lens' msg T.Text
, forall msg. AnyMessageDescriptor msg -> Lens' msg ByteString
anyValueLens :: Lens' msg B.ByteString
}
class (Enum a, Bounded a) => MessageEnum a where
maybeToEnum :: Int -> Maybe a
showEnum :: a -> String
readEnum :: String -> Maybe a
build :: Message a => (a -> a) -> a
build :: forall a. Message a => (a -> a) -> a
build = ((a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
forall msg. Message msg => msg
defMessage)
maybeLens :: b -> Lens' (Maybe b) b
maybeLens :: forall b. b -> Lens' (Maybe b) b
maybeLens b
x = (Maybe b -> b)
-> (Maybe b -> b -> Maybe b)
-> forall {f :: * -> *}.
Functor f =>
LensLike f (Maybe b) (Maybe b) b b
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (b -> Maybe b -> b
forall a. a -> Maybe a -> a
fromMaybe b
x) ((Maybe b -> b -> Maybe b)
-> forall {f :: * -> *}.
Functor f =>
LensLike f (Maybe b) (Maybe b) b b)
-> (Maybe b -> b -> Maybe b)
-> forall {f :: * -> *}.
Functor f =>
LensLike f (Maybe b) (Maybe b) b b
forall a b. (a -> b) -> a -> b
$ (b -> Maybe b) -> Maybe b -> b -> Maybe b
forall a b. a -> b -> a
const b -> Maybe b
forall a. a -> Maybe a
Just
reverseRepeatedFields :: Map k (FieldDescriptor msg) -> msg -> msg
reverseRepeatedFields :: forall k msg. Map k (FieldDescriptor msg) -> msg -> msg
reverseRepeatedFields Map k (FieldDescriptor msg)
fields msg
x0
= (msg -> FieldDescriptor msg -> msg)
-> msg -> Map k (FieldDescriptor msg) -> msg
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Map.foldl' msg -> FieldDescriptor msg -> msg
forall a. a -> FieldDescriptor a -> a
reverseListField msg
x0 Map k (FieldDescriptor msg)
fields
where
reverseListField :: a -> FieldDescriptor a -> a
reverseListField :: forall a. a -> FieldDescriptor a -> a
reverseListField a
x (FieldDescriptor String
_ FieldTypeDescriptor value
_ (RepeatedField Packing
_ Lens' a [value]
f))
= Setter a a [value] [value] -> ([value] -> [value]) -> a -> a
forall s t a b. Setter s t a b -> (a -> b) -> s -> t
over LensLike' f a [value]
Lens' a [value]
Setter a a [value] [value]
f [value] -> [value]
forall a. [a] -> [a]
reverse a
x
reverseListField a
x FieldDescriptor a
_ = a
x
newtype Registry = Registry (Map.Map T.Text SomeMessageType)
deriving (NonEmpty Registry -> Registry
Registry -> Registry -> Registry
(Registry -> Registry -> Registry)
-> (NonEmpty Registry -> Registry)
-> (forall b. Integral b => b -> Registry -> Registry)
-> Semigroup Registry
forall b. Integral b => b -> Registry -> Registry
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: Registry -> Registry -> Registry
<> :: Registry -> Registry -> Registry
$csconcat :: NonEmpty Registry -> Registry
sconcat :: NonEmpty Registry -> Registry
$cstimes :: forall b. Integral b => b -> Registry -> Registry
stimes :: forall b. Integral b => b -> Registry -> Registry
Semigroup.Semigroup, Semigroup Registry
Registry
Semigroup Registry =>
Registry
-> (Registry -> Registry -> Registry)
-> ([Registry] -> Registry)
-> Monoid Registry
[Registry] -> Registry
Registry -> Registry -> Registry
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: Registry
mempty :: Registry
$cmappend :: Registry -> Registry -> Registry
mappend :: Registry -> Registry -> Registry
$cmconcat :: [Registry] -> Registry
mconcat :: [Registry] -> Registry
Monoid)
register :: forall msg . Message msg => Proxy msg -> Registry
register :: forall msg. Message msg => Proxy msg -> Registry
register Proxy msg
p = Map Text SomeMessageType -> Registry
Registry (Map Text SomeMessageType -> Registry)
-> Map Text SomeMessageType -> Registry
forall a b. (a -> b) -> a -> b
$ Text -> SomeMessageType -> Map Text SomeMessageType
forall k a. k -> a -> Map k a
Map.singleton (Proxy msg -> Text
forall msg. Message msg => Proxy msg -> Text
messageName (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @msg)) (Proxy msg -> SomeMessageType
forall msg. Message msg => Proxy msg -> SomeMessageType
SomeMessageType Proxy msg
p)
lookupRegistered :: T.Text -> Registry -> Maybe SomeMessageType
lookupRegistered :: Text -> Registry -> Maybe SomeMessageType
lookupRegistered Text
n (Registry Map Text SomeMessageType
m) = Text -> Map Text SomeMessageType -> Maybe SomeMessageType
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup ((Text, Text) -> Text
forall a b. (a, b) -> b
snd ((Text, Text) -> Text) -> (Text, Text) -> Text
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOnEnd Text
"/" Text
n) Map Text SomeMessageType
m
data SomeMessageType where
SomeMessageType :: Message msg => Proxy msg -> SomeMessageType
discardUnknownFields :: Message msg => msg -> msg
discardUnknownFields :: forall msg. Message msg => msg -> msg
discardUnknownFields = Setter msg msg FieldSet FieldSet -> FieldSet -> msg -> msg
forall s t a b. Setter s t a b -> b -> s -> t
set LensLike' f msg FieldSet
forall msg. Message msg => Lens' msg FieldSet
Lens' msg FieldSet
Setter msg msg FieldSet FieldSet
unknownFields []