Skip to content

Commit

Permalink
Add Data.ProtoLens.Any for storing arbitrary Messages.
Browse files Browse the repository at this point in the history
Fixes google#22.

Provides simple `pack` and `unpack` functions.  Since the `unpack` operation
is partial (and has multiple types of "failure"), I wasn't sure how to fit it
into a `Lens`; so I left that alone for the time being.

I turned this into a minor version bump.  It does add a new field to
`MessageDescriptor` which usually requires a major bump; but since that field
is internal to codegen, it shouldn't break any individual users.
  • Loading branch information
judah committed Jul 13, 2017
1 parent 3e9e3a7 commit 2a91314
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 28 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# ChangeLog

## v0.2.2.0
- Add `Data.ProtoLens.Any` for packing/unpacking messages to `Any`.
- Improve the behavior of oneof fields by generating sum types

## v0.2.1.0
- Include `base`'s modules in the reexport list.
- Use custom-setup in packages that depend on `proto-lens-protoc`.
Expand Down
4 changes: 2 additions & 2 deletions proto-lens-descriptors/proto-lens-descriptors.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: proto-lens-descriptors
version: 0.2.1.0
version: 0.2.2.0
synopsis: Protocol buffers for describing the definitions of messages.
description:
This package provides definitions for the 'proto-lens' package
Expand Down Expand Up @@ -28,5 +28,5 @@ library
, lens-labels == 0.1.*
-- Specify an exact version of `proto-lens`, since it's tied closely
-- to the generated code.
, proto-lens == 0.2.1.0
, proto-lens == 0.2.2.0
, text == 1.2.*
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ instance Data.ProtoLens.Message CodeGeneratorRequest where
:: Data.ProtoLens.FieldDescriptor CodeGeneratorRequest
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.compiler.CodeGeneratorRequest")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, fileToGenerate__field_descriptor),
(Data.ProtoLens.Tag 2, parameter__field_descriptor),
Expand Down Expand Up @@ -152,6 +153,7 @@ instance Data.ProtoLens.Message CodeGeneratorResponse where
:: Data.ProtoLens.FieldDescriptor CodeGeneratorResponse
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.compiler.CodeGeneratorResponse")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, error__field_descriptor),
(Data.ProtoLens.Tag 15, file__field_descriptor)])
Expand Down Expand Up @@ -247,6 +249,8 @@ instance Data.ProtoLens.Message CodeGeneratorResponse'File where
:: Data.ProtoLens.FieldDescriptor CodeGeneratorResponse'File
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack
"google.protobuf.compiler.CodeGeneratorResponse.File")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, insertionPoint__field_descriptor),
Expand Down
24 changes: 24 additions & 0 deletions proto-lens-descriptors/src/Proto/Google/Protobuf/Descriptor.hs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ instance Data.ProtoLens.Message DescriptorProto where
:: Data.ProtoLens.FieldDescriptor DescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.DescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, field__field_descriptor),
Expand Down Expand Up @@ -295,6 +296,7 @@ instance Data.ProtoLens.Message DescriptorProto'ExtensionRange
:: Data.ProtoLens.FieldDescriptor DescriptorProto'ExtensionRange
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.DescriptorProto.ExtensionRange")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, start__field_descriptor),
(Data.ProtoLens.Tag 2, end__field_descriptor)])
Expand Down Expand Up @@ -365,6 +367,7 @@ instance Data.ProtoLens.Message DescriptorProto'ReservedRange where
:: Data.ProtoLens.FieldDescriptor DescriptorProto'ReservedRange
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.DescriptorProto.ReservedRange")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, start__field_descriptor),
(Data.ProtoLens.Tag 2, end__field_descriptor)])
Expand Down Expand Up @@ -447,6 +450,7 @@ instance Data.ProtoLens.Message EnumDescriptorProto where
:: Data.ProtoLens.FieldDescriptor EnumDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.EnumDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, value__field_descriptor),
Expand Down Expand Up @@ -529,6 +533,7 @@ instance Data.ProtoLens.Message EnumOptions where
:: Data.ProtoLens.FieldDescriptor EnumOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.EnumOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 2, allowAlias__field_descriptor),
(Data.ProtoLens.Tag 3, deprecated__field_descriptor),
Expand Down Expand Up @@ -623,6 +628,7 @@ instance Data.ProtoLens.Message EnumValueDescriptorProto where
:: Data.ProtoLens.FieldDescriptor EnumValueDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.EnumValueDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, number__field_descriptor),
Expand Down Expand Up @@ -683,6 +689,7 @@ instance Data.ProtoLens.Message EnumValueOptions where
:: Data.ProtoLens.FieldDescriptor EnumValueOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.EnumValueOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, deprecated__field_descriptor),
(Data.ProtoLens.Tag 999, uninterpretedOption__field_descriptor)])
Expand Down Expand Up @@ -949,6 +956,7 @@ instance Data.ProtoLens.Message FieldDescriptorProto where
:: Data.ProtoLens.FieldDescriptor FieldDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.FieldDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 3, number__field_descriptor),
Expand Down Expand Up @@ -1406,6 +1414,7 @@ instance Data.ProtoLens.Message FieldOptions where
:: Data.ProtoLens.FieldDescriptor FieldOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.FieldOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, ctype__field_descriptor),
(Data.ProtoLens.Tag 2, packed__field_descriptor),
Expand Down Expand Up @@ -1784,6 +1793,7 @@ instance Data.ProtoLens.Message FileDescriptorProto where
:: Data.ProtoLens.FieldDescriptor FileDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.FileDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, package__field_descriptor),
Expand Down Expand Up @@ -1836,6 +1846,7 @@ instance Data.ProtoLens.Message FileDescriptorSet where
:: Data.ProtoLens.FieldDescriptor FileDescriptorSet
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.FileDescriptorSet")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, file__field_descriptor)])
(Data.Map.fromList [("file", file__field_descriptor)])
Expand Down Expand Up @@ -2197,6 +2208,7 @@ instance Data.ProtoLens.Message FileOptions where
:: Data.ProtoLens.FieldDescriptor FileOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.FileOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, javaPackage__field_descriptor),
(Data.ProtoLens.Tag 8, javaOuterClassname__field_descriptor),
Expand Down Expand Up @@ -2311,6 +2323,7 @@ instance Data.ProtoLens.Message GeneratedCodeInfo where
:: Data.ProtoLens.FieldDescriptor GeneratedCodeInfo
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.GeneratedCodeInfo")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, annotation__field_descriptor)])
(Data.Map.fromList [("annotation", annotation__field_descriptor)])
Expand Down Expand Up @@ -2419,6 +2432,7 @@ instance Data.ProtoLens.Message GeneratedCodeInfo'Annotation where
:: Data.ProtoLens.FieldDescriptor GeneratedCodeInfo'Annotation
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.GeneratedCodeInfo.Annotation")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, path__field_descriptor),
(Data.ProtoLens.Tag 2, sourceFile__field_descriptor),
Expand Down Expand Up @@ -2553,6 +2567,7 @@ instance Data.ProtoLens.Message MessageOptions where
:: Data.ProtoLens.FieldDescriptor MessageOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.MessageOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, messageSetWireFormat__field_descriptor),
(Data.ProtoLens.Tag 2,
Expand Down Expand Up @@ -2729,6 +2744,7 @@ instance Data.ProtoLens.Message MethodDescriptorProto where
:: Data.ProtoLens.FieldDescriptor MethodDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.MethodDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, inputType__field_descriptor),
Expand Down Expand Up @@ -2794,6 +2810,7 @@ instance Data.ProtoLens.Message MethodOptions where
:: Data.ProtoLens.FieldDescriptor MethodOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.MethodOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 33, deprecated__field_descriptor),
(Data.ProtoLens.Tag 999, uninterpretedOption__field_descriptor)])
Expand Down Expand Up @@ -2836,6 +2853,7 @@ instance Data.ProtoLens.Message OneofDescriptorProto where
:: Data.ProtoLens.FieldDescriptor OneofDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.OneofDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor)])
(Data.Map.fromList [("name", name__field_descriptor)])
Expand Down Expand Up @@ -2917,6 +2935,7 @@ instance Data.ProtoLens.Message ServiceDescriptorProto where
:: Data.ProtoLens.FieldDescriptor ServiceDescriptorProto
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.ServiceDescriptorProto")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, name__field_descriptor),
(Data.ProtoLens.Tag 2, method__field_descriptor),
Expand Down Expand Up @@ -2976,6 +2995,7 @@ instance Data.ProtoLens.Message ServiceOptions where
:: Data.ProtoLens.FieldDescriptor ServiceOptions
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.ServiceOptions")
(Data.Map.fromList
[(Data.ProtoLens.Tag 33, deprecated__field_descriptor),
(Data.ProtoLens.Tag 999, uninterpretedOption__field_descriptor)])
Expand Down Expand Up @@ -3008,6 +3028,7 @@ instance Data.ProtoLens.Message SourceCodeInfo where
:: Data.ProtoLens.FieldDescriptor SourceCodeInfo
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.SourceCodeInfo")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, location__field_descriptor)])
(Data.Map.fromList [("location", location__field_descriptor)])
Expand Down Expand Up @@ -3127,6 +3148,7 @@ instance Data.ProtoLens.Message SourceCodeInfo'Location where
:: Data.ProtoLens.FieldDescriptor SourceCodeInfo'Location
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.SourceCodeInfo.Location")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, path__field_descriptor),
(Data.ProtoLens.Tag 2, span__field_descriptor),
Expand Down Expand Up @@ -3317,6 +3339,7 @@ instance Data.ProtoLens.Message UninterpretedOption where
:: Data.ProtoLens.FieldDescriptor UninterpretedOption
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.UninterpretedOption")
(Data.Map.fromList
[(Data.ProtoLens.Tag 2, name__field_descriptor),
(Data.ProtoLens.Tag 3, identifierValue__field_descriptor),
Expand Down Expand Up @@ -3381,6 +3404,7 @@ instance Data.ProtoLens.Message UninterpretedOption'NamePart where
:: Data.ProtoLens.FieldDescriptor UninterpretedOption'NamePart
in
Data.ProtoLens.MessageDescriptor
(Data.Text.pack "google.protobuf.UninterpretedOption.NamePart")
(Data.Map.fromList
[(Data.ProtoLens.Tag 1, namePart__field_descriptor),
(Data.ProtoLens.Tag 2, isExtension__field_descriptor)])
Expand Down
16 changes: 11 additions & 5 deletions proto-lens-protobuf-types/proto-lens-protobuf-types.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: proto-lens-protobuf-types
version: 0.2.1.0
version: 0.2.2.0
synopsis: Basic protocol buffer message types.
description:
This package provides bindings standard protocol message types,
Expand All @@ -25,7 +25,13 @@ custom-setup
, proto-lens-protoc == 0.2.*

library
exposed-modules: Proto.Google.Protobuf.Any
Proto.Google.Protobuf.Duration
Proto.Google.Protobuf.Wrappers
build-depends: proto-lens-protoc == 0.2.*
hs-source-dirs: src
exposed-modules: Data.ProtoLens.Any
Proto.Google.Protobuf.Any
Proto.Google.Protobuf.Duration
Proto.Google.Protobuf.Wrappers
build-depends: base >= 4.8 && < 4.10
, lens-family
, proto-lens >= 0.2.2.0 && < 0.3
, proto-lens-protoc == 0.2.*
, text == 1.2.*
68 changes: 68 additions & 0 deletions proto-lens-protobuf-types/src/Data/ProtoLens/Any.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.ProtoLens.Any
( Any
, pack
, packWithPrefix
, unpack
, UnpackError(..)
) where

import Control.Exception (Exception(..))
import Data.Monoid ((<>))
import Data.Text (Text, breakOnEnd)
import Data.Typeable (Typeable)
import Data.ProtoLens
( decodeMessage
, def
, encodeMessage
, Message(..)
, MessageDescriptor(..)
)
import Lens.Family2 ((&), (.~), (^.))
import Proto.Google.Protobuf.Any

-- | Packs the given message into an 'Any' using the default type URL prefix
-- "type.googleapis.com".
pack :: forall a . Message a => a -> Any
pack = packWithPrefix googleApisPrefix

googleApisPrefix :: Text
googleApisPrefix = "type.googleapis.com"


-- | Packs the given message into an 'Any' using the given type URL prefix.
packWithPrefix :: forall a . Message a => Text -> a -> Any
packWithPrefix prefix x =
def & typeUrl .~ (prefix <> "/" <> name)
& value .~ encodeMessage x
where
name = messageName (descriptor :: MessageDescriptor a)


data UnpackError
= DifferentType
{ expectedMessageType :: Text -- ^ The expected @packagename.messagename@
, actualUrl :: Text -- ^ The typeUrl in the 'Any' being unpacked
}
| DecodingError String -- ^ The error from decodeMessage
deriving (Show, Eq, Typeable)

instance Exception UnpackError

-- | Unpacks the given 'Any' into the given message type. Returns 'Nothing'
-- if the type doesn't match or parsing the payload has failed.
--
-- Ignores the type URL prefix.
unpack :: forall a . Message a => Any -> Either UnpackError a
unpack a
| expectedName /= snd (breakOnEnd "/" $ a ^. typeUrl)
= Left DifferentType
{ expectedMessageType = expectedName
, actualUrl = a ^. typeUrl
}
| otherwise = case decodeMessage (a ^. value) of
Left e -> Left $ DecodingError e
Right x -> Right x
where
expectedName = messageName (descriptor :: MessageDescriptor a)
10 changes: 5 additions & 5 deletions proto-lens-protoc/proto-lens-protoc.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: proto-lens-protoc
version: 0.2.1.0
version: 0.2.2.0
synopsis: Protocol buffer compiler for the proto-lens library.
description:
Turn protocol buffer files (.proto) into Haskell files (.hs) which
Expand Down Expand Up @@ -47,8 +47,8 @@ library
, lens-family == 1.2.*
, lens-labels == 0.1.*
, process >= 1.2 && < 1.5
, proto-lens == 0.2.1.0
, proto-lens-descriptors == 0.2.1.0
, proto-lens == 0.2.2.0
, proto-lens-descriptors == 0.2.2.0
, text == 1.2.*
reexported-modules:
-- Modules that are needed by the generated Haskell files.
Expand Down Expand Up @@ -82,8 +82,8 @@ executable proto-lens-protoc
, lens-family == 1.2.*
-- Specify an exact version of `proto-lens`, since it's tied closely
-- to the generated code.
, proto-lens == 0.2.1.0
, proto-lens-descriptors == 0.2.1.0
, proto-lens == 0.2.2.0
, proto-lens-descriptors == 0.2.2.0
, text == 1.2.*
hs-source-dirs: src
other-modules:
Expand Down

0 comments on commit 2a91314

Please sign in to comment.