proto3-suite 0.3.0.0 → 0.4.0.0
raw patch · 23 files changed
+3472/−2952 lines, 23 filesdep +generic-arbitrarydep +optparse-applicativedep ~QuickCheckdep ~proto3-wiredep ~swagger2PVP ok
version bump matches the API change (PVP)
Dependencies added: generic-arbitrary, optparse-applicative
Dependency ranges changed: QuickCheck, proto3-wire, swagger2
API changes (from Hackage documentation)
- Proto3.Suite.Class: instance (GHC.Enum.Bounded e, GHC.Enum.Enum e) => Proto3.Suite.Class.HasDefault (Proto3.Suite.Types.Enumerated e)
- Proto3.Suite.Class: instance (GHC.Enum.Bounded e, GHC.Enum.Enum e, Proto3.Suite.Class.Named e) => Proto3.Suite.Class.MessageField (Proto3.Suite.Types.PackedVec (Proto3.Suite.Types.Enumerated e))
- Proto3.Suite.Class: instance (GHC.Enum.Bounded e, Proto3.Suite.Class.Named e, GHC.Enum.Enum e) => Proto3.Suite.Class.MessageField (Proto3.Suite.Types.Enumerated e)
- Proto3.Suite.Class: instance (GHC.Enum.Bounded e, Proto3.Suite.Class.Named e, GHC.Enum.Enum e) => Proto3.Suite.Class.Primitive (Proto3.Suite.Types.Enumerated e)
- Proto3.Suite.Class: instance GHC.Generics.Constructor c => Proto3.Suite.Class.GenericFinite (GHC.Generics.M1 GHC.Generics.C c f)
- Proto3.Suite.Class: instance Proto3.Suite.Class.GenericFinite f => Proto3.Suite.Class.GenericFinite (GHC.Generics.M1 GHC.Generics.S t f)
- Proto3.Suite.DotProto.AST: DotProtoServiceRPC :: DotProtoIdentifier -> (DotProtoIdentifier, Streaming) -> (DotProtoIdentifier, Streaming) -> [DotProtoOption] -> DotProtoServicePart
- Proto3.Suite.DotProto.AST: [dotProtoOneOfFields] :: DotProtoMessagePart -> [DotProtoField]
- Proto3.Suite.DotProto.AST: [dotProtoOneOfName] :: DotProtoMessagePart -> DotProtoIdentifier
- Proto3.Suite.DotProto.Generate: InternalEmptyModulePath :: CompileError
- Proto3.Suite.DotProto.Generate: fieldLikeName :: String -> String
- Proto3.Suite.DotProto.Generate: instance GHC.Classes.Eq Proto3.Suite.DotProto.Generate.CompileError
- Proto3.Suite.DotProto.Generate: instance GHC.Classes.Eq Proto3.Suite.DotProto.Generate.DotProtoKind
- Proto3.Suite.DotProto.Generate: instance GHC.Classes.Ord Proto3.Suite.DotProto.Generate.DotProtoKind
- Proto3.Suite.DotProto.Generate: instance GHC.Enum.Bounded Proto3.Suite.DotProto.Generate.DotProtoKind
- Proto3.Suite.DotProto.Generate: instance GHC.Enum.Enum Proto3.Suite.DotProto.Generate.DotProtoKind
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.CompileError
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.DotProtoKind
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.DotProtoTypeInfo
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.FieldInfo
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.OneofField
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.OneofSubfield
- Proto3.Suite.DotProto.Generate: instance GHC.Show.Show Proto3.Suite.DotProto.Generate.QualifiedField
- Proto3.Suite.DotProto.Generate: isPackable :: TypeContext -> DotProtoPrimType -> Bool
- Proto3.Suite.DotProto.Generate: prefixedEnumFieldName :: String -> String -> String
- Proto3.Suite.DotProto.Generate: typeLikeName :: MonadError CompileError m => String -> m String
- Proto3.Suite.Types: instance (GHC.Enum.Bounded a, GHC.Enum.Enum a) => Test.QuickCheck.Arbitrary.Arbitrary (Proto3.Suite.Types.Enumerated a)
+ Proto3.Suite.Class: instance (GHC.Generics.Constructor i, Proto3.Suite.Class.GenericHasDefault f) => Proto3.Suite.Class.GenericHasDefault (GHC.Generics.C1 i f)
+ Proto3.Suite.Class: instance (GHC.Generics.Datatype i, Proto3.Suite.Class.GenericHasDefault f) => Proto3.Suite.Class.GenericHasDefault (GHC.Generics.D1 i f)
+ Proto3.Suite.Class: instance (GHC.Generics.Selector i, Proto3.Suite.Class.GenericHasDefault f) => Proto3.Suite.Class.GenericHasDefault (GHC.Generics.S1 i f)
+ Proto3.Suite.Class: instance (Proto3.Suite.Class.GenericHasDefault f, Proto3.Suite.Class.GenericHasDefault g) => Proto3.Suite.Class.GenericHasDefault (f GHC.Generics.:*: g)
+ Proto3.Suite.Class: instance (Proto3.Suite.Class.GenericHasDefault f, Proto3.Suite.Class.GenericHasDefault g) => Proto3.Suite.Class.GenericHasDefault (f GHC.Generics.:+: g)
+ Proto3.Suite.Class: instance (Proto3.Suite.Class.Named e, Proto3.Wire.Class.ProtoEnum e) => Proto3.Suite.Class.MessageField (Proto3.Suite.Types.Enumerated e)
+ Proto3.Suite.Class: instance (Proto3.Suite.Class.Named e, Proto3.Wire.Class.ProtoEnum e) => Proto3.Suite.Class.MessageField (Proto3.Suite.Types.PackedVec (Proto3.Suite.Types.Enumerated e))
+ Proto3.Suite.Class: instance (Proto3.Suite.Class.Named e, Proto3.Wire.Class.ProtoEnum e) => Proto3.Suite.Class.Primitive (Proto3.Suite.Types.Enumerated e)
+ Proto3.Suite.Class: instance GHC.Generics.Constructor c => Proto3.Suite.Class.GenericFinite (GHC.Generics.M1 GHC.Generics.C c GHC.Generics.U1)
+ Proto3.Suite.Class: instance Proto3.Suite.Class.GenericHasDefault GHC.Generics.U1
+ Proto3.Suite.Class: instance Proto3.Suite.Class.HasDefault GHC.Integer.Type.Integer
+ Proto3.Suite.Class: instance Proto3.Suite.Class.HasDefault GHC.Types.Int
+ Proto3.Suite.Class: instance Proto3.Suite.Class.HasDefault f => Proto3.Suite.Class.GenericHasDefault (GHC.Generics.K1 i f)
+ Proto3.Suite.Class: instance Proto3.Wire.Class.ProtoEnum e => Proto3.Suite.Class.HasDefault (Proto3.Suite.Types.Enumerated e)
+ Proto3.Suite.DotProto: Anonymous :: DotProtoIdentifier
+ Proto3.Suite.DotProto: Bool :: DotProtoPrimType
+ Proto3.Suite.DotProto: BoolLit :: Bool -> DotProtoValue
+ Proto3.Suite.DotProto: Bytes :: DotProtoPrimType
+ Proto3.Suite.DotProto: DotProto :: [DotProtoImport] -> [DotProtoOption] -> DotProtoPackageSpec -> [DotProtoDefinition] -> DotProtoMeta -> DotProto
+ Proto3.Suite.DotProto: DotProtoEmptyField :: DotProtoField
+ Proto3.Suite.DotProto: DotProtoEnum :: String -> DotProtoIdentifier -> [DotProtoEnumPart] -> DotProtoDefinition
+ Proto3.Suite.DotProto: DotProtoEnumEmpty :: DotProtoEnumPart
+ Proto3.Suite.DotProto: DotProtoEnumField :: DotProtoIdentifier -> DotProtoEnumValue -> [DotProtoOption] -> DotProtoEnumPart
+ Proto3.Suite.DotProto: DotProtoEnumOption :: DotProtoOption -> DotProtoEnumPart
+ Proto3.Suite.DotProto: DotProtoField :: FieldNumber -> DotProtoType -> DotProtoIdentifier -> [DotProtoOption] -> String -> DotProtoField
+ Proto3.Suite.DotProto: DotProtoImport :: DotProtoImportQualifier -> FilePath -> DotProtoImport
+ Proto3.Suite.DotProto: DotProtoImportDefault :: DotProtoImportQualifier
+ Proto3.Suite.DotProto: DotProtoImportPublic :: DotProtoImportQualifier
+ Proto3.Suite.DotProto: DotProtoImportWeak :: DotProtoImportQualifier
+ Proto3.Suite.DotProto: DotProtoMessage :: String -> DotProtoIdentifier -> [DotProtoMessagePart] -> DotProtoDefinition
+ Proto3.Suite.DotProto: DotProtoMessageDefinition :: DotProtoDefinition -> DotProtoMessagePart
+ Proto3.Suite.DotProto: DotProtoMessageField :: DotProtoField -> DotProtoMessagePart
+ Proto3.Suite.DotProto: DotProtoMessageOneOf :: DotProtoIdentifier -> [DotProtoField] -> DotProtoMessagePart
+ Proto3.Suite.DotProto: DotProtoMessageReserved :: [DotProtoReservedField] -> DotProtoMessagePart
+ Proto3.Suite.DotProto: DotProtoMeta :: Path -> DotProtoMeta
+ Proto3.Suite.DotProto: DotProtoNoPackage :: DotProtoPackageSpec
+ Proto3.Suite.DotProto: DotProtoOption :: DotProtoIdentifier -> DotProtoValue -> DotProtoOption
+ Proto3.Suite.DotProto: DotProtoPackageSpec :: DotProtoIdentifier -> DotProtoPackageSpec
+ Proto3.Suite.DotProto: DotProtoService :: String -> DotProtoIdentifier -> [DotProtoServicePart] -> DotProtoDefinition
+ Proto3.Suite.DotProto: DotProtoServiceEmpty :: DotProtoServicePart
+ Proto3.Suite.DotProto: DotProtoServiceOption :: DotProtoOption -> DotProtoServicePart
+ Proto3.Suite.DotProto: DotProtoServiceRPCMethod :: RPCMethod -> DotProtoServicePart
+ Proto3.Suite.DotProto: Dots :: Path -> DotProtoIdentifier
+ Proto3.Suite.DotProto: Double :: DotProtoPrimType
+ Proto3.Suite.DotProto: FieldName :: String -> FieldName
+ Proto3.Suite.DotProto: FieldRange :: Int -> Int -> DotProtoReservedField
+ Proto3.Suite.DotProto: Fixed32 :: DotProtoPrimType
+ Proto3.Suite.DotProto: Fixed64 :: DotProtoPrimType
+ Proto3.Suite.DotProto: Float :: DotProtoPrimType
+ Proto3.Suite.DotProto: FloatLit :: Double -> DotProtoValue
+ Proto3.Suite.DotProto: Identifier :: DotProtoIdentifier -> DotProtoValue
+ Proto3.Suite.DotProto: Int32 :: DotProtoPrimType
+ Proto3.Suite.DotProto: Int64 :: DotProtoPrimType
+ Proto3.Suite.DotProto: IntLit :: Int -> DotProtoValue
+ Proto3.Suite.DotProto: Map :: DotProtoPrimType -> DotProtoPrimType -> DotProtoType
+ Proto3.Suite.DotProto: MessageName :: String -> MessageName
+ Proto3.Suite.DotProto: Named :: DotProtoIdentifier -> DotProtoPrimType
+ Proto3.Suite.DotProto: NestedRepeated :: DotProtoPrimType -> DotProtoType
+ Proto3.Suite.DotProto: NonStreaming :: Streaming
+ Proto3.Suite.DotProto: Optional :: DotProtoPrimType -> DotProtoType
+ Proto3.Suite.DotProto: PackageName :: String -> PackageName
+ Proto3.Suite.DotProto: PackedField :: Packing
+ Proto3.Suite.DotProto: Path :: NonEmpty String -> Path
+ Proto3.Suite.DotProto: Prim :: DotProtoPrimType -> DotProtoType
+ Proto3.Suite.DotProto: Qualified :: DotProtoIdentifier -> DotProtoIdentifier -> DotProtoIdentifier
+ Proto3.Suite.DotProto: RPCMethod :: DotProtoIdentifier -> DotProtoIdentifier -> Streaming -> DotProtoIdentifier -> Streaming -> [DotProtoOption] -> RPCMethod
+ Proto3.Suite.DotProto: RenderingOptions :: (DotProtoIdentifier -> DotProtoIdentifier -> FieldNumber -> Doc) -> (DotProtoIdentifier -> DotProtoIdentifier -> Doc) -> RenderingOptions
+ Proto3.Suite.DotProto: Repeated :: DotProtoPrimType -> DotProtoType
+ Proto3.Suite.DotProto: ReservedIdentifier :: String -> DotProtoReservedField
+ Proto3.Suite.DotProto: SFixed32 :: DotProtoPrimType
+ Proto3.Suite.DotProto: SFixed64 :: DotProtoPrimType
+ Proto3.Suite.DotProto: SInt32 :: DotProtoPrimType
+ Proto3.Suite.DotProto: SInt64 :: DotProtoPrimType
+ Proto3.Suite.DotProto: Single :: String -> DotProtoIdentifier
+ Proto3.Suite.DotProto: SingleField :: Int -> DotProtoReservedField
+ Proto3.Suite.DotProto: Streaming :: Streaming
+ Proto3.Suite.DotProto: String :: DotProtoPrimType
+ Proto3.Suite.DotProto: StringLit :: String -> DotProtoValue
+ Proto3.Suite.DotProto: UInt32 :: DotProtoPrimType
+ Proto3.Suite.DotProto: UInt64 :: DotProtoPrimType
+ Proto3.Suite.DotProto: UnpackedField :: Packing
+ Proto3.Suite.DotProto: [components] :: Path -> NonEmpty String
+ Proto3.Suite.DotProto: [dotProtoFieldComment] :: DotProtoField -> String
+ Proto3.Suite.DotProto: [dotProtoFieldName] :: DotProtoField -> DotProtoIdentifier
+ Proto3.Suite.DotProto: [dotProtoFieldNumber] :: DotProtoField -> FieldNumber
+ Proto3.Suite.DotProto: [dotProtoFieldOptions] :: DotProtoField -> [DotProtoOption]
+ Proto3.Suite.DotProto: [dotProtoFieldType] :: DotProtoField -> DotProtoType
+ Proto3.Suite.DotProto: [dotProtoImportPath] :: DotProtoImport -> FilePath
+ Proto3.Suite.DotProto: [dotProtoImportQualifier] :: DotProtoImport -> DotProtoImportQualifier
+ Proto3.Suite.DotProto: [dotProtoOptionIdentifier] :: DotProtoOption -> DotProtoIdentifier
+ Proto3.Suite.DotProto: [dotProtoOptionValue] :: DotProtoOption -> DotProtoValue
+ Proto3.Suite.DotProto: [getFieldName] :: FieldName -> String
+ Proto3.Suite.DotProto: [getMessageName] :: MessageName -> String
+ Proto3.Suite.DotProto: [getPackageName] :: PackageName -> String
+ Proto3.Suite.DotProto: [metaModulePath] :: DotProtoMeta -> Path
+ Proto3.Suite.DotProto: [protoDefinitions] :: DotProto -> [DotProtoDefinition]
+ Proto3.Suite.DotProto: [protoImports] :: DotProto -> [DotProtoImport]
+ Proto3.Suite.DotProto: [protoMeta] :: DotProto -> DotProtoMeta
+ Proto3.Suite.DotProto: [protoOptions] :: DotProto -> [DotProtoOption]
+ Proto3.Suite.DotProto: [protoPackage] :: DotProto -> DotProtoPackageSpec
+ Proto3.Suite.DotProto: [roEnumMemberName] :: RenderingOptions -> DotProtoIdentifier -> DotProtoIdentifier -> Doc
+ Proto3.Suite.DotProto: [roSelectorName] :: RenderingOptions -> DotProtoIdentifier -> DotProtoIdentifier -> FieldNumber -> Doc
+ Proto3.Suite.DotProto: [rpcMethodName] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto: [rpcMethodOptions] :: RPCMethod -> [DotProtoOption]
+ Proto3.Suite.DotProto: [rpcMethodRequestStreaming] :: RPCMethod -> Streaming
+ Proto3.Suite.DotProto: [rpcMethodRequestType] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto: [rpcMethodResponseStreaming] :: RPCMethod -> Streaming
+ Proto3.Suite.DotProto: [rpcMethodResponseType] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto: class Pretty a
+ Proto3.Suite.DotProto: data DotProto
+ Proto3.Suite.DotProto: data DotProtoDefinition
+ Proto3.Suite.DotProto: data DotProtoEnumPart
+ Proto3.Suite.DotProto: data DotProtoField
+ Proto3.Suite.DotProto: data DotProtoIdentifier
+ Proto3.Suite.DotProto: data DotProtoImport
+ Proto3.Suite.DotProto: data DotProtoImportQualifier
+ Proto3.Suite.DotProto: data DotProtoMessagePart
+ Proto3.Suite.DotProto: data DotProtoMeta
+ Proto3.Suite.DotProto: data DotProtoOption
+ Proto3.Suite.DotProto: data DotProtoPackageSpec
+ Proto3.Suite.DotProto: data DotProtoPrimType
+ Proto3.Suite.DotProto: data DotProtoReservedField
+ Proto3.Suite.DotProto: data DotProtoServicePart
+ Proto3.Suite.DotProto: data DotProtoType
+ Proto3.Suite.DotProto: data DotProtoValue
+ Proto3.Suite.DotProto: data Packing
+ Proto3.Suite.DotProto: data RPCMethod
+ Proto3.Suite.DotProto: data RenderingOptions
+ Proto3.Suite.DotProto: data Streaming
+ Proto3.Suite.DotProto: defEnumMemberName :: DotProtoIdentifier -> DotProtoIdentifier -> Doc
+ Proto3.Suite.DotProto: defRenderingOptions :: RenderingOptions
+ Proto3.Suite.DotProto: defSelectorName :: DotProtoIdentifier -> DotProtoIdentifier -> FieldNumber -> Doc
+ Proto3.Suite.DotProto: fakePath :: Path
+ Proto3.Suite.DotProto: fieldLikeName :: String -> String
+ Proto3.Suite.DotProto: newtype FieldName
+ Proto3.Suite.DotProto: newtype MessageName
+ Proto3.Suite.DotProto: newtype PackageName
+ Proto3.Suite.DotProto: newtype Path
+ Proto3.Suite.DotProto: pPrint :: Pretty a => a -> Doc
+ Proto3.Suite.DotProto: pPrintList :: Pretty a => PrettyLevel -> [a] -> Doc
+ Proto3.Suite.DotProto: pPrintPrec :: Pretty a => PrettyLevel -> Rational -> a -> Doc
+ Proto3.Suite.DotProto: packageFromDefs :: String -> [DotProtoDefinition] -> DotProto
+ Proto3.Suite.DotProto: parseProto :: Path -> String -> Either ParseError DotProto
+ Proto3.Suite.DotProto: parseProtoFile :: MonadIO m => Path -> FilePath -> m (Either ParseError DotProto)
+ Proto3.Suite.DotProto: prefixedEnumFieldName :: String -> String -> String
+ Proto3.Suite.DotProto: renderDotProto :: RenderingOptions -> DotProto -> Doc
+ Proto3.Suite.DotProto: toProtoFile :: RenderingOptions -> DotProto -> String
+ Proto3.Suite.DotProto: toProtoFileDef :: DotProto -> String
+ Proto3.Suite.DotProto: type DotProtoEnumValue = Int32
+ Proto3.Suite.DotProto: typeLikeName :: MonadError CompileError m => String -> m String
+ Proto3.Suite.DotProto.AST: DotProtoServiceRPCMethod :: RPCMethod -> DotProtoServicePart
+ Proto3.Suite.DotProto.AST: RPCMethod :: DotProtoIdentifier -> DotProtoIdentifier -> Streaming -> DotProtoIdentifier -> Streaming -> [DotProtoOption] -> RPCMethod
+ Proto3.Suite.DotProto.AST: [rpcMethodName] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto.AST: [rpcMethodOptions] :: RPCMethod -> [DotProtoOption]
+ Proto3.Suite.DotProto.AST: [rpcMethodRequestStreaming] :: RPCMethod -> Streaming
+ Proto3.Suite.DotProto.AST: [rpcMethodRequestType] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto.AST: [rpcMethodResponseStreaming] :: RPCMethod -> Streaming
+ Proto3.Suite.DotProto.AST: [rpcMethodResponseType] :: RPCMethod -> DotProtoIdentifier
+ Proto3.Suite.DotProto.AST: data RPCMethod
+ Proto3.Suite.DotProto.AST: fakePath :: Path
+ Proto3.Suite.DotProto.AST: instance GHC.Classes.Eq Proto3.Suite.DotProto.AST.RPCMethod
+ Proto3.Suite.DotProto.AST: instance GHC.Show.Show Proto3.Suite.DotProto.AST.RPCMethod
+ Proto3.Suite.DotProto.AST: instance Test.QuickCheck.Arbitrary.Arbitrary Proto3.Suite.DotProto.AST.RPCMethod
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoEnum :: Prism' DotProtoDefinition (String, DotProtoIdentifier, [DotProtoEnumPart])
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoMessage :: Prism' DotProtoDefinition (String, DotProtoIdentifier, [DotProtoMessagePart])
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoMessageDefinition :: Prism' DotProtoMessagePart DotProtoDefinition
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoMessageField :: Prism' DotProtoMessagePart DotProtoField
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoMessageOneOf :: Prism' DotProtoMessagePart (DotProtoIdentifier, [DotProtoField])
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoMessageReserved :: Prism' DotProtoMessagePart [DotProtoReservedField]
+ Proto3.Suite.DotProto.AST.Lens: _DotProtoService :: Prism' DotProtoDefinition (String, DotProtoIdentifier, [DotProtoServicePart])
+ Proto3.Suite.DotProto.Generate: CompileArgs :: [FilePath] -> [FilePath] -> FilePath -> FilePath -> CompileArgs
+ Proto3.Suite.DotProto.Generate: EmptyEnumeration :: String -> CompileError
+ Proto3.Suite.DotProto.Generate: InvalidPackageName :: DotProtoIdentifier -> CompileError
+ Proto3.Suite.DotProto.Generate: NonzeroFirstEnumeration :: String -> DotProtoIdentifier -> Int32 -> CompileError
+ Proto3.Suite.DotProto.Generate: [extraInstanceFiles] :: CompileArgs -> [FilePath]
+ Proto3.Suite.DotProto.Generate: [includeDir] :: CompileArgs -> [FilePath]
+ Proto3.Suite.DotProto.Generate: [inputProto] :: CompileArgs -> FilePath
+ Proto3.Suite.DotProto.Generate: [outputDir] :: CompileArgs -> FilePath
+ Proto3.Suite.DotProto.Generate: data CompileArgs
+ Proto3.Suite.Tutorial: instance Proto3.Wire.Class.ProtoEnum Proto3.Suite.Tutorial.Shape
+ Proto3.Suite.Types: instance Proto3.Wire.Class.ProtoEnum a => Test.QuickCheck.Arbitrary.Arbitrary (Proto3.Suite.Types.Enumerated a)
- Proto3.Suite: Enumerated :: Either Int a -> Enumerated a
+ Proto3.Suite: Enumerated :: Either Int32 a -> Enumerated a
- Proto3.Suite: [enumerated] :: Enumerated a -> Either Int a
+ Proto3.Suite: [enumerated] :: Enumerated a -> Either Int32 a
- Proto3.Suite: class Enum a => Finite a
+ Proto3.Suite: class ProtoEnum a => Finite a
- Proto3.Suite: def :: (HasDefault a, Num a) => a
+ Proto3.Suite: def :: (HasDefault a, Generic a, GenericHasDefault (Rep a)) => a
- Proto3.Suite: enumerate :: (Finite a, IsString string, GenericFinite (Rep a)) => Proxy# a -> [(string, Int)]
+ Proto3.Suite: enumerate :: (Finite a, IsString string, Generic a, GenericFinite (Rep a)) => Proxy# a -> [(string, Int32)]
- Proto3.Suite.Class: class Enum a => Finite a
+ Proto3.Suite.Class: class ProtoEnum a => Finite a
- Proto3.Suite.Class: def :: (HasDefault a, Num a) => a
+ Proto3.Suite.Class: def :: (HasDefault a, Generic a, GenericHasDefault (Rep a)) => a
- Proto3.Suite.Class: enumerate :: (Finite a, IsString string, GenericFinite (Rep a)) => Proxy# a -> [(string, Int)]
+ Proto3.Suite.Class: enumerate :: (Finite a, IsString string, Generic a, GenericFinite (Rep a)) => Proxy# a -> [(string, Int32)]
- Proto3.Suite.DotProto.AST: DotProtoEnum :: DotProtoIdentifier -> [DotProtoEnumPart] -> DotProtoDefinition
+ Proto3.Suite.DotProto.AST: DotProtoEnum :: String -> DotProtoIdentifier -> [DotProtoEnumPart] -> DotProtoDefinition
- Proto3.Suite.DotProto.AST: DotProtoField :: FieldNumber -> DotProtoType -> DotProtoIdentifier -> [DotProtoOption] -> Maybe String -> DotProtoField
+ Proto3.Suite.DotProto.AST: DotProtoField :: FieldNumber -> DotProtoType -> DotProtoIdentifier -> [DotProtoOption] -> String -> DotProtoField
- Proto3.Suite.DotProto.AST: DotProtoMessage :: DotProtoIdentifier -> [DotProtoMessagePart] -> DotProtoDefinition
+ Proto3.Suite.DotProto.AST: DotProtoMessage :: String -> DotProtoIdentifier -> [DotProtoMessagePart] -> DotProtoDefinition
- Proto3.Suite.DotProto.AST: DotProtoService :: DotProtoIdentifier -> [DotProtoServicePart] -> DotProtoDefinition
+ Proto3.Suite.DotProto.AST: DotProtoService :: String -> DotProtoIdentifier -> [DotProtoServicePart] -> DotProtoDefinition
- Proto3.Suite.DotProto.AST: Path :: [String] -> Path
+ Proto3.Suite.DotProto.AST: Path :: NonEmpty String -> Path
- Proto3.Suite.DotProto.AST: [components] :: Path -> [String]
+ Proto3.Suite.DotProto.AST: [components] :: Path -> NonEmpty String
- Proto3.Suite.DotProto.AST: [dotProtoFieldComment] :: DotProtoField -> Maybe String
+ Proto3.Suite.DotProto.AST: [dotProtoFieldComment] :: DotProtoField -> String
- Proto3.Suite.DotProto.AST: type DotProtoEnumValue = Int
+ Proto3.Suite.DotProto.AST: type DotProtoEnumValue = Int32
- Proto3.Suite.DotProto.Generate: compileDotProtoFile :: [FilePath] -> FilePath -> [FilePath] -> FilePath -> IO (Either CompileError ())
+ Proto3.Suite.DotProto.Generate: compileDotProtoFile :: CompileArgs -> IO (Either CompileError ())
- Proto3.Suite.DotProto.Generate: compileDotProtoFileOrDie :: [FilePath] -> FilePath -> [FilePath] -> FilePath -> IO ()
+ Proto3.Suite.DotProto.Generate: compileDotProtoFileOrDie :: CompileArgs -> IO ()
- Proto3.Suite.DotProto.Generate: readDotProtoWithContext :: [FilePath] -> FilePath -> IO (Either CompileError (DotProto, TypeContext))
+ Proto3.Suite.DotProto.Generate: readDotProtoWithContext :: (MonadError CompileError m, MonadIO m) => [FilePath] -> FilePath -> m (DotProto, TypeContext)
- Proto3.Suite.JSONPB: ParamSchema :: Maybe Value -> SwaggerType t -> Maybe Format -> Maybe (SwaggerItems t) -> Maybe Scientific -> Maybe Bool -> Maybe Scientific -> Maybe Bool -> Maybe Integer -> Maybe Integer -> Maybe Pattern -> Maybe Integer -> Maybe Integer -> Maybe Bool -> Maybe [Value] -> Maybe Scientific -> ParamSchema
+ Proto3.Suite.JSONPB: ParamSchema :: Maybe Value -> Maybe (SwaggerType t) -> Maybe Format -> Maybe (SwaggerItems t) -> Maybe Scientific -> Maybe Bool -> Maybe Scientific -> Maybe Bool -> Maybe Integer -> Maybe Integer -> Maybe Pattern -> Maybe Integer -> Maybe Integer -> Maybe Bool -> Maybe [Value] -> Maybe Scientific -> ParamSchema
- Proto3.Suite.JSONPB: [_paramSchemaType] :: ParamSchema -> SwaggerType t
+ Proto3.Suite.JSONPB: [_paramSchemaType] :: ParamSchema -> Maybe (SwaggerType t)
- Proto3.Suite.JSONPB: declareNamedSchema :: ToSchema a => proxy a -> Declare (Definitions Schema) NamedSchema
+ Proto3.Suite.JSONPB: declareNamedSchema :: ToSchema a => Proxy a -> Declare (Definitions Schema) NamedSchema
- Proto3.Suite.JSONPB: declareSchemaRef :: ToSchema a => proxy a -> Declare (Definitions Schema) (Referenced Schema)
+ Proto3.Suite.JSONPB: declareSchemaRef :: ToSchema a => Proxy a -> Declare (Definitions Schema) (Referenced Schema)
- Proto3.Suite.Types: Enumerated :: Either Int a -> Enumerated a
+ Proto3.Suite.Types: Enumerated :: Either Int32 a -> Enumerated a
- Proto3.Suite.Types: [enumerated] :: Enumerated a -> Either Int a
+ Proto3.Suite.Types: [enumerated] :: Enumerated a -> Either Int32 a
Files
- gen/TestProto.hs +565/−335
- gen/TestProtoImport.hs +36/−26
- gen/TestProtoOneof.hs +87/−86
- gen/TestProtoOneofImport.hs +117/−25
- proto3-suite.cabal +13/−8
- src/Proto3/Suite/Class.hs +85/−74
- src/Proto3/Suite/DhallPB.hs +2/−2
- src/Proto3/Suite/DotProto.hs +2/−0
- src/Proto3/Suite/DotProto/AST.hs +52/−43
- src/Proto3/Suite/DotProto/AST/Lens.hs +9/−0
- src/Proto3/Suite/DotProto/Generate.hs +1815/−2147
- src/Proto3/Suite/DotProto/Generate/Swagger.hs +14/−1
- src/Proto3/Suite/DotProto/Internal.hs +449/−62
- src/Proto3/Suite/DotProto/Parsing.hs +32/−25
- src/Proto3/Suite/DotProto/Rendering.hs +31/−21
- src/Proto3/Suite/JSONPB/Class.hs +9/−2
- src/Proto3/Suite/Tutorial.hs +9/−8
- src/Proto3/Suite/Types.hs +5/−5
- tests/ArbitraryGeneratedTestTypes.hs +5/−5
- tests/Main.hs +13/−10
- tests/TestCodeGen.hs +69/−35
- tools/canonicalize-proto-file/Main.hs +25/−19
- tools/compile-proto-file/Main.hs +28/−13
gen/TestProto.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-}@@ -9,33 +11,39 @@ -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module TestProto where import qualified Prelude as Hs-import qualified Proto3.Suite.DhallPB as HsDhallPb-import qualified Proto3.Suite.DotProto as HsProtobuf-import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Suite.Class as HsProtobuf+import qualified Proto3.Suite.DotProto as HsProtobuf import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:))+import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf-import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.Applicative as Hs+import Control.Applicative ((<*>), (<|>), (<$>))+import qualified Control.DeepSeq as Hs import qualified Control.Monad as Hs-import qualified Data.Text.Lazy as Hs (Text) import qualified Data.ByteString as Hs+import qualified Data.Coerce as Hs+import qualified Data.Int as Hs (Int16, Int32, Int64)+import qualified Data.List.NonEmpty as Hs (NonEmpty(..))+import qualified Data.Map as Hs (Map, mapKeysMonotonic)+import qualified Data.Proxy as Proxy import qualified Data.String as Hs (fromString)+import qualified Data.Text.Lazy as Hs (Text) import qualified Data.Vector as Hs (Vector)-import qualified Data.Int as Hs (Int16, Int32, Int64) import qualified Data.Word as Hs (Word16, Word32, Word64)-import qualified Data.Proxy as Proxy-import qualified GHC.Generics as Hs import qualified GHC.Enum as Hs+import qualified GHC.Generics as Hs+import qualified Unsafe.Coerce as Hs import qualified TestProtoImport data Trivial = Trivial{trivialTrivialField :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named Trivial where nameOf _ = (Hs.fromString "Trivial") +instance HsProtobuf.HasDefault Trivial+ instance HsProtobuf.Message Trivial where encodeMessage _ Trivial{trivialTrivialField = trivialTrivialField} = (Hs.mconcat@@ -50,7 +58,7 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "trivialField") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB Trivial where toJSONPB (Trivial f1) = (HsJSONPB.object ["trivialField" .= f1])@@ -84,10 +92,6 @@ HsJSONPB.insOrdFromList [("trivialField", trivialTrivialField)]}}) -instance HsDhallPb.Interpret Trivial- -instance HsDhallPb.Inject Trivial- data MultipleFields = MultipleFields{multipleFieldsMultiFieldDouble :: Hs.Double, multipleFieldsMultiFieldFloat :: Hs.Float,@@ -95,11 +99,13 @@ multipleFieldsMultiFieldInt64 :: Hs.Int64, multipleFieldsMultiFieldString :: Hs.Text, multipleFieldsMultiFieldBool :: Hs.Bool}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named MultipleFields where nameOf _ = (Hs.fromString "MultipleFields") +instance HsProtobuf.HasDefault MultipleFields+ instance HsProtobuf.Message MultipleFields where encodeMessage _ MultipleFields{multipleFieldsMultiFieldDouble =@@ -146,32 +152,32 @@ (HsProtobuf.Prim HsProtobuf.Double) (HsProtobuf.Single "multiFieldDouble") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.Float) (HsProtobuf.Single "multiFieldFloat") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "multiFieldInt32") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Prim HsProtobuf.Int64) (HsProtobuf.Single "multiFieldInt64") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 5) (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "multiFieldString") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 6) (HsProtobuf.Prim HsProtobuf.Bool) (HsProtobuf.Single "multiFieldBool") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB MultipleFields where toJSONPB (MultipleFields f1 f2 f3 f4 f5 f6)@@ -251,33 +257,33 @@ ("multiFieldBool", multipleFieldsMultiFieldBool)]}}) -instance HsDhallPb.Interpret MultipleFields- -instance HsDhallPb.Inject MultipleFields- data SignedInts = SignedInts{signedIntsSigned32 :: Hs.Int32, signedIntsSigned64 :: Hs.Int64}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named SignedInts where nameOf _ = (Hs.fromString "SignedInts") +instance HsProtobuf.HasDefault SignedInts+ instance HsProtobuf.Message SignedInts where encodeMessage _ SignedInts{signedIntsSigned32 = signedIntsSigned32, signedIntsSigned64 = signedIntsSigned64} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Signed signedIntsSigned32)),+ (Hs.coerce @(Hs.Int32) @(HsProtobuf.Signed Hs.Int32)+ signedIntsSigned32)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.Signed signedIntsSigned64))])+ (Hs.coerce @(Hs.Int64) @(HsProtobuf.Signed Hs.Int64)+ signedIntsSigned64))]) decodeMessage _ = (Hs.pure SignedInts) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed Hs.Int32)) @(_ Hs.Int32) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed Hs.Int64)) @(_ Hs.Int64) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) dotProto _@@ -285,12 +291,12 @@ (HsProtobuf.Prim HsProtobuf.SInt32) (HsProtobuf.Single "signed32") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.SInt64) (HsProtobuf.Single "signed64") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB SignedInts where toJSONPB (SignedInts f1 f2)@@ -331,17 +337,15 @@ [("signed32", signedIntsSigned32), ("signed64", signedIntsSigned64)]}}) -instance HsDhallPb.Interpret SignedInts- -instance HsDhallPb.Inject SignedInts- data WithEnum = WithEnum{withEnumEnumField :: HsProtobuf.Enumerated TestProto.WithEnum_TestEnum}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithEnum where nameOf _ = (Hs.fromString "WithEnum") +instance HsProtobuf.HasDefault WithEnum+ instance HsProtobuf.Message WithEnum where encodeMessage _ WithEnum{withEnumEnumField = withEnumEnumField} = (Hs.mconcat@@ -356,7 +360,7 @@ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "TestEnum"))) (HsProtobuf.Single "enumField") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithEnum where toJSONPB (WithEnum f1) = (HsJSONPB.object ["enumField" .= f1])@@ -390,33 +394,34 @@ HsJSONPB.insOrdFromList [("enumField", withEnumEnumField)]}}) -instance HsDhallPb.Interpret WithEnum- -instance HsDhallPb.Inject WithEnum- data WithEnum_TestEnum = WithEnum_TestEnumENUM1 | WithEnum_TestEnumENUM2 | WithEnum_TestEnumENUM3- deriving (Hs.Show, Hs.Bounded, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithEnum_TestEnum where nameOf _ = (Hs.fromString "WithEnum_TestEnum") -instance Hs.Enum WithEnum_TestEnum where- toEnum 0 = WithEnum_TestEnumENUM1- toEnum 1 = WithEnum_TestEnumENUM2- toEnum 2 = WithEnum_TestEnumENUM3- toEnum i = (Hs.toEnumError "WithEnum_TestEnum" i (0 :: Hs.Int, 2))- fromEnum (WithEnum_TestEnumENUM1) = 0- fromEnum (WithEnum_TestEnumENUM2) = 1- fromEnum (WithEnum_TestEnumENUM3) = 2- succ (WithEnum_TestEnumENUM1) = WithEnum_TestEnumENUM2- succ (WithEnum_TestEnumENUM2) = WithEnum_TestEnumENUM3- succ _ = Hs.succError "WithEnum_TestEnum"- pred (WithEnum_TestEnumENUM2) = WithEnum_TestEnumENUM1- pred (WithEnum_TestEnumENUM3) = WithEnum_TestEnumENUM2- pred _ = Hs.predError "WithEnum_TestEnum"+instance HsProtobuf.HasDefault WithEnum_TestEnum +instance Hs.Bounded WithEnum_TestEnum where+ minBound = WithEnum_TestEnumENUM1+ maxBound = WithEnum_TestEnumENUM3+ +instance Hs.Ord WithEnum_TestEnum where+ compare x y+ = Hs.compare (HsProtobuf.fromProtoEnum x)+ (HsProtobuf.fromProtoEnum y)+ +instance HsProtobuf.ProtoEnum WithEnum_TestEnum where+ toProtoEnumMay 0 = Hs.Just WithEnum_TestEnumENUM1+ toProtoEnumMay 1 = Hs.Just WithEnum_TestEnumENUM2+ toProtoEnumMay 2 = Hs.Just WithEnum_TestEnumENUM3+ toProtoEnumMay _ = Hs.Nothing+ fromProtoEnum (WithEnum_TestEnumENUM1) = 0+ fromProtoEnum (WithEnum_TestEnumENUM2) = 1+ fromProtoEnum (WithEnum_TestEnumENUM3) = 2+ instance HsJSONPB.ToJSONPB WithEnum_TestEnum where toJSONPB x _ = HsJSONPB.enumFieldString x toEncodingPB x _ = HsJSONPB.enumFieldEncoding x@@ -437,28 +442,29 @@ instance HsJSONPB.FromJSON WithEnum_TestEnum where parseJSON = HsJSONPB.parseJSONPB -instance HsDhallPb.Interpret WithEnum_TestEnum- -instance HsDhallPb.Inject WithEnum_TestEnum- instance HsProtobuf.Finite WithEnum_TestEnum data WithNesting = WithNesting{withNestingNestedMessage :: Hs.Maybe TestProto.WithNesting_Nested}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNesting where nameOf _ = (Hs.fromString "WithNesting") +instance HsProtobuf.HasDefault WithNesting+ instance HsProtobuf.Message WithNesting where encodeMessage _ WithNesting{withNestingNestedMessage = withNestingNestedMessage} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested withNestingNestedMessage))])+ (Hs.coerce @(Hs.Maybe TestProto.WithNesting_Nested)+ @(HsProtobuf.Nested TestProto.WithNesting_Nested)+ withNestingNestedMessage))]) decodeMessage _ = (Hs.pure WithNesting) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.WithNesting_Nested))+ @(_ (Hs.Maybe TestProto.WithNesting_Nested)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -466,7 +472,7 @@ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "Nested"))) (HsProtobuf.Single "nestedMessage") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNesting where toJSONPB (WithNesting f1)@@ -504,20 +510,18 @@ [("nestedMessage", withNestingNestedMessage)]}}) -instance HsDhallPb.Interpret WithNesting- -instance HsDhallPb.Inject WithNesting- data WithNesting_Nested = WithNesting_Nested{withNesting_NestedNestedField1 :: Hs.Text, withNesting_NestedNestedField2 :: Hs.Int32, withNesting_NestedNestedPacked :: Hs.Vector Hs.Int32, withNesting_NestedNestedUnpacked :: Hs.Vector Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNesting_Nested where nameOf _ = (Hs.fromString "WithNesting_Nested") +instance HsProtobuf.HasDefault WithNesting_Nested+ instance HsProtobuf.Message WithNesting_Nested where encodeMessage _ WithNesting_Nested{withNesting_NestedNestedField1 =@@ -532,9 +536,11 @@ (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2) withNesting_NestedNestedField2), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)- (HsProtobuf.PackedVec withNesting_NestedNestedPacked)),+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.PackedVec Hs.Int32)+ withNesting_NestedNestedPacked)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 4)- (HsProtobuf.UnpackedVec withNesting_NestedNestedUnpacked))])+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.UnpackedVec Hs.Int32)+ withNesting_NestedNestedUnpacked))]) decodeMessage _ = (Hs.pure WithNesting_Nested) <*> (HsProtobuf.at HsProtobuf.decodeMessageField@@ -543,11 +549,13 @@ (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2)) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 3))) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.UnpackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 4))) dotProto _@@ -555,24 +563,24 @@ (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "nestedField1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedField2") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "nestedPacked") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "nestedUnpacked") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.False))]- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNesting_Nested where toJSONPB (WithNesting_Nested f1 f2 f3 f4)@@ -634,27 +642,29 @@ ("nestedUnpacked", withNesting_NestedNestedUnpacked)]}}) -instance HsDhallPb.Interpret WithNesting_Nested- -instance HsDhallPb.Inject WithNesting_Nested- data WithNestingRepeated = WithNestingRepeated{withNestingRepeatedNestedMessages :: Hs.Vector TestProto.WithNestingRepeated_Nested}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNestingRepeated where nameOf _ = (Hs.fromString "WithNestingRepeated") +instance HsProtobuf.HasDefault WithNestingRepeated+ instance HsProtobuf.Message WithNestingRepeated where encodeMessage _ WithNestingRepeated{withNestingRepeatedNestedMessages = withNestingRepeatedNestedMessages} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.NestedVec withNestingRepeatedNestedMessages))])+ (Hs.coerce @(Hs.Vector TestProto.WithNestingRepeated_Nested)+ @(HsProtobuf.NestedVec TestProto.WithNestingRepeated_Nested)+ withNestingRepeatedNestedMessages))]) decodeMessage _ = (Hs.pure WithNestingRepeated) <*>- ((Hs.pure HsProtobuf.nestedvec) <*>+ (Hs.coerce+ @(_ (HsProtobuf.NestedVec TestProto.WithNestingRepeated_Nested))+ @(_ (Hs.Vector TestProto.WithNestingRepeated_Nested)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -663,7 +673,7 @@ (HsProtobuf.Named (HsProtobuf.Single "Nested"))) (HsProtobuf.Single "nestedMessages") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNestingRepeated where toJSONPB (WithNestingRepeated f1)@@ -703,10 +713,6 @@ [("nestedMessages", withNestingRepeatedNestedMessages)]}}) -instance HsDhallPb.Interpret WithNestingRepeated- -instance HsDhallPb.Inject WithNestingRepeated- data WithNestingRepeated_Nested = WithNestingRepeated_Nested{withNestingRepeated_NestedNestedField1 :: Hs.Text, withNestingRepeated_NestedNestedField2@@ -715,11 +721,13 @@ :: Hs.Vector Hs.Int32, withNestingRepeated_NestedNestedUnpacked :: Hs.Vector Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNestingRepeated_Nested where nameOf _ = (Hs.fromString "WithNestingRepeated_Nested") +instance HsProtobuf.HasDefault WithNestingRepeated_Nested+ instance HsProtobuf.Message WithNestingRepeated_Nested where encodeMessage _ WithNestingRepeated_Nested{withNestingRepeated_NestedNestedField1 =@@ -736,9 +744,10 @@ (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2) withNestingRepeated_NestedNestedField2), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)- (HsProtobuf.PackedVec withNestingRepeated_NestedNestedPacked)),+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.PackedVec Hs.Int32)+ withNestingRepeated_NestedNestedPacked)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 4)- (HsProtobuf.UnpackedVec+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.UnpackedVec Hs.Int32) withNestingRepeated_NestedNestedUnpacked))]) decodeMessage _ = (Hs.pure WithNestingRepeated_Nested) <*>@@ -748,11 +757,13 @@ (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2)) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 3))) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.UnpackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 4))) dotProto _@@ -760,24 +771,24 @@ (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "nestedField1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedField2") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "nestedPacked") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "nestedUnpacked") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.False))]- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNestingRepeated_Nested where toJSONPB (WithNestingRepeated_Nested f1 f2 f3 f4)@@ -842,17 +853,15 @@ ("nestedUnpacked", withNestingRepeated_NestedNestedUnpacked)]}}) -instance HsDhallPb.Interpret WithNestingRepeated_Nested- -instance HsDhallPb.Inject WithNestingRepeated_Nested- data NestedInts = NestedInts{nestedIntsNestedInt1 :: Hs.Int32, nestedIntsNestedInt2 :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named NestedInts where nameOf _ = (Hs.fromString "NestedInts") +instance HsProtobuf.HasDefault NestedInts+ instance HsProtobuf.Message NestedInts where encodeMessage _ NestedInts{nestedIntsNestedInt1 = nestedIntsNestedInt1,@@ -874,12 +883,12 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedInt1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedInt2") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB NestedInts where toJSONPB (NestedInts f1 f2)@@ -921,27 +930,28 @@ [("nestedInt1", nestedIntsNestedInt1), ("nestedInt2", nestedIntsNestedInt2)]}}) -instance HsDhallPb.Interpret NestedInts- -instance HsDhallPb.Inject NestedInts- data WithNestingRepeatedInts = WithNestingRepeatedInts{withNestingRepeatedIntsNestedInts :: Hs.Vector TestProto.NestedInts}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNestingRepeatedInts where nameOf _ = (Hs.fromString "WithNestingRepeatedInts") +instance HsProtobuf.HasDefault WithNestingRepeatedInts+ instance HsProtobuf.Message WithNestingRepeatedInts where encodeMessage _ WithNestingRepeatedInts{withNestingRepeatedIntsNestedInts = withNestingRepeatedIntsNestedInts} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.NestedVec withNestingRepeatedIntsNestedInts))])+ (Hs.coerce @(Hs.Vector TestProto.NestedInts)+ @(HsProtobuf.NestedVec TestProto.NestedInts)+ withNestingRepeatedIntsNestedInts))]) decodeMessage _ = (Hs.pure WithNestingRepeatedInts) <*>- ((Hs.pure HsProtobuf.nestedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.NestedVec TestProto.NestedInts))+ @(_ (Hs.Vector TestProto.NestedInts)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -950,7 +960,7 @@ (HsProtobuf.Named (HsProtobuf.Single "NestedInts"))) (HsProtobuf.Single "nestedInts") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNestingRepeatedInts where toJSONPB (WithNestingRepeatedInts f1)@@ -989,27 +999,28 @@ [("nestedInts", withNestingRepeatedIntsNestedInts)]}}) -instance HsDhallPb.Interpret WithNestingRepeatedInts- -instance HsDhallPb.Inject WithNestingRepeatedInts- data WithNestingInts = WithNestingInts{withNestingIntsNestedInts :: Hs.Maybe TestProto.NestedInts}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNestingInts where nameOf _ = (Hs.fromString "WithNestingInts") +instance HsProtobuf.HasDefault WithNestingInts+ instance HsProtobuf.Message WithNestingInts where encodeMessage _ WithNestingInts{withNestingIntsNestedInts = withNestingIntsNestedInts} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested withNestingIntsNestedInts))])+ (Hs.coerce @(Hs.Maybe TestProto.NestedInts)+ @(HsProtobuf.Nested TestProto.NestedInts)+ withNestingIntsNestedInts))]) decodeMessage _ = (Hs.pure WithNestingInts) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.NestedInts))+ @(_ (Hs.Maybe TestProto.NestedInts)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -1018,7 +1029,7 @@ (HsProtobuf.Named (HsProtobuf.Single "NestedInts"))) (HsProtobuf.Single "nestedInts") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNestingInts where toJSONPB (WithNestingInts f1)@@ -1056,27 +1067,27 @@ [("nestedInts", withNestingIntsNestedInts)]}}) -instance HsDhallPb.Interpret WithNestingInts- -instance HsDhallPb.Inject WithNestingInts- data WithRepetition = WithRepetition{withRepetitionRepeatedField1 :: Hs.Vector Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithRepetition where nameOf _ = (Hs.fromString "WithRepetition") +instance HsProtobuf.HasDefault WithRepetition+ instance HsProtobuf.Message WithRepetition where encodeMessage _ WithRepetition{withRepetitionRepeatedField1 = withRepetitionRepeatedField1} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.PackedVec withRepetitionRepeatedField1))])+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.PackedVec Hs.Int32)+ withRepetitionRepeatedField1))]) decodeMessage _ = (Hs.pure WithRepetition) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -1084,7 +1095,7 @@ (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "repeatedField1") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithRepetition where toJSONPB (WithRepetition f1)@@ -1122,20 +1133,16 @@ [("repeatedField1", withRepetitionRepeatedField1)]}}) -instance HsDhallPb.Interpret WithRepetition- -instance HsDhallPb.Inject WithRepetition- -data WithFixed = WithFixed{withFixedFixed1 ::- HsProtobuf.Fixed Hs.Word32,- withFixedFixed2 :: HsProtobuf.Fixed Hs.Int32,- withFixedFixed3 :: HsProtobuf.Fixed Hs.Word64,- withFixedFixed4 :: HsProtobuf.Fixed Hs.Int64}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+data WithFixed = WithFixed{withFixedFixed1 :: Hs.Word32,+ withFixedFixed2 :: Hs.Int32, withFixedFixed3 :: Hs.Word64,+ withFixedFixed4 :: Hs.Int64}+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithFixed where nameOf _ = (Hs.fromString "WithFixed") +instance HsProtobuf.HasDefault WithFixed+ instance HsProtobuf.Message WithFixed where encodeMessage _ WithFixed{withFixedFixed1 = withFixedFixed1,@@ -1144,26 +1151,36 @@ withFixedFixed4 = withFixedFixed4} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- withFixedFixed1),+ (Hs.coerce @(Hs.Word32) @(HsProtobuf.Fixed Hs.Word32)+ withFixedFixed1)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.Signed withFixedFixed2)),+ (Hs.coerce @(Hs.Int32)+ @(HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int32))+ withFixedFixed2)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)- withFixedFixed3),+ (Hs.coerce @(Hs.Word64) @(HsProtobuf.Fixed Hs.Word64)+ withFixedFixed3)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 4)- (HsProtobuf.Signed withFixedFixed4))])+ (Hs.coerce @(Hs.Int64)+ @(HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int64))+ withFixedFixed4))]) decodeMessage _ = (Hs.pure WithFixed) <*>- (HsProtobuf.at HsProtobuf.decodeMessageField- (HsProtobuf.FieldNumber 1))+ (Hs.coerce @(_ (HsProtobuf.Fixed Hs.Word32)) @(_ Hs.Word32)+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int32)))+ @(_ Hs.Int32) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) <*>- (HsProtobuf.at HsProtobuf.decodeMessageField- (HsProtobuf.FieldNumber 3))+ (Hs.coerce @(_ (HsProtobuf.Fixed Hs.Word64)) @(_ Hs.Word64)+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 3))) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int64)))+ @(_ Hs.Int64) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 4))) dotProto _@@ -1171,22 +1188,22 @@ (HsProtobuf.Prim HsProtobuf.Fixed32) (HsProtobuf.Single "fixed1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.SFixed32) (HsProtobuf.Single "fixed2") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3) (HsProtobuf.Prim HsProtobuf.Fixed64) (HsProtobuf.Single "fixed3") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Prim HsProtobuf.SFixed64) (HsProtobuf.Single "fixed4") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithFixed where toJSONPB (WithFixed f1 f2 f3 f4)@@ -1239,17 +1256,15 @@ ("fixed3", withFixedFixed3), ("fixed4", withFixedFixed4)]}}) -instance HsDhallPb.Interpret WithFixed- -instance HsDhallPb.Inject WithFixed- data WithBytes = WithBytes{withBytesBytes1 :: Hs.ByteString, withBytesBytes2 :: Hs.Vector Hs.ByteString}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithBytes where nameOf _ = (Hs.fromString "WithBytes") +instance HsProtobuf.HasDefault WithBytes+ instance HsProtobuf.Message WithBytes where encodeMessage _ WithBytes{withBytesBytes1 = withBytesBytes1,@@ -1258,13 +1273,16 @@ [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1) withBytesBytes1), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.UnpackedVec withBytesBytes2))])+ (Hs.coerce @(Hs.Vector Hs.ByteString)+ @(HsProtobuf.UnpackedVec Hs.ByteString)+ withBytesBytes2))]) decodeMessage _ = (Hs.pure WithBytes) <*> (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1)) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.UnpackedVec Hs.ByteString))+ @(_ (Hs.Vector Hs.ByteString)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) dotProto _@@ -1272,12 +1290,12 @@ (HsProtobuf.Prim HsProtobuf.Bytes) (HsProtobuf.Single "bytes1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Repeated HsProtobuf.Bytes) (HsProtobuf.Single "bytes2") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithBytes where toJSONPB (WithBytes f1 f2)@@ -1318,34 +1336,36 @@ [("bytes1", withBytesBytes1), ("bytes2", withBytesBytes2)]}}) -instance HsDhallPb.Interpret WithBytes- -instance HsDhallPb.Inject WithBytes- data WithPacking = WithPacking{withPackingPacking1 :: Hs.Vector Hs.Int32, withPackingPacking2 :: Hs.Vector Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithPacking where nameOf _ = (Hs.fromString "WithPacking") +instance HsProtobuf.HasDefault WithPacking+ instance HsProtobuf.Message WithPacking where encodeMessage _ WithPacking{withPackingPacking1 = withPackingPacking1, withPackingPacking2 = withPackingPacking2} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.UnpackedVec withPackingPacking1)),+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.UnpackedVec Hs.Int32)+ withPackingPacking1)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.PackedVec withPackingPacking2))])+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.PackedVec Hs.Int32)+ withPackingPacking2))]) decodeMessage _ = (Hs.pure WithPacking) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.UnpackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) dotProto _@@ -1354,13 +1374,13 @@ (HsProtobuf.Single "packing1") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.False))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "packing2") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithPacking where toJSONPB (WithPacking f1 f2)@@ -1401,28 +1421,31 @@ [("packing1", withPackingPacking1), ("packing2", withPackingPacking2)]}}) -instance HsDhallPb.Interpret WithPacking- -instance HsDhallPb.Inject WithPacking- data E = EFLD0 | EFLD1- deriving (Hs.Show, Hs.Bounded, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Generic, Hs.NFData) instance HsProtobuf.Named E where nameOf _ = (Hs.fromString "E") -instance Hs.Enum E where- toEnum 0 = EFLD0- toEnum 1 = EFLD1- toEnum i = (Hs.toEnumError "E" i (0 :: Hs.Int, 1))- fromEnum (EFLD0) = 0- fromEnum (EFLD1) = 1- succ (EFLD0) = EFLD1- succ _ = Hs.succError "E"- pred (EFLD1) = EFLD0- pred _ = Hs.predError "E"+instance HsProtobuf.HasDefault E +instance Hs.Bounded E where+ minBound = EFLD0+ maxBound = EFLD1+ +instance Hs.Ord E where+ compare x y+ = Hs.compare (HsProtobuf.fromProtoEnum x)+ (HsProtobuf.fromProtoEnum y)+ +instance HsProtobuf.ProtoEnum E where+ toProtoEnumMay 0 = Hs.Just EFLD0+ toProtoEnumMay 1 = Hs.Just EFLD1+ toProtoEnumMay _ = Hs.Nothing+ fromProtoEnum (EFLD0) = 0+ fromProtoEnum (EFLD1) = 1+ instance HsJSONPB.ToJSONPB E where toJSONPB x _ = HsJSONPB.enumFieldString x toEncodingPB x _ = HsJSONPB.enumFieldEncoding x@@ -1439,10 +1462,6 @@ instance HsJSONPB.FromJSON E where parseJSON = HsJSONPB.parseJSONPB -instance HsDhallPb.Interpret E- -instance HsDhallPb.Inject E- instance HsProtobuf.Finite E data AllPackedTypes = AllPackedTypes{allPackedTypesPackedWord32 ::@@ -1450,26 +1469,24 @@ allPackedTypesPackedWord64 :: Hs.Vector Hs.Word64, allPackedTypesPackedInt32 :: Hs.Vector Hs.Int32, allPackedTypesPackedInt64 :: Hs.Vector Hs.Int64,- allPackedTypesPackedFixed32 ::- Hs.Vector (HsProtobuf.Fixed Hs.Word32),- allPackedTypesPackedFixed64 ::- Hs.Vector (HsProtobuf.Fixed Hs.Word64),+ allPackedTypesPackedFixed32 :: Hs.Vector Hs.Word32,+ allPackedTypesPackedFixed64 :: Hs.Vector Hs.Word64, allPackedTypesPackedFloat :: Hs.Vector Hs.Float, allPackedTypesPackedDouble :: Hs.Vector Hs.Double,- allPackedTypesPackedSFixed32 ::- Hs.Vector (HsProtobuf.Fixed Hs.Int32),- allPackedTypesPackedSFixed64 ::- Hs.Vector (HsProtobuf.Fixed Hs.Int64),+ allPackedTypesPackedSFixed32 :: Hs.Vector Hs.Int32,+ allPackedTypesPackedSFixed64 :: Hs.Vector Hs.Int64, allPackedTypesPackedBool :: Hs.Vector Hs.Bool, allPackedTypesPackedEnum :: Hs.Vector (HsProtobuf.Enumerated TestProto.E), allPackedTypesUnpackedEnum :: Hs.Vector (HsProtobuf.Enumerated TestProto.E)}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named AllPackedTypes where nameOf _ = (Hs.fromString "AllPackedTypes") +instance HsProtobuf.HasDefault AllPackedTypes+ instance HsProtobuf.Message AllPackedTypes where encodeMessage _ AllPackedTypes{allPackedTypesPackedWord32 =@@ -1488,86 +1505,118 @@ allPackedTypesUnpackedEnum = allPackedTypesUnpackedEnum} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.PackedVec allPackedTypesPackedWord32)),+ (Hs.coerce @(Hs.Vector Hs.Word32) @(HsProtobuf.PackedVec Hs.Word32)+ allPackedTypesPackedWord32)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.PackedVec allPackedTypesPackedWord64)),+ (Hs.coerce @(Hs.Vector Hs.Word64) @(HsProtobuf.PackedVec Hs.Word64)+ allPackedTypesPackedWord64)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)- (HsProtobuf.PackedVec allPackedTypesPackedInt32)),+ (Hs.coerce @(Hs.Vector Hs.Int32) @(HsProtobuf.PackedVec Hs.Int32)+ allPackedTypesPackedInt32)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 4)- (HsProtobuf.PackedVec allPackedTypesPackedInt64)),+ (Hs.coerce @(Hs.Vector Hs.Int64) @(HsProtobuf.PackedVec Hs.Int64)+ allPackedTypesPackedInt64)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 5)- (HsProtobuf.PackedVec allPackedTypesPackedFixed32)),+ (Hs.coerce @(Hs.Vector Hs.Word32)+ @(HsProtobuf.PackedVec (HsProtobuf.Fixed Hs.Word32))+ allPackedTypesPackedFixed32)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 6)- (HsProtobuf.PackedVec allPackedTypesPackedFixed64)),+ (Hs.coerce @(Hs.Vector Hs.Word64)+ @(HsProtobuf.PackedVec (HsProtobuf.Fixed Hs.Word64))+ allPackedTypesPackedFixed64)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 7)- (HsProtobuf.PackedVec allPackedTypesPackedFloat)),+ (Hs.coerce @(Hs.Vector Hs.Float) @(HsProtobuf.PackedVec Hs.Float)+ allPackedTypesPackedFloat)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 8)- (HsProtobuf.PackedVec allPackedTypesPackedDouble)),+ (Hs.coerce @(Hs.Vector Hs.Double) @(HsProtobuf.PackedVec Hs.Double)+ allPackedTypesPackedDouble)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 9)- (HsProtobuf.PackedVec- (Hs.fmap HsProtobuf.Signed allPackedTypesPackedSFixed32))),+ (Hs.coerce @(Hs.Vector Hs.Int32)+ @(HsProtobuf.PackedVec (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int32)))+ allPackedTypesPackedSFixed32)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 10)- (HsProtobuf.PackedVec- (Hs.fmap HsProtobuf.Signed allPackedTypesPackedSFixed64))),+ (Hs.coerce @(Hs.Vector Hs.Int64)+ @(HsProtobuf.PackedVec (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int64)))+ allPackedTypesPackedSFixed64)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 11)- (HsProtobuf.PackedVec allPackedTypesPackedBool)),+ (Hs.coerce @(Hs.Vector Hs.Bool) @(HsProtobuf.PackedVec Hs.Bool)+ allPackedTypesPackedBool)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 12)- (HsProtobuf.PackedVec allPackedTypesPackedEnum)),+ (Hs.coerce @(Hs.Vector (HsProtobuf.Enumerated TestProto.E))+ @(HsProtobuf.PackedVec (HsProtobuf.Enumerated TestProto.E))+ allPackedTypesPackedEnum)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 13)- (HsProtobuf.UnpackedVec allPackedTypesUnpackedEnum))])+ (Hs.coerce @(Hs.Vector (HsProtobuf.Enumerated TestProto.E))+ @(HsProtobuf.UnpackedVec (HsProtobuf.Enumerated TestProto.E))+ allPackedTypesUnpackedEnum))]) decodeMessage _ = (Hs.pure AllPackedTypes) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Word32))+ @(_ (Hs.Vector Hs.Word32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Word64))+ @(_ (Hs.Vector Hs.Word64)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int32))+ @(_ (Hs.Vector Hs.Int32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 3))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Int64))+ @(_ (Hs.Vector Hs.Int64)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 4))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec (HsProtobuf.Fixed Hs.Word32)))+ @(_ (Hs.Vector Hs.Word32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 5))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec (HsProtobuf.Fixed Hs.Word64)))+ @(_ (Hs.Vector Hs.Word64)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 6))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Float))+ @(_ (Hs.Vector Hs.Float)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 7))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Double))+ @(_ (Hs.Vector Hs.Double)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 8))) <*>- ((Hs.pure (Hs.fmap HsProtobuf.signed)) <*>- ((Hs.pure HsProtobuf.packedvec) <*>- (HsProtobuf.at HsProtobuf.decodeMessageField- (HsProtobuf.FieldNumber 9))))+ (Hs.coerce+ @(_ (HsProtobuf.PackedVec (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int32))))+ @(_ (Hs.Vector Hs.Int32))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 9))) <*>- ((Hs.pure (Hs.fmap HsProtobuf.signed)) <*>- ((Hs.pure HsProtobuf.packedvec) <*>- (HsProtobuf.at HsProtobuf.decodeMessageField- (HsProtobuf.FieldNumber 10))))+ (Hs.coerce+ @(_ (HsProtobuf.PackedVec (HsProtobuf.Signed (HsProtobuf.Fixed Hs.Int64))))+ @(_ (Hs.Vector Hs.Int64))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 10))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Bool))+ @(_ (Hs.Vector Hs.Bool)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 11))) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce+ @(_ (HsProtobuf.PackedVec (HsProtobuf.Enumerated TestProto.E)))+ @(_ (Hs.Vector (HsProtobuf.Enumerated TestProto.E))) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 12))) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce+ @(_ (HsProtobuf.UnpackedVec (HsProtobuf.Enumerated TestProto.E)))+ @(_ (Hs.Vector (HsProtobuf.Enumerated TestProto.E))) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 13))) dotProto _@@ -1576,79 +1625,79 @@ (HsProtobuf.Single "packedWord32") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Repeated HsProtobuf.UInt64) (HsProtobuf.Single "packedWord64") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3) (HsProtobuf.Repeated HsProtobuf.Int32) (HsProtobuf.Single "packedInt32") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Repeated HsProtobuf.Int64) (HsProtobuf.Single "packedInt64") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 5) (HsProtobuf.Repeated HsProtobuf.Fixed32) (HsProtobuf.Single "packedFixed32") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 6) (HsProtobuf.Repeated HsProtobuf.Fixed64) (HsProtobuf.Single "packedFixed64") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 7) (HsProtobuf.Repeated HsProtobuf.Float) (HsProtobuf.Single "packedFloat") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 8) (HsProtobuf.Repeated HsProtobuf.Double) (HsProtobuf.Single "packedDouble") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 9) (HsProtobuf.Repeated HsProtobuf.SFixed32) (HsProtobuf.Single "packedSFixed32") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 10) (HsProtobuf.Repeated HsProtobuf.SFixed64) (HsProtobuf.Single "packedSFixed64") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 11) (HsProtobuf.Repeated HsProtobuf.Bool) (HsProtobuf.Single "packedBool") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 12) (HsProtobuf.Repeated (HsProtobuf.Named (HsProtobuf.Single "E"))) (HsProtobuf.Single "packedEnum") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 13) (HsProtobuf.Repeated (HsProtobuf.Named (HsProtobuf.Single "E"))) (HsProtobuf.Single "unpackedEnum") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.False))]- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB AllPackedTypes where toJSONPB@@ -1766,20 +1815,18 @@ ("unpackedEnum", allPackedTypesUnpackedEnum)]}}) -instance HsDhallPb.Interpret AllPackedTypes- -instance HsDhallPb.Inject AllPackedTypes- data OutOfOrderFields = OutOfOrderFields{outOfOrderFieldsField1 :: Hs.Vector Hs.Word32, outOfOrderFieldsField2 :: Hs.Text, outOfOrderFieldsField3 :: Hs.Int64, outOfOrderFieldsField4 :: Hs.Vector Hs.Text}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named OutOfOrderFields where nameOf _ = (Hs.fromString "OutOfOrderFields") +instance HsProtobuf.HasDefault OutOfOrderFields+ instance HsProtobuf.Message OutOfOrderFields where encodeMessage _ OutOfOrderFields{outOfOrderFieldsField1 = outOfOrderFieldsField1,@@ -1788,16 +1835,19 @@ outOfOrderFieldsField4 = outOfOrderFieldsField4} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2001)- (HsProtobuf.PackedVec outOfOrderFieldsField1)),+ (Hs.coerce @(Hs.Vector Hs.Word32) @(HsProtobuf.PackedVec Hs.Word32)+ outOfOrderFieldsField1)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 101) outOfOrderFieldsField2), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 30) outOfOrderFieldsField3), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1002)- (HsProtobuf.UnpackedVec outOfOrderFieldsField4))])+ (Hs.coerce @(Hs.Vector Hs.Text) @(HsProtobuf.UnpackedVec Hs.Text)+ outOfOrderFieldsField4))]) decodeMessage _ = (Hs.pure OutOfOrderFields) <*>- ((Hs.pure HsProtobuf.packedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.PackedVec Hs.Word32))+ @(_ (Hs.Vector Hs.Word32)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2001))) <*>@@ -1807,7 +1857,8 @@ (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 30)) <*>- ((Hs.pure HsProtobuf.unpackedvec) <*>+ (Hs.coerce @(_ (HsProtobuf.UnpackedVec Hs.Text))+ @(_ (Hs.Vector Hs.Text)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1002))) dotProto _@@ -1816,22 +1867,22 @@ (HsProtobuf.Single "field1") [(HsProtobuf.DotProtoOption (HsProtobuf.Single "packed") (HsProtobuf.BoolLit Hs.True))]- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 101) (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "field2") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 30) (HsProtobuf.Prim HsProtobuf.Int64) (HsProtobuf.Single "field3") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1002) (HsProtobuf.Repeated HsProtobuf.String) (HsProtobuf.Single "field4") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB OutOfOrderFields where toJSONPB (OutOfOrderFields f2001 f101 f30 f1002)@@ -1887,18 +1938,16 @@ ("field3", outOfOrderFieldsField3), ("field4", outOfOrderFieldsField4)]}}) -instance HsDhallPb.Interpret OutOfOrderFields- -instance HsDhallPb.Inject OutOfOrderFields- data ShadowedMessage = ShadowedMessage{shadowedMessageName :: Hs.Text, shadowedMessageValue :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named ShadowedMessage where nameOf _ = (Hs.fromString "ShadowedMessage") +instance HsProtobuf.HasDefault ShadowedMessage+ instance HsProtobuf.Message ShadowedMessage where encodeMessage _ ShadowedMessage{shadowedMessageName = shadowedMessageName,@@ -1920,12 +1969,12 @@ (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "name") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "value") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB ShadowedMessage where toJSONPB (ShadowedMessage f2 f1)@@ -1966,18 +2015,16 @@ [("name", shadowedMessageName), ("value", shadowedMessageValue)]}}) -instance HsDhallPb.Interpret ShadowedMessage- -instance HsDhallPb.Inject ShadowedMessage- data MessageShadower = MessageShadower{messageShadowerShadowedMessage :: Hs.Maybe TestProto.MessageShadower_ShadowedMessage, messageShadowerName :: Hs.Text}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named MessageShadower where nameOf _ = (Hs.fromString "MessageShadower") +instance HsProtobuf.HasDefault MessageShadower+ instance HsProtobuf.Message MessageShadower where encodeMessage _ MessageShadower{messageShadowerShadowedMessage =@@ -1985,12 +2032,16 @@ messageShadowerName = messageShadowerName} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested messageShadowerShadowedMessage)),+ (Hs.coerce @(Hs.Maybe TestProto.MessageShadower_ShadowedMessage)+ @(HsProtobuf.Nested TestProto.MessageShadower_ShadowedMessage)+ messageShadowerShadowedMessage)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2) messageShadowerName)]) decodeMessage _ = (Hs.pure MessageShadower) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce+ @(_ (HsProtobuf.Nested TestProto.MessageShadower_ShadowedMessage))+ @(_ (Hs.Maybe TestProto.MessageShadower_ShadowedMessage)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>@@ -2002,12 +2053,12 @@ (HsProtobuf.Named (HsProtobuf.Single "ShadowedMessage"))) (HsProtobuf.Single "shadowed_message") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "name") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB MessageShadower where toJSONPB (MessageShadower f1 f2)@@ -2052,19 +2103,17 @@ messageShadowerShadowedMessage), ("name", messageShadowerName)]}}) -instance HsDhallPb.Interpret MessageShadower- -instance HsDhallPb.Inject MessageShadower- data MessageShadower_ShadowedMessage = MessageShadower_ShadowedMessage{messageShadower_ShadowedMessageName :: Hs.Text, messageShadower_ShadowedMessageValue :: Hs.Text}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named MessageShadower_ShadowedMessage where nameOf _ = (Hs.fromString "MessageShadower_ShadowedMessage") +instance HsProtobuf.HasDefault MessageShadower_ShadowedMessage+ instance HsProtobuf.Message MessageShadower_ShadowedMessage where encodeMessage _ MessageShadower_ShadowedMessage{messageShadower_ShadowedMessageName@@ -2088,12 +2137,12 @@ (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "name") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.String) (HsProtobuf.Single "value") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB MessageShadower_ShadowedMessage where toJSONPB (MessageShadower_ShadowedMessage f1 f2)@@ -2138,19 +2187,17 @@ ("value", messageShadower_ShadowedMessageValue)]}}) -instance HsDhallPb.Interpret MessageShadower_ShadowedMessage- -instance HsDhallPb.Inject MessageShadower_ShadowedMessage- data WithQualifiedName = WithQualifiedName{withQualifiedNameQname1 :: Hs.Maybe TestProto.ShadowedMessage, withQualifiedNameQname2 :: Hs.Maybe TestProto.MessageShadower_ShadowedMessage}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithQualifiedName where nameOf _ = (Hs.fromString "WithQualifiedName") +instance HsProtobuf.HasDefault WithQualifiedName+ instance HsProtobuf.Message WithQualifiedName where encodeMessage _ WithQualifiedName{withQualifiedNameQname1 =@@ -2158,16 +2205,23 @@ withQualifiedNameQname2 = withQualifiedNameQname2} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 100)- (HsProtobuf.Nested withQualifiedNameQname1)),+ (Hs.coerce @(Hs.Maybe TestProto.ShadowedMessage)+ @(HsProtobuf.Nested TestProto.ShadowedMessage)+ withQualifiedNameQname1)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 200)- (HsProtobuf.Nested withQualifiedNameQname2))])+ (Hs.coerce @(Hs.Maybe TestProto.MessageShadower_ShadowedMessage)+ @(HsProtobuf.Nested TestProto.MessageShadower_ShadowedMessage)+ withQualifiedNameQname2))]) decodeMessage _ = (Hs.pure WithQualifiedName) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.ShadowedMessage))+ @(_ (Hs.Maybe TestProto.ShadowedMessage)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 100))) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce+ @(_ (HsProtobuf.Nested TestProto.MessageShadower_ShadowedMessage))+ @(_ (Hs.Maybe TestProto.MessageShadower_ShadowedMessage)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 200))) dotProto _@@ -2176,15 +2230,15 @@ (HsProtobuf.Named (HsProtobuf.Single "ShadowedMessage"))) (HsProtobuf.Single "qname1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 200) (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Dots- (HsProtobuf.Path ["MessageShadower", "ShadowedMessage"]))))+ (HsProtobuf.Path ("MessageShadower" Hs.:| ["ShadowedMessage"]))))) (HsProtobuf.Single "qname2") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithQualifiedName where toJSONPB (WithQualifiedName f100 f200)@@ -2227,18 +2281,16 @@ [("qname1", withQualifiedNameQname1), ("qname2", withQualifiedNameQname2)]}}) -instance HsDhallPb.Interpret WithQualifiedName- -instance HsDhallPb.Inject WithQualifiedName- data UsingImported = UsingImported{usingImportedImportedNesting :: Hs.Maybe TestProtoImport.WithNesting, usingImportedLocalNesting :: Hs.Maybe TestProto.WithNesting}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named UsingImported where nameOf _ = (Hs.fromString "UsingImported") +instance HsProtobuf.HasDefault UsingImported+ instance HsProtobuf.Message UsingImported where encodeMessage _ UsingImported{usingImportedImportedNesting =@@ -2246,16 +2298,22 @@ usingImportedLocalNesting = usingImportedLocalNesting} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 100)- (HsProtobuf.Nested usingImportedImportedNesting)),+ (Hs.coerce @(Hs.Maybe TestProtoImport.WithNesting)+ @(HsProtobuf.Nested TestProtoImport.WithNesting)+ usingImportedImportedNesting)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 200)- (HsProtobuf.Nested usingImportedLocalNesting))])+ (Hs.coerce @(Hs.Maybe TestProto.WithNesting)+ @(HsProtobuf.Nested TestProto.WithNesting)+ usingImportedLocalNesting))]) decodeMessage _ = (Hs.pure UsingImported) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoImport.WithNesting))+ @(_ (Hs.Maybe TestProtoImport.WithNesting)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 100))) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.WithNesting))+ @(_ (Hs.Maybe TestProto.WithNesting)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 200))) dotProto _@@ -2263,16 +2321,16 @@ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Dots- (HsProtobuf.Path ["TestProtoImport", "WithNesting"]))))+ (HsProtobuf.Path ("TestProtoImport" Hs.:| ["WithNesting"]))))) (HsProtobuf.Single "importedNesting") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 200) (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "WithNesting"))) (HsProtobuf.Single "localNesting") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB UsingImported where toJSONPB (UsingImported f100 f200)@@ -2319,25 +2377,26 @@ ("localNesting", usingImportedLocalNesting)]}}) -instance HsDhallPb.Interpret UsingImported- -instance HsDhallPb.Inject UsingImported- data Wrapped = Wrapped{wrappedWrapped :: Hs.Maybe TestProto.Wrapped}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named Wrapped where nameOf _ = (Hs.fromString "Wrapped") +instance HsProtobuf.HasDefault Wrapped+ instance HsProtobuf.Message Wrapped where encodeMessage _ Wrapped{wrappedWrapped = wrappedWrapped} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested wrappedWrapped))])+ (Hs.coerce @(Hs.Maybe TestProto.Wrapped)+ @(HsProtobuf.Nested TestProto.Wrapped)+ wrappedWrapped))]) decodeMessage _ = (Hs.pure Wrapped) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.Wrapped))+ @(_ (Hs.Maybe TestProto.Wrapped)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) dotProto _@@ -2345,7 +2404,7 @@ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "Wrapped"))) (HsProtobuf.Single "wrapped") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB Wrapped where toJSONPB (Wrapped f1) = (HsJSONPB.object ["wrapped" .= f1])@@ -2379,28 +2438,31 @@ HsJSONPB.insOrdFromList [("wrapped", wrappedWrapped)]}}) -instance HsDhallPb.Interpret Wrapped- -instance HsDhallPb.Inject Wrapped- data EnumAnnots = EnumAnnotsFOO | EnumAnnotsBAR- deriving (Hs.Show, Hs.Bounded, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Generic, Hs.NFData) instance HsProtobuf.Named EnumAnnots where nameOf _ = (Hs.fromString "EnumAnnots") -instance Hs.Enum EnumAnnots where- toEnum 0 = EnumAnnotsFOO- toEnum 1 = EnumAnnotsBAR- toEnum i = (Hs.toEnumError "EnumAnnots" i (0 :: Hs.Int, 1))- fromEnum (EnumAnnotsFOO) = 0- fromEnum (EnumAnnotsBAR) = 1- succ (EnumAnnotsFOO) = EnumAnnotsBAR- succ _ = Hs.succError "EnumAnnots"- pred (EnumAnnotsBAR) = EnumAnnotsFOO- pred _ = Hs.predError "EnumAnnots"+instance HsProtobuf.HasDefault EnumAnnots +instance Hs.Bounded EnumAnnots where+ minBound = EnumAnnotsFOO+ maxBound = EnumAnnotsBAR+ +instance Hs.Ord EnumAnnots where+ compare x y+ = Hs.compare (HsProtobuf.fromProtoEnum x)+ (HsProtobuf.fromProtoEnum y)+ +instance HsProtobuf.ProtoEnum EnumAnnots where+ toProtoEnumMay 0 = Hs.Just EnumAnnotsFOO+ toProtoEnumMay 1 = Hs.Just EnumAnnotsBAR+ toProtoEnumMay _ = Hs.Nothing+ fromProtoEnum (EnumAnnotsFOO) = 0+ fromProtoEnum (EnumAnnotsBAR) = 1+ instance HsJSONPB.ToJSONPB EnumAnnots where toJSONPB x _ = HsJSONPB.enumFieldString x toEncodingPB x _ = HsJSONPB.enumFieldEncoding x@@ -2417,8 +2479,176 @@ instance HsJSONPB.FromJSON EnumAnnots where parseJSON = HsJSONPB.parseJSONPB -instance HsDhallPb.Interpret EnumAnnots+instance HsProtobuf.Finite EnumAnnots -instance HsDhallPb.Inject EnumAnnots+data WrappedTrivial = WrappedTrivial{wrappedTrivialTrivial ::+ Hs.Maybe TestProto.Trivial}+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) -instance HsProtobuf.Finite EnumAnnots+instance HsProtobuf.Named WrappedTrivial where+ nameOf _ = (Hs.fromString "WrappedTrivial")+ +instance HsProtobuf.HasDefault WrappedTrivial+ +instance HsProtobuf.Message WrappedTrivial where+ encodeMessage _+ WrappedTrivial{wrappedTrivialTrivial = wrappedTrivialTrivial}+ = (Hs.mconcat+ [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)+ (Hs.coerce @(Hs.Maybe TestProto.Trivial)+ @(HsProtobuf.Nested TestProto.Trivial)+ wrappedTrivialTrivial))])+ decodeMessage _+ = (Hs.pure WrappedTrivial) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProto.Trivial))+ @(_ (Hs.Maybe TestProto.Trivial))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 1)))+ dotProto _+ = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1)+ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "Trivial")))+ (HsProtobuf.Single "trivial")+ []+ "")]+ +instance HsJSONPB.ToJSONPB WrappedTrivial where+ toJSONPB (WrappedTrivial f1) = (HsJSONPB.object ["trivial" .= f1])+ toEncodingPB (WrappedTrivial f1)+ = (HsJSONPB.pairs ["trivial" .= f1])+ +instance HsJSONPB.FromJSONPB WrappedTrivial where+ parseJSONPB+ = (HsJSONPB.withObject "WrappedTrivial"+ (\ obj -> (Hs.pure WrappedTrivial) <*> obj .: "trivial"))+ +instance HsJSONPB.ToJSON WrappedTrivial where+ toJSON = HsJSONPB.toAesonValue+ toEncoding = HsJSONPB.toAesonEncoding+ +instance HsJSONPB.FromJSON WrappedTrivial where+ parseJSON = HsJSONPB.parseJSONPB+ +instance HsJSONPB.ToSchema WrappedTrivial where+ declareNamedSchema _+ = do let declare_trivial = HsJSONPB.declareSchemaRef+ wrappedTrivialTrivial <- declare_trivial Proxy.Proxy+ let _ = Hs.pure WrappedTrivial <*> HsJSONPB.asProxy declare_trivial+ Hs.return+ (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName =+ Hs.Just "WrappedTrivial",+ HsJSONPB._namedSchemaSchema =+ Hs.mempty{HsJSONPB._schemaParamSchema =+ Hs.mempty{HsJSONPB._paramSchemaType =+ HsJSONPB.SwaggerObject},+ HsJSONPB._schemaProperties =+ HsJSONPB.insOrdFromList+ [("trivial", wrappedTrivialTrivial)]}})+ +data MapTest = MapTest{mapTestPrim :: Hs.Map Hs.Text Hs.Int32,+ mapTestTrivial ::+ Hs.Map Hs.Int32 (Hs.Maybe TestProto.WrappedTrivial),+ mapTestSigned :: Hs.Map Hs.Int32 Hs.Int32}+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData)+ +instance HsProtobuf.Named MapTest where+ nameOf _ = (Hs.fromString "MapTest")+ +instance HsProtobuf.HasDefault MapTest+ +instance HsProtobuf.Message MapTest where+ encodeMessage _+ MapTest{mapTestPrim = mapTestPrim, mapTestTrivial = mapTestTrivial,+ mapTestSigned = mapTestSigned}+ = (Hs.mconcat+ [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)+ (Hs.unsafeCoerce @(Hs.Map Hs.Text Hs.Int32)+ @(Hs.Map Hs.Text (HsProtobuf.Signed Hs.Int32))+ mapTestPrim)),+ (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)+ (Hs.unsafeCoerce+ @(Hs.Map Hs.Int32 (Hs.Maybe TestProto.WrappedTrivial))+ @(Hs.Map Hs.Int32 (HsProtobuf.Nested TestProto.WrappedTrivial))+ mapTestTrivial)),+ (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)+ (Hs.unsafeCoerce @(Hs.Map Hs.Int32 Hs.Int32)+ @(Hs.Map (HsProtobuf.Signed Hs.Int32) (HsProtobuf.Signed Hs.Int32))+ mapTestSigned))])+ decodeMessage _+ = (Hs.pure MapTest) <*>+ (Hs.unsafeCoerce @(_ (Hs.Map Hs.Text (HsProtobuf.Signed Hs.Int32)))+ @(_ (Hs.Map Hs.Text Hs.Int32))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 1)))+ <*>+ (Hs.unsafeCoerce+ @(_ (Hs.Map Hs.Int32 (HsProtobuf.Nested TestProto.WrappedTrivial)))+ @(_ (Hs.Map Hs.Int32 (Hs.Maybe TestProto.WrappedTrivial)))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 2)))+ <*>+ (Hs.unsafeCoerce+ @(_ (Hs.Map (HsProtobuf.Signed Hs.Int32) (HsProtobuf.Signed Hs.Int32)))+ @(_ (Hs.Map Hs.Int32 Hs.Int32))+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 3)))+ dotProto _+ = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1)+ (HsProtobuf.Map HsProtobuf.String HsProtobuf.SInt32)+ (HsProtobuf.Single "prim")+ []+ ""),+ (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2)+ (HsProtobuf.Map HsProtobuf.Int32+ (HsProtobuf.Named (HsProtobuf.Single "WrappedTrivial")))+ (HsProtobuf.Single "trivial")+ []+ ""),+ (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 3)+ (HsProtobuf.Map HsProtobuf.SInt32 HsProtobuf.SInt32)+ (HsProtobuf.Single "signed")+ []+ "")]+ +instance HsJSONPB.ToJSONPB MapTest where+ toJSONPB (MapTest f1 f2 f3)+ = (HsJSONPB.object ["prim" .= f1, "trivial" .= f2, "signed" .= f3])+ toEncodingPB (MapTest f1 f2 f3)+ = (HsJSONPB.pairs ["prim" .= f1, "trivial" .= f2, "signed" .= f3])+ +instance HsJSONPB.FromJSONPB MapTest where+ parseJSONPB+ = (HsJSONPB.withObject "MapTest"+ (\ obj ->+ (Hs.pure MapTest) <*> obj .: "prim" <*> obj .: "trivial" <*>+ obj .: "signed"))+ +instance HsJSONPB.ToJSON MapTest where+ toJSON = HsJSONPB.toAesonValue+ toEncoding = HsJSONPB.toAesonEncoding+ +instance HsJSONPB.FromJSON MapTest where+ parseJSON = HsJSONPB.parseJSONPB+ +instance HsJSONPB.ToSchema MapTest where+ declareNamedSchema _+ = do let declare_prim = HsJSONPB.declareSchemaRef+ mapTestPrim <- declare_prim Proxy.Proxy+ let declare_trivial = HsJSONPB.declareSchemaRef+ mapTestTrivial <- declare_trivial Proxy.Proxy+ let declare_signed = HsJSONPB.declareSchemaRef+ mapTestSigned <- declare_signed Proxy.Proxy+ let _ = Hs.pure MapTest <*> HsJSONPB.asProxy declare_prim <*>+ HsJSONPB.asProxy declare_trivial+ <*> HsJSONPB.asProxy declare_signed+ Hs.return+ (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName =+ Hs.Just "MapTest",+ HsJSONPB._namedSchemaSchema =+ Hs.mempty{HsJSONPB._schemaParamSchema =+ Hs.mempty{HsJSONPB._paramSchemaType =+ HsJSONPB.SwaggerObject},+ HsJSONPB._schemaProperties =+ HsJSONPB.insOrdFromList+ [("prim", mapTestPrim),+ ("trivial", mapTestTrivial),+ ("signed", mapTestSigned)]}})
gen/TestProtoImport.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-}@@ -9,51 +11,65 @@ -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module TestProtoImport where import qualified Prelude as Hs-import qualified Proto3.Suite.DhallPB as HsDhallPb-import qualified Proto3.Suite.DotProto as HsProtobuf-import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Suite.Class as HsProtobuf+import qualified Proto3.Suite.DotProto as HsProtobuf import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:))+import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf-import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.Applicative as Hs+import Control.Applicative ((<*>), (<|>), (<$>))+import qualified Control.DeepSeq as Hs import qualified Control.Monad as Hs-import qualified Data.Text.Lazy as Hs (Text) import qualified Data.ByteString as Hs+import qualified Data.Coerce as Hs+import qualified Data.Int as Hs (Int16, Int32, Int64)+import qualified Data.List.NonEmpty as Hs (NonEmpty(..))+import qualified Data.Map as Hs (Map, mapKeysMonotonic)+import qualified Data.Proxy as Proxy import qualified Data.String as Hs (fromString)+import qualified Data.Text.Lazy as Hs (Text) import qualified Data.Vector as Hs (Vector)-import qualified Data.Int as Hs (Int16, Int32, Int64) import qualified Data.Word as Hs (Word16, Word32, Word64)-import qualified Data.Proxy as Proxy-import qualified GHC.Generics as Hs import qualified GHC.Enum as Hs+import qualified GHC.Generics as Hs+import qualified Unsafe.Coerce as Hs data WithNesting = WithNesting{withNestingNestedMessage1 :: Hs.Maybe TestProtoImport.WithNesting_Nested, withNestingNestedMessage2 :: Hs.Maybe TestProtoImport.WithNesting_Nested}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNesting where nameOf _ = (Hs.fromString "WithNesting") +instance HsProtobuf.HasDefault WithNesting+ instance HsProtobuf.Message WithNesting where encodeMessage _ WithNesting{withNestingNestedMessage1 = withNestingNestedMessage1, withNestingNestedMessage2 = withNestingNestedMessage2} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested withNestingNestedMessage1)),+ (Hs.coerce @(Hs.Maybe TestProtoImport.WithNesting_Nested)+ @(HsProtobuf.Nested TestProtoImport.WithNesting_Nested)+ withNestingNestedMessage1)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 100)- (HsProtobuf.Nested withNestingNestedMessage2))])+ (Hs.coerce @(Hs.Maybe TestProtoImport.WithNesting_Nested)+ @(HsProtobuf.Nested TestProtoImport.WithNesting_Nested)+ withNestingNestedMessage2))]) decodeMessage _ = (Hs.pure WithNesting) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce+ @(_ (HsProtobuf.Nested TestProtoImport.WithNesting_Nested))+ @(_ (Hs.Maybe TestProtoImport.WithNesting_Nested)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.nested) <*>+ (Hs.coerce+ @(_ (HsProtobuf.Nested TestProtoImport.WithNesting_Nested))+ @(_ (Hs.Maybe TestProtoImport.WithNesting_Nested)) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 100))) dotProto _@@ -61,12 +77,12 @@ (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "Nested"))) (HsProtobuf.Single "nestedMessage1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 100) (HsProtobuf.Prim (HsProtobuf.Named (HsProtobuf.Single "Nested"))) (HsProtobuf.Single "nestedMessage2") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNesting where toJSONPB (WithNesting f1 f100)@@ -113,18 +129,16 @@ ("nestedMessage2", withNestingNestedMessage2)]}}) -instance HsDhallPb.Interpret WithNesting- -instance HsDhallPb.Inject WithNesting- data WithNesting_Nested = WithNesting_Nested{withNesting_NestedNestedField1 :: Hs.Int32, withNesting_NestedNestedField2 :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithNesting_Nested where nameOf _ = (Hs.fromString "WithNesting_Nested") +instance HsProtobuf.HasDefault WithNesting_Nested+ instance HsProtobuf.Message WithNesting_Nested where encodeMessage _ WithNesting_Nested{withNesting_NestedNestedField1 =@@ -147,12 +161,12 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedField1") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "nestedField2") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB WithNesting_Nested where toJSONPB (WithNesting_Nested f1 f2)@@ -196,7 +210,3 @@ withNesting_NestedNestedField1), ("nestedField2", withNesting_NestedNestedField2)]}})- -instance HsDhallPb.Interpret WithNesting_Nested- -instance HsDhallPb.Inject WithNesting_Nested
gen/TestProtoOneof.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-}@@ -9,33 +11,39 @@ -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module TestProtoOneof where import qualified Prelude as Hs-import qualified Proto3.Suite.DhallPB as HsDhallPb-import qualified Proto3.Suite.DotProto as HsProtobuf-import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Suite.Class as HsProtobuf+import qualified Proto3.Suite.DotProto as HsProtobuf import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:))+import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf-import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.Applicative as Hs+import Control.Applicative ((<*>), (<|>), (<$>))+import qualified Control.DeepSeq as Hs import qualified Control.Monad as Hs-import qualified Data.Text.Lazy as Hs (Text) import qualified Data.ByteString as Hs+import qualified Data.Coerce as Hs+import qualified Data.Int as Hs (Int16, Int32, Int64)+import qualified Data.List.NonEmpty as Hs (NonEmpty(..))+import qualified Data.Map as Hs (Map, mapKeysMonotonic)+import qualified Data.Proxy as Proxy import qualified Data.String as Hs (fromString)+import qualified Data.Text.Lazy as Hs (Text) import qualified Data.Vector as Hs (Vector)-import qualified Data.Int as Hs (Int16, Int32, Int64) import qualified Data.Word as Hs (Word16, Word32, Word64)-import qualified Data.Proxy as Proxy-import qualified GHC.Generics as Hs import qualified GHC.Enum as Hs+import qualified GHC.Generics as Hs+import qualified Unsafe.Coerce as Hs import qualified TestProtoOneofImport data DummyMsg = DummyMsg{dummyMsgDummy :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named DummyMsg where nameOf _ = (Hs.fromString "DummyMsg") +instance HsProtobuf.HasDefault DummyMsg+ instance HsProtobuf.Message DummyMsg where encodeMessage _ DummyMsg{dummyMsgDummy = dummyMsgDummy} = (Hs.mconcat@@ -50,7 +58,7 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "dummy") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB DummyMsg where toJSONPB (DummyMsg f1) = (HsJSONPB.object ["dummy" .= f1])@@ -84,28 +92,31 @@ HsJSONPB.insOrdFromList [("dummy", dummyMsgDummy)]}}) -instance HsDhallPb.Interpret DummyMsg- -instance HsDhallPb.Inject DummyMsg- data DummyEnum = DummyEnumDUMMY0 | DummyEnumDUMMY1- deriving (Hs.Show, Hs.Bounded, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Generic, Hs.NFData) instance HsProtobuf.Named DummyEnum where nameOf _ = (Hs.fromString "DummyEnum") -instance Hs.Enum DummyEnum where- toEnum 0 = DummyEnumDUMMY0- toEnum 1 = DummyEnumDUMMY1- toEnum i = (Hs.toEnumError "DummyEnum" i (0 :: Hs.Int, 1))- fromEnum (DummyEnumDUMMY0) = 0- fromEnum (DummyEnumDUMMY1) = 1- succ (DummyEnumDUMMY0) = DummyEnumDUMMY1- succ _ = Hs.succError "DummyEnum"- pred (DummyEnumDUMMY1) = DummyEnumDUMMY0- pred _ = Hs.predError "DummyEnum"+instance HsProtobuf.HasDefault DummyEnum +instance Hs.Bounded DummyEnum where+ minBound = DummyEnumDUMMY0+ maxBound = DummyEnumDUMMY1+ +instance Hs.Ord DummyEnum where+ compare x y+ = Hs.compare (HsProtobuf.fromProtoEnum x)+ (HsProtobuf.fromProtoEnum y)+ +instance HsProtobuf.ProtoEnum DummyEnum where+ toProtoEnumMay 0 = Hs.Just DummyEnumDUMMY0+ toProtoEnumMay 1 = Hs.Just DummyEnumDUMMY1+ toProtoEnumMay _ = Hs.Nothing+ fromProtoEnum (DummyEnumDUMMY0) = 0+ fromProtoEnum (DummyEnumDUMMY1) = 1+ instance HsJSONPB.ToJSONPB DummyEnum where toJSONPB x _ = HsJSONPB.enumFieldString x toEncodingPB x _ = HsJSONPB.enumFieldEncoding x@@ -122,20 +133,18 @@ instance HsJSONPB.FromJSON DummyEnum where parseJSON = HsJSONPB.parseJSONPB -instance HsDhallPb.Interpret DummyEnum- -instance HsDhallPb.Inject DummyEnum- instance HsProtobuf.Finite DummyEnum data Something = Something{somethingValue :: Hs.Int64, somethingAnother :: Hs.Int32, somethingPickOne :: Hs.Maybe SomethingPickOne}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named Something where nameOf _ = (Hs.fromString "Something") +instance HsProtobuf.HasDefault Something+ instance HsProtobuf.Message Something where encodeMessage _ Something{somethingValue = somethingValue,@@ -143,9 +152,11 @@ somethingPickOne = somethingPickOne} = (Hs.mconcat [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Signed somethingValue)),+ (Hs.coerce @(Hs.Int64) @(HsProtobuf.Signed Hs.Int64)+ somethingValue)), (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.Signed somethingAnother)),+ (Hs.coerce @(Hs.Int32) @(HsProtobuf.Signed Hs.Int32)+ somethingAnother)), case somethingPickOne of Hs.Nothing -> Hs.mempty Hs.Just x@@ -158,20 +169,24 @@ (HsProtobuf.ForceEmit y)) SomethingPickOneDummyMsg1 y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 10)- (HsProtobuf.Nested (Hs.Just y)))+ (Hs.coerce @(Hs.Maybe TestProtoOneof.DummyMsg)+ @(HsProtobuf.Nested TestProtoOneof.DummyMsg)+ (Hs.Just y))) SomethingPickOneDummyMsg2 y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 11)- (HsProtobuf.Nested (Hs.Just y)))+ (Hs.coerce @(Hs.Maybe TestProtoOneof.DummyMsg)+ @(HsProtobuf.Nested TestProtoOneof.DummyMsg)+ (Hs.Just y))) SomethingPickOneDummyEnum y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 12) (HsProtobuf.ForceEmit y))]) decodeMessage _ = (Hs.pure Something) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed Hs.Int64)) @(_ Hs.Int64) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 1))) <*>- ((Hs.pure HsProtobuf.signed) <*>+ (Hs.coerce @(_ (HsProtobuf.Signed Hs.Int32)) @(_ Hs.Int32) (HsProtobuf.at HsProtobuf.decodeMessageField (HsProtobuf.FieldNumber 2))) <*>@@ -184,10 +199,14 @@ HsProtobuf.decodeMessageField), ((HsProtobuf.FieldNumber 10), (Hs.pure (Hs.fmap SomethingPickOneDummyMsg1)) <*>- ((Hs.pure HsProtobuf.nested) <*> HsProtobuf.decodeMessageField)),+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoOneof.DummyMsg))+ @(_ (Hs.Maybe TestProtoOneof.DummyMsg))+ HsProtobuf.decodeMessageField)), ((HsProtobuf.FieldNumber 11), (Hs.pure (Hs.fmap SomethingPickOneDummyMsg2)) <*>- ((Hs.pure HsProtobuf.nested) <*> HsProtobuf.decodeMessageField)),+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoOneof.DummyMsg))+ @(_ (Hs.Maybe TestProtoOneof.DummyMsg))+ HsProtobuf.decodeMessageField)), ((HsProtobuf.FieldNumber 12), (Hs.pure (Hs.Just Hs.. SomethingPickOneDummyEnum)) <*> HsProtobuf.decodeMessageField)])@@ -196,12 +215,12 @@ (HsProtobuf.Prim HsProtobuf.SInt64) (HsProtobuf.Single "value") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2) (HsProtobuf.Prim HsProtobuf.SInt32) (HsProtobuf.Single "another") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB Something where toJSONPB (Something f1 f2 f4_or_f9_or_f10_or_f11_or_f12)@@ -299,17 +318,13 @@ ("another", somethingAnother), ("pickOne", somethingPickOne)]}}) -instance HsDhallPb.Interpret Something- -instance HsDhallPb.Inject Something- data SomethingPickOne = SomethingPickOneName Hs.Text | SomethingPickOneSomeid Hs.Int32 | SomethingPickOneDummyMsg1 TestProtoOneof.DummyMsg | SomethingPickOneDummyMsg2 TestProtoOneof.DummyMsg | SomethingPickOneDummyEnum (HsProtobuf.Enumerated TestProtoOneof.DummyEnum)- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named SomethingPickOne where nameOf _ = (Hs.fromString "SomethingPickOne")@@ -353,18 +368,16 @@ HsJSONPB._schemaMinProperties = Hs.Just 1, HsJSONPB._schemaMaxProperties = Hs.Just 1}}) -instance HsDhallPb.Interpret SomethingPickOne- -instance HsDhallPb.Inject SomethingPickOne- data OneofFirst = OneofFirst{oneofFirstFirst :: Hs.Maybe OneofFirstFirst, oneofFirstLast :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named OneofFirst where nameOf _ = (Hs.fromString "OneofFirst") +instance HsProtobuf.HasDefault OneofFirst+ instance HsProtobuf.Message OneofFirst where encodeMessage _ OneofFirst{oneofFirstFirst = oneofFirstFirst,@@ -399,7 +412,7 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "last") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB OneofFirst where toJSONPB (OneofFirst f1_or_f2 f3)@@ -473,13 +486,9 @@ [("first", oneofFirstFirst), ("last", oneofFirstLast)]}}) -instance HsDhallPb.Interpret OneofFirst- -instance HsDhallPb.Inject OneofFirst- data OneofFirstFirst = OneofFirstFirstChoice1 Hs.Text | OneofFirstFirstChoice2 Hs.Text- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named OneofFirstFirst where nameOf _ = (Hs.fromString "OneofFirstFirst")@@ -508,18 +517,16 @@ HsJSONPB._schemaMinProperties = Hs.Just 1, HsJSONPB._schemaMaxProperties = Hs.Just 1}}) -instance HsDhallPb.Interpret OneofFirstFirst- -instance HsDhallPb.Inject OneofFirstFirst- data OneofMiddle = OneofMiddle{oneofMiddleFirst :: Hs.Int32, oneofMiddleMiddle :: Hs.Maybe OneofMiddleMiddle, oneofMiddleLast :: Hs.Int32}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named OneofMiddle where nameOf _ = (Hs.fromString "OneofMiddle") +instance HsProtobuf.HasDefault OneofMiddle+ instance HsProtobuf.Message OneofMiddle where encodeMessage _ OneofMiddle{oneofMiddleFirst = oneofMiddleFirst,@@ -560,12 +567,12 @@ (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "first") []- Hs.Nothing),+ ""), (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 4) (HsProtobuf.Prim HsProtobuf.Int32) (HsProtobuf.Single "last") []- Hs.Nothing)]+ "")] instance HsJSONPB.ToJSONPB OneofMiddle where toJSONPB (OneofMiddle f1 f2_or_f3 f4)@@ -651,13 +658,9 @@ ("middle", oneofMiddleMiddle), ("last", oneofMiddleLast)]}}) -instance HsDhallPb.Interpret OneofMiddle- -instance HsDhallPb.Inject OneofMiddle- data OneofMiddleMiddle = OneofMiddleMiddleChoice1 Hs.Text | OneofMiddleMiddleChoice2 Hs.Text- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named OneofMiddleMiddle where nameOf _ = (Hs.fromString "OneofMiddleMiddle")@@ -686,17 +689,15 @@ HsJSONPB._schemaMinProperties = Hs.Just 1, HsJSONPB._schemaMaxProperties = Hs.Just 1}}) -instance HsDhallPb.Interpret OneofMiddleMiddle- -instance HsDhallPb.Inject OneofMiddleMiddle- data WithImported = WithImported{withImportedPickOne :: Hs.Maybe WithImportedPickOne}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithImported where nameOf _ = (Hs.fromString "WithImported") +instance HsProtobuf.HasDefault WithImported+ instance HsProtobuf.Message WithImported where encodeMessage _ WithImported{withImportedPickOne = withImportedPickOne}@@ -707,19 +708,27 @@ -> case x of WithImportedPickOneDummyMsg1 y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)- (HsProtobuf.Nested (Hs.Just y)))+ (Hs.coerce @(Hs.Maybe TestProtoOneof.DummyMsg)+ @(HsProtobuf.Nested TestProtoOneof.DummyMsg)+ (Hs.Just y))) WithImportedPickOneWithOneof y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.Nested (Hs.Just y)))])+ (Hs.coerce @(Hs.Maybe TestProtoOneofImport.WithOneof)+ @(HsProtobuf.Nested TestProtoOneofImport.WithOneof)+ (Hs.Just y)))]) decodeMessage _ = (Hs.pure WithImported) <*> (HsProtobuf.oneof Hs.Nothing [((HsProtobuf.FieldNumber 1), (Hs.pure (Hs.fmap WithImportedPickOneDummyMsg1)) <*>- ((Hs.pure HsProtobuf.nested) <*> HsProtobuf.decodeMessageField)),+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoOneof.DummyMsg))+ @(_ (Hs.Maybe TestProtoOneof.DummyMsg))+ HsProtobuf.decodeMessageField)), ((HsProtobuf.FieldNumber 2), (Hs.pure (Hs.fmap WithImportedPickOneWithOneof)) <*>- ((Hs.pure HsProtobuf.nested) <*> HsProtobuf.decodeMessageField))])+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoOneofImport.WithOneof))+ @(_ (Hs.Maybe TestProtoOneofImport.WithOneof))+ HsProtobuf.decodeMessageField))]) dotProto _ = [] instance HsJSONPB.ToJSONPB WithImported where@@ -794,13 +803,9 @@ HsJSONPB.insOrdFromList [("pickOne", withImportedPickOne)]}}) -instance HsDhallPb.Interpret WithImported- -instance HsDhallPb.Inject WithImported- data WithImportedPickOne = WithImportedPickOneDummyMsg1 TestProtoOneof.DummyMsg | WithImportedPickOneWithOneof TestProtoOneofImport.WithOneof- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithImportedPickOne where nameOf _ = (Hs.fromString "WithImportedPickOne")@@ -829,7 +834,3 @@ withImportedPickOneWithOneof)], HsJSONPB._schemaMinProperties = Hs.Just 1, HsJSONPB._schemaMaxProperties = Hs.Just 1}})- -instance HsDhallPb.Interpret WithImportedPickOne- -instance HsDhallPb.Inject WithImportedPickOne
gen/TestProtoOneofImport.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-}@@ -9,33 +11,112 @@ -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT! module TestProtoOneofImport where import qualified Prelude as Hs-import qualified Proto3.Suite.DhallPB as HsDhallPb-import qualified Proto3.Suite.DotProto as HsProtobuf-import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Suite.Class as HsProtobuf+import qualified Proto3.Suite.DotProto as HsProtobuf import qualified Proto3.Suite.JSONPB as HsJSONPB import Proto3.Suite.JSONPB ((.=), (.:))+import qualified Proto3.Suite.Types as HsProtobuf import qualified Proto3.Wire as HsProtobuf-import Control.Applicative ((<*>), (<|>), (<$>)) import qualified Control.Applicative as Hs+import Control.Applicative ((<*>), (<|>), (<$>))+import qualified Control.DeepSeq as Hs import qualified Control.Monad as Hs-import qualified Data.Text.Lazy as Hs (Text) import qualified Data.ByteString as Hs+import qualified Data.Coerce as Hs+import qualified Data.Int as Hs (Int16, Int32, Int64)+import qualified Data.List.NonEmpty as Hs (NonEmpty(..))+import qualified Data.Map as Hs (Map, mapKeysMonotonic)+import qualified Data.Proxy as Proxy import qualified Data.String as Hs (fromString)+import qualified Data.Text.Lazy as Hs (Text) import qualified Data.Vector as Hs (Vector)-import qualified Data.Int as Hs (Int16, Int32, Int64) import qualified Data.Word as Hs (Word16, Word32, Word64)-import qualified Data.Proxy as Proxy-import qualified GHC.Generics as Hs import qualified GHC.Enum as Hs+import qualified GHC.Generics as Hs+import qualified Unsafe.Coerce as Hs +data AMessage = AMessage{amessageX :: Hs.Text,+ amessageY :: Hs.Int32}+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData)+ +instance HsProtobuf.Named AMessage where+ nameOf _ = (Hs.fromString "AMessage")+ +instance HsProtobuf.HasDefault AMessage+ +instance HsProtobuf.Message AMessage where+ encodeMessage _+ AMessage{amessageX = amessageX, amessageY = amessageY}+ = (Hs.mconcat+ [(HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 1)+ amessageX),+ (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)+ amessageY)])+ decodeMessage _+ = (Hs.pure AMessage) <*>+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 1))+ <*>+ (HsProtobuf.at HsProtobuf.decodeMessageField+ (HsProtobuf.FieldNumber 2))+ dotProto _+ = [(HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 1)+ (HsProtobuf.Prim HsProtobuf.String)+ (HsProtobuf.Single "x")+ []+ ""),+ (HsProtobuf.DotProtoField (HsProtobuf.FieldNumber 2)+ (HsProtobuf.Prim HsProtobuf.Int32)+ (HsProtobuf.Single "y")+ []+ "")]+ +instance HsJSONPB.ToJSONPB AMessage where+ toJSONPB (AMessage f1 f2)+ = (HsJSONPB.object ["x" .= f1, "y" .= f2])+ toEncodingPB (AMessage f1 f2)+ = (HsJSONPB.pairs ["x" .= f1, "y" .= f2])+ +instance HsJSONPB.FromJSONPB AMessage where+ parseJSONPB+ = (HsJSONPB.withObject "AMessage"+ (\ obj -> (Hs.pure AMessage) <*> obj .: "x" <*> obj .: "y"))+ +instance HsJSONPB.ToJSON AMessage where+ toJSON = HsJSONPB.toAesonValue+ toEncoding = HsJSONPB.toAesonEncoding+ +instance HsJSONPB.FromJSON AMessage where+ parseJSON = HsJSONPB.parseJSONPB+ +instance HsJSONPB.ToSchema AMessage where+ declareNamedSchema _+ = do let declare_x = HsJSONPB.declareSchemaRef+ amessageX <- declare_x Proxy.Proxy+ let declare_y = HsJSONPB.declareSchemaRef+ amessageY <- declare_y Proxy.Proxy+ let _ = Hs.pure AMessage <*> HsJSONPB.asProxy declare_x <*>+ HsJSONPB.asProxy declare_y+ Hs.return+ (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName =+ Hs.Just "AMessage",+ HsJSONPB._namedSchemaSchema =+ Hs.mempty{HsJSONPB._schemaParamSchema =+ Hs.mempty{HsJSONPB._paramSchemaType =+ HsJSONPB.SwaggerObject},+ HsJSONPB._schemaProperties =+ HsJSONPB.insOrdFromList+ [("x", amessageX), ("y", amessageY)]}})+ data WithOneof = WithOneof{withOneofPickOne :: Hs.Maybe WithOneofPickOne}- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithOneof where nameOf _ = (Hs.fromString "WithOneof") +instance HsProtobuf.HasDefault WithOneof+ instance HsProtobuf.Message WithOneof where encodeMessage _ WithOneof{withOneofPickOne = withOneofPickOne} = (Hs.mconcat@@ -48,7 +129,12 @@ (HsProtobuf.ForceEmit y)) WithOneofPickOneB y -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 2)- (HsProtobuf.ForceEmit y))])+ (HsProtobuf.ForceEmit y))+ WithOneofPickOneC y+ -> (HsProtobuf.encodeMessageField (HsProtobuf.FieldNumber 3)+ (Hs.coerce @(Hs.Maybe TestProtoOneofImport.AMessage)+ @(HsProtobuf.Nested TestProtoOneofImport.AMessage)+ (Hs.Just y)))]) decodeMessage _ = (Hs.pure WithOneof) <*> (HsProtobuf.oneof Hs.Nothing@@ -57,16 +143,22 @@ HsProtobuf.decodeMessageField), ((HsProtobuf.FieldNumber 2), (Hs.pure (Hs.Just Hs.. WithOneofPickOneB)) <*>- HsProtobuf.decodeMessageField)])+ HsProtobuf.decodeMessageField),+ ((HsProtobuf.FieldNumber 3),+ (Hs.pure (Hs.fmap WithOneofPickOneC)) <*>+ (Hs.coerce @(_ (HsProtobuf.Nested TestProtoOneofImport.AMessage))+ @(_ (Hs.Maybe TestProtoOneofImport.AMessage))+ HsProtobuf.decodeMessageField))]) dotProto _ = [] instance HsJSONPB.ToJSONPB WithOneof where- toJSONPB (WithOneof f1_or_f2)+ toJSONPB (WithOneof f1_or_f2_or_f3) = (HsJSONPB.object [(let encodePickOne- = (case f1_or_f2 of+ = (case f1_or_f2_or_f3 of Hs.Just (WithOneofPickOneA f1) -> (HsJSONPB.pair "a" f1) Hs.Just (WithOneofPickOneB f2) -> (HsJSONPB.pair "b" f2)+ Hs.Just (WithOneofPickOneC f3) -> (HsJSONPB.pair "c" f3) Hs.Nothing -> Hs.mempty) in \ options ->@@ -74,12 +166,13 @@ ("pickOne" .= (HsJSONPB.objectOrNull [encodePickOne] options)) options else encodePickOne options)])- toEncodingPB (WithOneof f1_or_f2)+ toEncodingPB (WithOneof f1_or_f2_or_f3) = (HsJSONPB.pairs [(let encodePickOne- = (case f1_or_f2 of+ = (case f1_or_f2_or_f3 of Hs.Just (WithOneofPickOneA f1) -> (HsJSONPB.pair "a" f1) Hs.Just (WithOneofPickOneB f2) -> (HsJSONPB.pair "b" f2)+ Hs.Just (WithOneofPickOneC f3) -> (HsJSONPB.pair "c" f3) Hs.Nothing -> Hs.mempty) in \ options ->@@ -99,6 +192,8 @@ (HsJSONPB.parseField parseObj "a"), Hs.Just Hs.. WithOneofPickOneB <$> (HsJSONPB.parseField parseObj "b"),+ Hs.Just Hs.. WithOneofPickOneC <$>+ (HsJSONPB.parseField parseObj "c"), Hs.pure Hs.Nothing] in ((obj .: "pickOne") Hs.>>=@@ -128,13 +223,10 @@ HsJSONPB.insOrdFromList [("pickOne", withOneofPickOne)]}}) -instance HsDhallPb.Interpret WithOneof- -instance HsDhallPb.Inject WithOneof- data WithOneofPickOne = WithOneofPickOneA Hs.Text | WithOneofPickOneB Hs.Int32- deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic)+ | WithOneofPickOneC TestProtoOneofImport.AMessage+ deriving (Hs.Show, Hs.Eq, Hs.Ord, Hs.Generic, Hs.NFData) instance HsProtobuf.Named WithOneofPickOne where nameOf _ = (Hs.fromString "WithOneofPickOne")@@ -147,6 +239,9 @@ let declare_b = HsJSONPB.declareSchemaRef withOneofPickOneB <- declare_b Proxy.Proxy let _ = Hs.pure WithOneofPickOneB <*> HsJSONPB.asProxy declare_b+ let declare_c = HsJSONPB.declareSchemaRef+ withOneofPickOneC <- declare_c Proxy.Proxy+ let _ = Hs.pure WithOneofPickOneC <*> HsJSONPB.asProxy declare_c Hs.return (HsJSONPB.NamedSchema{HsJSONPB._namedSchemaName = Hs.Just "WithOneofPickOne",@@ -157,10 +252,7 @@ HsJSONPB._schemaProperties = HsJSONPB.insOrdFromList [("a", withOneofPickOneA),- ("b", withOneofPickOneB)],+ ("b", withOneofPickOneB),+ ("c", withOneofPickOneC)], HsJSONPB._schemaMinProperties = Hs.Just 1, HsJSONPB._schemaMaxProperties = Hs.Just 1}})- -instance HsDhallPb.Interpret WithOneofPickOne- -instance HsDhallPb.Inject WithOneofPickOne
proto3-suite.cabal view
@@ -1,5 +1,5 @@ name: proto3-suite-version: 0.3.0.0+version: 0.4.0.0 synopsis: A low level library for writing out data in the Protocol Buffers wire format license: Apache-2.0 author: Awake Security@@ -27,6 +27,7 @@ Proto3.Suite.DotProto Proto3.Suite.DotProto.Generate Proto3.Suite.DotProto.AST+ Proto3.Suite.DotProto.AST.Lens Proto3.Suite.DotProto.Parsing Proto3.Suite.DotProto.Rendering Proto3.Suite.JSONPB@@ -59,12 +60,12 @@ parsers >= 0.12 && <0.13, pretty ==1.1.*, pretty-show >= 1.6.12 && < 2.0,- proto3-wire == 1.0.*,- QuickCheck >=2.10 && <2.13,+ proto3-wire == 1.1.*,+ QuickCheck >=2.10 && <2.14, quickcheck-instances < 0.4, safe ==0.3.*, semigroups ==0.18.*,- swagger2 >=2.1.6 && <2.4,+ swagger2 >=2.1.6 && <2.5, system-filepath, text >= 0.2 && <1.3, transformers >=0.4 && <0.6,@@ -94,7 +95,7 @@ hs-source-dirs: tests gen default-language: Haskell2010 build-depends: base >=4.8 && <5.0,- QuickCheck >=2.10 && <2.13,+ QuickCheck >=2.10 && <2.14, aeson >= 1.1.1.0 && < 1.5, attoparsec >= 0.13.0.1, base >=4.8 && <5.0,@@ -102,10 +103,13 @@ bytestring >=0.10.6.0 && <0.11.0, cereal >= 0.5.1 && <0.6, containers >=0.5 && < 0.7,+ deepseq ==1.4.*, doctest,+ generic-arbitrary,+ mtl ==2.2.*, pretty-show >= 1.6.12 && < 2.0, proto3-suite,- proto3-wire == 1.0.*,+ proto3-wire == 1.1.*, semigroups ==0.18.*, swagger2, tasty >= 0.11 && <1.2,@@ -122,7 +126,7 @@ hs-source-dirs: tools/compile-proto-file default-language: Haskell2010 build-depends: base >=4.8 && <5.0- , optparse-generic+ , optparse-applicative , proto3-suite , system-filepath , text@@ -135,9 +139,10 @@ default-language: Haskell2010 build-depends: base >=4.8 && <5.0 , containers >=0.5 && <0.7+ , mtl ==2.2.* , optparse-generic , proto3-suite- , proto3-wire == 1.0.*+ , proto3-wire == 1.1.* , range-set-list >=0.1.2 && <0.2 , system-filepath , turtle
src/Proto3/Suite/Class.hs view
@@ -97,6 +97,7 @@ import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Lazy as BL import Data.Coerce (coerce)+import qualified Data.Foldable as Foldable import Data.Functor (($>)) import Data.Int (Int32, Int64) import qualified Data.Map as M@@ -115,20 +116,19 @@ import Proto3.Suite.DotProto as DotProto import Proto3.Suite.Types as Wire import Proto3.Wire+import Proto3.Wire.Class (ProtoEnum(..)) import Proto3.Wire.Decode (ParseError, Parser (..), RawField, RawMessage, RawPrimitive, runParser) import qualified Proto3.Wire.Decode as Decode import qualified Proto3.Wire.Encode as Encode-import Safe (toEnumMay) -- | A class for types with default values per the protocol buffers spec. class HasDefault a where -- | The default value for this type. def :: a - -- | Numeric types default to zero- default def :: Num a => a- def = 0+ default def :: (Generic a, GenericHasDefault (Rep a)) => a+ def = to (genericDef @(Rep a)) isDefault :: a -> Bool @@ -145,19 +145,29 @@ | isDefault p = mempty | otherwise = f p -instance HasDefault Int32-instance HasDefault Int64-instance HasDefault Word32-instance HasDefault Word64-instance HasDefault (Signed Int32)-instance HasDefault (Signed Int64)-instance HasDefault (Fixed Word32)-instance HasDefault (Fixed Word64)-instance HasDefault (Signed (Fixed Int32))-instance HasDefault (Signed (Fixed Int64))-instance HasDefault Float-instance HasDefault Double+-- -- | Numeric types default to zero+-- instance Num a => HasDefault a where def = 0 +instance HasDefault Int where def = 0+instance HasDefault Integer where def = 0++instance HasDefault Int32 where def = 0+instance HasDefault Int64 where def = 0+instance HasDefault Word32 where def = 0+instance HasDefault Word64 where def = 0+instance HasDefault (Signed Int32) where def = 0+instance HasDefault (Signed Int64) where def = 0+-- | Used in generated records to represent @sfixed32@+instance HasDefault (Fixed Int32) where def = 0+-- | Used in generated records to represent @sfixed64@+instance HasDefault (Fixed Int64) where def = 0+instance HasDefault (Fixed Word32) where def = 0+instance HasDefault (Fixed Word64) where def = 0+instance HasDefault (Signed (Fixed Int32)) where def = 0+instance HasDefault (Signed (Fixed Int64)) where def = 0+instance HasDefault Float where def = 0+instance HasDefault Double where def = 0+ instance HasDefault Bool where def = False @@ -173,12 +183,9 @@ instance HasDefault BL.ByteString where def = mempty -instance (Bounded e, Enum e) => HasDefault (Enumerated e) where- def =- case toEnumMay 0 of- Nothing -> Enumerated (Left 0)- Just x -> Enumerated (Right x)- isDefault = (== 0) . either id fromEnum . enumerated+instance ProtoEnum e => HasDefault (Enumerated e) where+ def = Enumerated $ maybe (Left 0) Right (toProtoEnumMay 0)+ isDefault = (== 0) . either id fromProtoEnum . enumerated instance HasDefault (UnpackedVec a) where def = mempty@@ -215,20 +222,22 @@ def = M.empty isDefault = M.null --- TODO: Determine if we have a reason for rendering fixed32/sfixed as Fixed--- Word32/Int32 in generated datatypes; for other field types, we omit the--- newtype wrappers in the type signature but un/wrap them as needed in the--- encode/decodeMessage implementations. These Fixed wrappers can probably be--- removed and the type interface would be more consistent with other types, but--- until that occurs, the following two instances are needed.------ Tracked by https://github.com/awakesecurity/proto3-suite/issues/30.---- | Used in generated records to represent @sfixed32@-instance HasDefault (Fixed Int32)---- | Used in generated records to represent @sfixed64@-instance HasDefault (Fixed Int64)+class GenericHasDefault (f :: * -> *) where+ genericDef :: f x+instance HasDefault f => GenericHasDefault (K1 i f) where+ genericDef = K1 (def @f)+instance (GenericHasDefault f, GenericHasDefault g) => GenericHasDefault (f :*: g) where+ genericDef = genericDef @f :*: genericDef @g+instance (GenericHasDefault f, GenericHasDefault g) => GenericHasDefault (f :+: g) where+ genericDef = L1 (genericDef @f)+instance GenericHasDefault U1 where+ genericDef = U1 -- unit constructor+instance (Constructor i, GenericHasDefault f) => GenericHasDefault (C1 i f) where+ genericDef = M1 (genericDef @f)+instance (Datatype i, GenericHasDefault f) => GenericHasDefault (D1 i f) where+ genericDef = M1 (genericDef @f)+instance (Selector i, GenericHasDefault f) => GenericHasDefault (S1 i f) where+ genericDef = M1 (genericDef @f) -- | This class captures those types whose names need to appear in .proto files. --@@ -251,46 +260,44 @@ -- -- This class can be derived whenever a sum type is an instance of 'Generic', -- and only consists of zero-argument constructors. The derived instance should--- be compatible with derived `Enum` instances, in the sense that+-- be compatible with `ProtoEnum` instances, in the sense that ----- > map (toEnum . fst) enumerate+-- > map (fromJust . toProtoEnumMay . snd) enumerate -- -- should enumerate all values of the type without runtime errors.-class Enum a => Finite a where+class ProtoEnum a => Finite a where -- | Enumerate values of a finite type, along with names of constructors.- enumerate :: IsString string => Proxy# a -> [(string, Int)]+ enumerate :: IsString string => Proxy# a -> [(string, Int32)] - default enumerate :: (IsString string, GenericFinite (Rep a))- => Proxy# a -> [(string, Int)]- enumerate _ = snd (genericEnumerate (proxy# :: Proxy# (Rep a)) 0)+ default enumerate ::+ (IsString string, Generic a, GenericFinite (Rep a)) =>+ Proxy# a -> [(string, Int32)]+ enumerate _ =+ fmap (fromProtoEnum . (to :: Rep a p -> a)) <$> genericEnumerate -- | Generate metadata for an enum type. enum :: (Finite e, Named e) => Proxy# e -> DotProtoDefinition-enum pr = DotProtoEnum (Single $ nameOf pr) (map enumField $ enumerate pr)+enum pr = DotProtoEnum "" (Single $ nameOf pr) (map enumField $ enumerate pr) where enumField (name, value) = DotProtoEnumField (Single name) value [] class GenericFinite (f :: * -> *) where- genericEnumerate :: IsString string => Proxy# f -> Int -> (Int, [(string, Int)])+ genericEnumerate :: IsString string => [(string, f p)] instance ( GenericFinite f , GenericFinite g ) => GenericFinite (f :+: g) where- genericEnumerate _ i =- let (j, e1) = genericEnumerate (proxy# :: Proxy# f) i- (k, e2) = genericEnumerate (proxy# :: Proxy# g) j- in (k, e1 <> e2)+ genericEnumerate =+ (fmap L1 <$> genericEnumerate) <>+ (fmap R1 <$> genericEnumerate) -instance Constructor c => GenericFinite (M1 C c f) where- genericEnumerate _ i = (i + 1, [ (fromString name, i) ])+instance Constructor c => GenericFinite (M1 C c U1) where+ genericEnumerate = [ (fromString name, M1 U1) ] where name = conName (undefined :: M1 C c f ()) instance GenericFinite f => GenericFinite (M1 D t f) where- genericEnumerate _ = genericEnumerate (proxy# :: Proxy# f)--instance GenericFinite f => GenericFinite (M1 S t f) where- genericEnumerate _ = genericEnumerate (proxy# :: Proxy# f)+ genericEnumerate = fmap M1 <$> genericEnumerate -- | This class captures those types which correspond to primitives in -- the protocol buffers specification.@@ -373,7 +380,7 @@ primType _ = SFixed64 instance Primitive Bool where- encodePrimitive = Encode.enum+ encodePrimitive = Encode.bool decodePrimitive = Decode.bool primType _ = Bool @@ -407,11 +414,12 @@ decodePrimitive = Decode.lazyByteString primType _ = Bytes -instance forall e. (Bounded e, Named e, Enum e) => Primitive (Enumerated e) where- encodePrimitive num = Encode.enum num . enumify . enumerated- where enumify (Left i) = i- enumify (Right x) = fromEnum x- decodePrimitive = coerce @(Parser RawPrimitive (Either Int e)) @(Parser RawPrimitive (Enumerated e)) Decode.enum+instance forall e. (Named e, ProtoEnum e) => Primitive (Enumerated e) where+ encodePrimitive num = either (Encode.int32 num) (Encode.enum num) . enumerated+ decodePrimitive = coerce+ @(Parser RawPrimitive (Either Int32 e))+ @(Parser RawPrimitive (Enumerated e))+ Decode.enum primType _ = Named (Single (nameOf (proxy# :: Proxy# e))) instance (Primitive a) => Primitive (ForceEmit a) where@@ -448,7 +456,7 @@ , dotProtoFieldType = ty , dotProtoFieldName = Anonymous , dotProtoFieldOptions = packingOption- , dotProtoFieldComment = Nothing+ , dotProtoFieldComment = "" } where packingOption = maybe [] (toDotProtoOption . isPacked) packing@@ -475,7 +483,7 @@ instance MessageField TL.Text instance MessageField B.ByteString instance MessageField BL.ByteString-instance (Bounded e, Named e, Enum e) => MessageField (Enumerated e)+instance (Named e, ProtoEnum e) => MessageField (Enumerated e) instance (Ord k, Primitive k, MessageField k, Primitive v, MessageField v) => MessageField (M.Map k v) where encodeMessageField num = foldMap (Encode.embedded num . encodeMessage (fieldNumber 1)) . M.toList@@ -484,7 +492,7 @@ -- -- > When parsing from the wire or when merging, if there are duplicate map -- > keys the last key seen is used.- decodeMessageField = M.fromList . fromList+ decodeMessageField = M.fromList . Foldable.toList <$> repeated (Decode.embedded' (decodeMessage (fieldNumber 1))) protoType _ = messageField (Map (primType (proxy# :: Proxy# k)) (primType (proxy# :: Proxy# v))) Nothing @@ -495,7 +503,7 @@ -- -- > When parsing from the wire or when merging, if there are duplicate map -- > keys the last key seen is used.- decodeMessageField = M.fromList . fromList+ decodeMessageField = M.fromList . Foldable.toList <$> repeated (Decode.embedded' (decodeMessage (fieldNumber 1))) protoType _ = messageField (Map (primType (proxy# :: Proxy# k)) (Named . Single $ nameOf (proxy# :: Proxy# v))) Nothing @@ -511,30 +519,32 @@ instance Primitive a => MessageField (UnpackedVec a) where encodeMessageField = foldMap . encodePrimitive- decodeMessageField = UnpackedVec . fromList <$> repeated decodePrimitive+ decodeMessageField =+ UnpackedVec . fromList . Foldable.toList <$> repeated decodePrimitive protoType _ = messageField (Repeated $ primType (proxy# :: Proxy# a)) (Just DotProto.UnpackedField) instance forall a. (Named a, Message a) => MessageField (NestedVec a) where encodeMessageField fn = foldMap (Encode.embedded fn . encodeMessage (fieldNumber 1)) . coerce @(NestedVec a) @(Vector a)- decodeMessageField = fmap (coerce @(Vector a) @(NestedVec a) . fromList)- (repeated (Decode.embedded' oneMsg))+ decodeMessageField =+ fmap (coerce @(Vector a) @(NestedVec a) . fromList . Foldable.toList)+ (repeated (Decode.embedded' oneMsg)) where oneMsg :: Parser RawMessage a oneMsg = decodeMessage (fieldNumber 1) protoType _ = messageField (NestedRepeated . Named . Single $ nameOf (proxy# :: Proxy# a)) Nothing -instance (Bounded e, Enum e, Named e) => MessageField (PackedVec (Enumerated e)) where+instance (Named e, ProtoEnum e) => MessageField (PackedVec (Enumerated e)) where encodeMessageField fn = omittingDefault (Encode.packedVarints fn) . foldMap omit where -- omit values which are outside the enum range omit :: Enumerated e -> PackedVec Word64- omit (Enumerated (Right e)) = pure . fromIntegral . fromEnum $ e+ omit (Enumerated (Right e)) = pure . fromIntegral . fromProtoEnum $ e omit _ = mempty decodeMessageField = decodePacked (foldMap retain <$> Decode.packedVarints @Word64) where -- retain only those values which are inside the enum range- retain = foldMap (pure . Enumerated. Right) . toEnumMay . fromIntegral+ retain = foldMap (pure . Enumerated . Right) . toProtoEnumMay . fromIntegral protoType _ = messageField (Repeated . Named . Single $ nameOf (proxy# :: Proxy# e)) (Just DotProto.PackedField) instance MessageField (PackedVec Bool) where@@ -613,7 +623,7 @@ @(Parser RawField (Commented comments e)) decodeMessageField protoType p = (protoType (lowerProxy1 p))- { dotProtoFieldComment = Just (symbolVal (lowerProxy2 p)) }+ { dotProtoFieldComment = symbolVal (lowerProxy2 p) } where lowerProxy1 :: forall f (a :: k). Proxy# (f a) -> Proxy# a lowerProxy1 _ = proxy#@@ -625,7 +635,7 @@ :: Parser RawPrimitive [a] -> Parser RawField (PackedVec a) decodePacked = Parser- . fmap (fmap pack)+ . fmap (fmap (pack . Foldable.toList)) . TR.traverse . runParser where@@ -658,7 +668,8 @@ -- | Generate metadata for a message type. message :: (Message a, Named a) => Proxy# a -> DotProtoDefinition-message proxy = DotProtoMessage (Single $ nameOf proxy)+message proxy = DotProtoMessage ""+ (Single $ nameOf proxy) (DotProtoMessageField <$> dotProto proxy) -- * Generic Instances
src/Proto3/Suite/DhallPB.hs view
@@ -28,7 +28,7 @@ instance Dhall.Interpret a => Dhall.Interpret (Enumerated a) -instance Dhall.Interpret a => Dhall.Interpret (Either Int a)+instance Dhall.Interpret a => Dhall.Interpret (Either Int32 a) -------------------------------------------------------------------------------- -- Interpret the strict and lazy ByteString types@@ -114,7 +114,7 @@ instance Dhall.Inject a => Dhall.Inject (Enumerated a) -instance Dhall.Inject a => Dhall.Inject (Either Int a)+instance Dhall.Inject a => Dhall.Inject (Either Int32 a) -------------------------------------------------------------------------------- -- Inject integer scalar types
src/Proto3/Suite/DotProto.hs view
@@ -3,3 +3,5 @@ import Proto3.Suite.DotProto.AST as M import Proto3.Suite.DotProto.Parsing as M import Proto3.Suite.DotProto.Rendering as M+-- exported for testing+import Proto3.Suite.DotProto.Internal as M (fieldLikeName, prefixedEnumFieldName, typeLikeName)
src/Proto3/Suite/DotProto/AST.hs view
@@ -1,6 +1,7 @@ -- | Fairly straightforward AST encoding of the .proto grammar {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE RecordWildCards #-} module Proto3.Suite.DotProto.AST@@ -19,17 +20,22 @@ , DotProtoValue(..) , DotProtoPrimType(..) , Packing(..)- , Path(..)+ , Path(..), fakePath , DotProtoType(..) , DotProtoEnumValue , DotProtoEnumPart(..) , Streaming(..) , DotProtoServicePart(..)+ , RPCMethod(..) , DotProtoMessagePart(..) , DotProtoField(..) , DotProtoReservedField(..) ) where +import Control.Applicative+import Control.Monad+import Data.Int (Int32)+import qualified Data.List.NonEmpty as NE import Data.String (IsString) import qualified Filesystem.Path.CurrentOS as FP import Numeric.Natural@@ -63,8 +69,12 @@ instance Show PackageName where show = show . getPackageName -newtype Path = Path { components :: [String] } deriving (Show, Eq, Ord)+newtype Path = Path { components :: NE.NonEmpty String } deriving (Show, Eq, Ord) +-- Used for testing+fakePath :: Path+fakePath = Path ("fakePath" NE.:| [])+ data DotProtoIdentifier = Single String | Dots Path@@ -127,23 +137,26 @@ -- | Top-level protocol definitions data DotProtoDefinition- = DotProtoMessage DotProtoIdentifier [DotProtoMessagePart]- | DotProtoEnum DotProtoIdentifier [DotProtoEnumPart]- | DotProtoService DotProtoIdentifier [DotProtoServicePart]+ = DotProtoMessage String DotProtoIdentifier [DotProtoMessagePart]+ | DotProtoEnum String DotProtoIdentifier [DotProtoEnumPart]+ | DotProtoService String DotProtoIdentifier [DotProtoServicePart] deriving (Show, Eq) + instance Arbitrary DotProtoDefinition where arbitrary = oneof [arbitraryMessage, arbitraryEnum] where arbitraryMessage = do+ comment <- pure mempty -- until parser supports comments identifier <- arbitrarySingleIdentifier parts <- smallListOf arbitrary- return (DotProtoMessage identifier parts)+ return (DotProtoMessage comment identifier parts) arbitraryEnum = do+ comment <- pure mempty -- until parser supports comments identifier <- arbitrarySingleIdentifier parts <- smallListOf arbitrary- return (DotProtoEnum identifier parts)+ return (DotProtoEnum comment identifier parts) -- | Tracks misc metadata about the AST data DotProtoMeta = DotProtoMeta@@ -158,7 +171,7 @@ } deriving (Show, Eq) instance Arbitrary DotProtoMeta where- arbitrary = pure . DotProtoMeta . Path $ []+ arbitrary = pure (DotProtoMeta fakePath) -- | This data structure represents a .proto file -- The actual source order of protobuf statements isn't meaningful so@@ -264,7 +277,7 @@ instance Arbitrary DotProtoType where arbitrary = oneof [fmap Prim arbitrary] -type DotProtoEnumValue = Int+type DotProtoEnumValue = Int32 data DotProtoEnumPart = DotProtoEnumField DotProtoIdentifier DotProtoEnumValue [DotProtoOption]@@ -293,45 +306,40 @@ instance Arbitrary Streaming where arbitrary = elements [Streaming, NonStreaming] --- [refactor] add named accessors to ServiceRPC--- break this into two types data DotProtoServicePart- = DotProtoServiceRPC DotProtoIdentifier- (DotProtoIdentifier, Streaming)- (DotProtoIdentifier, Streaming)- [DotProtoOption]+ = DotProtoServiceRPCMethod RPCMethod | DotProtoServiceOption DotProtoOption | DotProtoServiceEmpty deriving (Show, Eq) instance Arbitrary DotProtoServicePart where arbitrary = oneof- [ arbitraryServiceRPC- , arbitraryServiceOption+ [ DotProtoServiceRPCMethod <$> arbitrary+ , DotProtoServiceOption <$> arbitrary ]- where- arbitraryServiceRPC = do- identifier <- arbitrarySingleIdentifier- rpcClause0 <- arbitraryRPCClause- rpcClause1 <- arbitraryRPCClause- options <- smallListOf arbitrary- return (DotProtoServiceRPC identifier rpcClause0 rpcClause1 options)- where- arbitraryRPCClause = do- identifier <- arbitraryIdentifier- streaming <- arbitrary- return (identifier, streaming) - arbitraryServiceOption = do- option <- arbitrary- return (DotProtoServiceOption option)+data RPCMethod = RPCMethod+ { rpcMethodName :: DotProtoIdentifier+ , rpcMethodRequestType :: DotProtoIdentifier+ , rpcMethodRequestStreaming :: Streaming+ , rpcMethodResponseType :: DotProtoIdentifier+ , rpcMethodResponseStreaming :: Streaming+ , rpcMethodOptions :: [DotProtoOption]+ } deriving (Show, Eq) +instance Arbitrary RPCMethod where+ arbitrary = do+ rpcMethodName <- arbitrarySingleIdentifier+ rpcMethodRequestType <- arbitraryIdentifier+ rpcMethodRequestStreaming <- arbitrary+ rpcMethodResponseType <- arbitraryIdentifier+ rpcMethodResponseStreaming <- arbitrary+ rpcMethodOptions <- smallListOf arbitrary+ return RPCMethod{..}+ data DotProtoMessagePart = DotProtoMessageField DotProtoField- | DotProtoMessageOneOf- { dotProtoOneOfName :: DotProtoIdentifier- , dotProtoOneOfFields :: [DotProtoField]- }+ | DotProtoMessageOneOf DotProtoIdentifier [DotProtoField] | DotProtoMessageDefinition DotProtoDefinition | DotProtoMessageReserved [DotProtoReservedField] deriving (Show, Eq)@@ -349,9 +357,9 @@ return (DotProtoMessageField field) arbitraryOneOf = do- dotProtoOneOfName <- arbitrarySingleIdentifier- dotProtoOneOfFields <- smallListOf arbitrary- return (DotProtoMessageOneOf {..})+ name <- arbitrarySingleIdentifier+ fields <- smallListOf arbitrary+ return (DotProtoMessageOneOf name fields) arbitraryDefinition = do definition <- arbitrary@@ -369,7 +377,7 @@ , dotProtoFieldType :: DotProtoType , dotProtoFieldName :: DotProtoIdentifier , dotProtoFieldOptions :: [DotProtoOption]- , dotProtoFieldComment :: Maybe String+ , dotProtoFieldComment :: String } | DotProtoEmptyField deriving (Show, Eq)@@ -381,7 +389,7 @@ dotProtoFieldName <- arbitraryIdentifier dotProtoFieldOptions <- smallListOf arbitrary -- TODO: Generate random comments once the parser supports comments- dotProtoFieldComment <- pure Nothing+ dotProtoFieldComment <- pure mempty return (DotProtoField {..}) data DotProtoReservedField@@ -412,9 +420,10 @@ _arbitraryService :: Gen DotProtoDefinition _arbitraryService = do+ comment <- pure mempty -- until parser supports comments identifier <- arbitrarySingleIdentifier parts <- smallListOf arbitrary- return (DotProtoService identifier parts)+ return (DotProtoService comment identifier parts) arbitraryIdentifierName :: Gen String arbitraryIdentifierName = do@@ -429,7 +438,7 @@ arbitraryPathIdentifier = do name <- arbitraryIdentifierName names <- smallListOf1 arbitraryIdentifierName- pure . Dots . Path $ name:names+ pure . Dots . Path $ name NE.:| names arbitraryNestedIdentifier :: Gen DotProtoIdentifier arbitraryNestedIdentifier = do
+ src/Proto3/Suite/DotProto/AST/Lens.hs view
@@ -0,0 +1,9 @@+{-# LANGUAGE TemplateHaskell #-}+module Proto3.Suite.DotProto.AST.Lens where++import Control.Lens.TH+import Proto3.Suite.DotProto.AST++makePrisms ''DotProtoDefinition+makePrisms ''DotProtoMessagePart+
src/Proto3/Suite/DotProto/Generate.hs view
@@ -1,2150 +1,1818 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}--{-| This module provides functions to generate Haskell declarations for protobuf- messages--}--module Proto3.Suite.DotProto.Generate- ( CompileError(..)- , TypeContext-- , compileDotProtoFile- , compileDotProtoFileOrDie- , hsModuleForDotProto- , renderHsModuleForDotProto- , readDotProtoWithContext-- -- * Utilities- , isPackable-- -- * Exposed for unit-testing- , fieldLikeName- , prefixedEnumFieldName- , typeLikeName- ) where--import Control.Applicative-import Control.Arrow ((&&&))-import Control.Monad.Except-import Control.Lens (ix, over)-import Data.Bifunctor (first)-import Data.Char-import Data.Coerce-import Data.Either (partitionEithers)-import Data.List (find, intercalate, nub, sortBy,- stripPrefix)-import qualified Data.Map as M-import Data.Maybe (catMaybes, fromMaybe)-import Data.Monoid-import Data.Ord (comparing)-import qualified Data.Set as S-import Data.String (fromString)-import qualified Data.Text as T-import Filesystem.Path.CurrentOS ((</>), (<.>))-import qualified Filesystem.Path.CurrentOS as FP-import Language.Haskell.Pretty-import Language.Haskell.Syntax-import Language.Haskell.Parser (ParseResult(..), parseModule)-import qualified NeatInterpolation as Neat-import Prelude hiding (FilePath)-import Proto3.Suite.DotProto-import Proto3.Suite.DotProto.Rendering (Pretty(..))-import Proto3.Suite.DotProto.Internal-import Proto3.Wire.Types (FieldNumber (..))-import System.IO (writeFile, readFile)-import Text.Parsec (ParseError)-import Turtle (FilePath)-import qualified Turtle-import Turtle.Format ((%))-import qualified Turtle.Format as F---- * Public interface--data CompileError- = CircularImport FilePath- | CompileParseError ParseError- | InternalEmptyModulePath- | InternalError String- | InvalidMethodName DotProtoIdentifier- | InvalidTypeName String- | InvalidMapKeyType String- | NoPackageDeclaration- | NoSuchType DotProtoIdentifier- | Unimplemented String- deriving (Show, Eq)--#if !(MIN_VERSION_mtl(2,2,2))-liftEither :: MonadError e m => Either e a -> m a-liftEither x =- case x of- Left e -> throwError e- Right a -> return a-#endif---- | Generate a Haskell module corresponding to a @.proto@ file-compileDotProtoFile- :: [FilePath]- -- ^ Haskell modules containing instances used to override default generated- -- instances- -> FilePath- -- ^ Output directory- -> [FilePath]- -- ^ List of search paths- -> FilePath- -- ^ Path to @.proto@ file (relative to search path)- -> IO (Either CompileError ())-compileDotProtoFile- extraInstanceFiles- outputDirectory- searchPaths- dotProtoPath = runExceptT $ do- (dotProto, importTypeContext) <- do- ExceptT (readDotProtoWithContext searchPaths dotProtoPath)-- let DotProto { protoMeta } = dotProto- let DotProtoMeta { metaModulePath } = protoMeta- let Path { components } = metaModulePath-- when (null components) (throwError InternalEmptyModulePath)-- typeLikeComponents <- traverse typeLikeName components-- let relativePath = FP.concat (map fromString typeLikeComponents) <.> "hs"- let modulePath = outputDirectory </> relativePath-- Turtle.mktree (Turtle.directory modulePath)-- listOfExtraInstances <- traverse getExtraInstances extraInstanceFiles-- let extraInstances = mconcat listOfExtraInstances-- haskellModule <- do- renderHsModuleForDotProto extraInstances dotProto importTypeContext-- liftIO (writeFile (FP.encodeString modulePath) haskellModule)---- | As 'compileDotProtoFile', except terminates the program with an error--- message on failure.-compileDotProtoFileOrDie- :: [FilePath]- -- ^ Haskell modules containing instances used to override default generated- -- instances- -> FilePath- -- ^ Output directory- -> [FilePath]- -- ^ List of search paths- -> FilePath- -- ^ Path to @.proto@ file (relative to search path)- -> IO ()-compileDotProtoFileOrDie- extraInstanceFiles- outputDirectory- searchPaths- dotProtoPath = do- compileResult <- do- compileDotProtoFile- extraInstanceFiles- outputDirectory- searchPaths- dotProtoPath-- case compileResult of- Left e -> do- -- TODO: pretty print the error messages- let errText = Turtle.format Turtle.w e- let dotProtoPathText = Turtle.format Turtle.fp dotProtoPath- dieLines [Neat.text|- Error: failed to compile "${dotProtoPathText}":-- ${errText}- |]- _ -> pure ()--getExtraInstances- :: (MonadIO m, MonadError CompileError m)- => FilePath -> m ([HsImportDecl], [HsDecl])-getExtraInstances extraInstanceFile = do- let extraInstanceFileString = FP.encodeString extraInstanceFile-- parseRes <- parseModule <$> liftIO (readFile extraInstanceFileString)-- case parseRes of- ParseOk (HsModule _srcloc _mod _es idecls decls) -> do- let isInstDecl HsInstDecl{} = True- isInstDecl _ = False-- return (idecls, filter isInstDecl decls) --TODO give compile result-- ParseFailed srcLoc err -> do- let srcLocText = Turtle.format Turtle.w srcLoc-- let errText = T.pack err-- let message = [Neat.text|- Error: Failed to parse instance file-- ${srcLocText}: ${errText}- |]-- internalError (T.unpack message)---- | Compile a 'DotProto' AST into a 'String' representing the Haskell--- source of a module implementing types and instances for the .proto--- messages and enums.-renderHsModuleForDotProto- :: MonadError CompileError m- => ([HsImportDecl],[HsDecl]) -> DotProto -> TypeContext -> m String-renderHsModuleForDotProto extraInstanceFiles dotProto importCtxt = do- haskellModule <- hsModuleForDotProto extraInstanceFiles dotProto importCtxt- return (T.unpack header ++ prettyPrint haskellModule)- where- header = [Neat.text|- {-# LANGUAGE DeriveGeneric #-}- {-# LANGUAGE DeriveAnyClass #-}- {-# LANGUAGE DataKinds #-}- {-# LANGUAGE GADTs #-}- {-# LANGUAGE TypeApplications #-}- {-# LANGUAGE OverloadedStrings #-}- {-# OPTIONS_GHC -fno-warn-unused-imports #-}- {-# OPTIONS_GHC -fno-warn-name-shadowing #-}- {-# OPTIONS_GHC -fno-warn-unused-matches #-}-- -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT!- |]---- | Compile a Haskell module AST given a 'DotProto' package AST.--- Instances given in @eis@ override those otherwise generated.-hsModuleForDotProto- :: MonadError CompileError m- => ([HsImportDecl], [HsDecl])- -- ^ Extra user-define instances that override default generated instances- -> DotProto- -- ^- -> TypeContext- -- ^- -> m HsModule-hsModuleForDotProto- _- DotProto { protoMeta = DotProtoMeta { metaModulePath = Path [] } }- _ =- throwError InternalEmptyModulePath-hsModuleForDotProto- (extraImports, extraInstances)- dotProto@DotProto- { protoPackage = DotProtoPackageSpec packageIdentifier- , protoMeta = DotProtoMeta { metaModulePath = modulePath }- , protoDefinitions- }- importTypeContext = do- moduleName <- modulePathModName modulePath-- typeContextImports <- ctxtImports importTypeContext-- let importDeclarations =- concat [ defaultImports hasService, extraImports, typeContextImports ]-- typeContext <- dotProtoTypeContext dotProto-- let toDotProtoDeclaration =- dotProtoDefinitionD packageIdentifier (typeContext <> importTypeContext)-- let instances = instancesForModule moduleName extraInstances-- listOfDeclarations <- traverse toDotProtoDeclaration protoDefinitions-- let overridenDeclarations =- replaceHsInstDecls instances (mconcat listOfDeclarations)-- return (module_ moduleName Nothing importDeclarations overridenDeclarations)- where- hasService = not (null [ () | DotProtoService {} <- protoDefinitions ])--hsModuleForDotProto _ _ _ =- throwError NoPackageDeclaration---- This very specific function will only work for the qualification on the very first type--- in the object of an instance declaration. Those are the only sort of instance declarations--- generated within this code, so it suffices.-instancesForModule :: Module -> [HsDecl] -> [HsDecl]-instancesForModule m = foldr go []- where go x xs = case x of- HsInstDecl a b c (HsTyCon (Qual tm i):ts) d ->- if m == tm then HsInstDecl a b c (HsTyCon (UnQual i):ts) d:xs else xs- _ -> xs---- | For each thing in @base@ replaces it if it finds a matching @override@-replaceHsInstDecls :: [HsDecl] -> [HsDecl] -> [HsDecl]-replaceHsInstDecls overrides base = concatMap mbReplace base- where -- instances defined separately from data type definition:- mbReplace hid@(HsInstDecl _ _ qn tys _) =- (: []) . fromMaybe hid $ search qn tys-- -- instances listed in "deriving" clause of data type definition:- mbReplace (HsDataDecl loc ctx tyn names def insts) =- let (filtered,customized) = partitionEithers (map (deriv tyn) insts)- in HsDataDecl loc ctx tyn names def filtered : customized-- -- irrelevant declarations remain unchanged:- mbReplace hid = [hid]-- deriv tyn qn = maybe (Left qn) Right $ search qn [HsTyCon (UnQual tyn)]-- search qn tys = find (\x -> Just (unQual qn,tys) == getSig x) overrides-- getSig (HsInstDecl _ _ qn tys _) = Just (unQual qn,tys)- getSig _ = Nothing-- unQual (Qual _ n) = Just n- unQual (UnQual n) = Just n- unQual (Special _) = Nothing---- | Parses the file at the given path and produces an AST along with a--- 'TypeContext' representing all types from imported @.proto@ files, using the--- first parameter as a list of paths to search for imported files. Terminates--- with exit code 1 when an included file cannot be found in the search path.-readDotProtoWithContext- :: [FilePath]- -> FilePath- -> IO (Either CompileError (DotProto, TypeContext))-readDotProtoWithContext [] dotProtoPath = do- -- If we're not given a search path, default to using the current working- -- directory, as `protoc` does- cwd <- Turtle.pwd- readDotProtoWithContext [cwd] dotProtoPath--readDotProtoWithContext searchPaths toplevelProto = runExceptT $ do- findProto searchPaths toplevelProto >>= \case- Found mp fp -> parse mp fp- BadModulePath e -> fatalBadModulePath toplevelProto e- NotFound -> dieLines [Neat.text|- Error: failed to find file "${toplevelProtoText}", after looking in- the following locations (controlled via the --includeDir switch(es)):-- $searchPathsText- |]- where- parse mp fp = parseProtoFile mp fp >>= \case- Right dp -> do- let importIt = readImportTypeContext searchPaths toplevelProto (S.singleton toplevelProto)- tc <- mconcat <$> mapM importIt (protoImports dp)- pure (dp, tc)- Left err -> throwError (CompileParseError err)-- searchPathsText = T.unlines (Turtle.format (" "%F.fp) . (</> toplevelProto) <$> searchPaths)- toplevelProtoText = Turtle.format F.fp toplevelProto--readImportTypeContext- :: (MonadError CompileError m, MonadIO m)- => [FilePath]- -> FilePath- -> S.Set FilePath- -> DotProtoImport- -> m TypeContext-readImportTypeContext searchPaths toplevelFP alreadyRead (DotProtoImport _ path)- | path `S.member` alreadyRead = throwError (CircularImport path)- | otherwise =- do import_ <- liftEither . first CompileParseError =<< importProto searchPaths toplevelFP path- case protoPackage import_ of- DotProtoPackageSpec importPkg ->- do importTypeContext <- dotProtoTypeContext import_- let importTypeContext' = flip fmap importTypeContext $ \tyInfo ->- tyInfo { dotProtoTypeInfoPackage = DotProtoPackageSpec importPkg- , dotProtoTypeInfoModulePath = metaModulePath . protoMeta $ import_- }- qualifiedTypeContext = M.fromList <$>- mapM (\(nm, tyInfo) -> (,tyInfo) <$> concatDotProtoIdentifier importPkg nm)- (M.assocs importTypeContext')-- importTypeContext'' <- (importTypeContext' <>) <$> qualifiedTypeContext- (importTypeContext'' <>) . mconcat <$> sequence- [ readImportTypeContext searchPaths toplevelFP (S.insert path alreadyRead) importImport- | importImport@(DotProtoImport DotProtoImportPublic _) <- protoImports import_- ]- _ -> throwError NoPackageDeclaration---- * Type-tracking data structures---- | Whether a definition is an enumeration or a message-data DotProtoKind = DotProtoKindEnum- | DotProtoKindMessage- deriving (Show, Eq, Ord, Enum, Bounded)---- | Information about messages and enumerations-data DotProtoTypeInfo = DotProtoTypeInfo- { dotProtoTypeInfoPackage :: DotProtoPackageSpec- -- ^ The package this type is defined in- , dotProtoTypeInfoParent :: DotProtoIdentifier- -- ^ The message this type is nested under, or 'Anonymous' if it's top-level- , dotProtoTypeChildContext :: TypeContext- -- ^ The context that should be used for declarations within the- -- scope of this type- , dotProtoTypeInfoKind :: DotProtoKind- -- ^ Whether this type is an enumeration or message- , dotProtoTypeInfoModulePath :: Path- -- ^ The include-relative module path used when importing this module- } deriving Show---- | A mapping from .proto type identifiers to their type information-type TypeContext = M.Map DotProtoIdentifier DotProtoTypeInfo---- ** Generating type contexts from ASTs--dotProtoTypeContext :: MonadError CompileError m => DotProto -> m TypeContext-dotProtoTypeContext DotProto { protoDefinitions- , protoMeta = DotProtoMeta modulePath- }- = mconcat <$> mapM (definitionTypeContext modulePath) protoDefinitions--definitionTypeContext- :: MonadError CompileError m => Path -> DotProtoDefinition -> m TypeContext-definitionTypeContext modulePath (DotProtoMessage msgIdent parts) =- do childTyContext <-- mapM updateDotProtoTypeInfoParent =<<- (mconcat <$> sequenceA- [ definitionTypeContext modulePath def- | DotProtoMessageDefinition def <- parts ])-- qualifiedChildTyContext <- M.fromList <$>- mapM (\(nm, tyInfo) -> (,tyInfo) <$>- concatDotProtoIdentifier msgIdent nm)- (M.assocs childTyContext)-- pure (M.singleton msgIdent- (DotProtoTypeInfo DotProtoNoPackage Anonymous- childTyContext DotProtoKindMessage modulePath) <>- qualifiedChildTyContext)- where updateDotProtoTypeInfoParent tyInfo =- do dotProtoTypeInfoParent <-- concatDotProtoIdentifier msgIdent (dotProtoTypeInfoParent tyInfo)- pure tyInfo { dotProtoTypeInfoParent }-definitionTypeContext modulePath (DotProtoEnum enumIdent _) =- pure (M.singleton enumIdent- (DotProtoTypeInfo DotProtoNoPackage Anonymous mempty DotProtoKindEnum modulePath))-definitionTypeContext _ _ = pure mempty--concatDotProtoIdentifier :: MonadError CompileError m- => DotProtoIdentifier -> DotProtoIdentifier -> m DotProtoIdentifier--concatDotProtoIdentifier Qualified{} _ = internalError "concatDotProtoIdentifier: Qualified"-concatDotProtoIdentifier _ Qualified{} = internalError "concatDotProtoIdentifier Qualified"--concatDotProtoIdentifier Anonymous Anonymous = pure Anonymous-concatDotProtoIdentifier Anonymous b = pure b-concatDotProtoIdentifier a Anonymous = pure a--concatDotProtoIdentifier (Single a) b = concatDotProtoIdentifier (Dots (Path [a])) b-concatDotProtoIdentifier a (Single b) = concatDotProtoIdentifier a (Dots (Path [b]))--concatDotProtoIdentifier (Dots (Path a)) (Dots (Path b)) = pure . Dots . Path $ a ++ b---- | Given a type context, generates the import statements necessary--- to import all the required types.-ctxtImports :: MonadError CompileError m => TypeContext -> m [HsImportDecl]-ctxtImports tyCtxt =- do imports <- nub <$> sequence- [ modulePathModName modulePath- | DotProtoTypeInfo { dotProtoTypeInfoModulePath = modulePath }- <- M.elems tyCtxt- ]- pure [ importDecl_ modName True Nothing Nothing | modName <- imports ]---- * Functions to convert 'DotProtoType' into Haskell types---- Convert a dot proto type to a Haskell type-dptToHsType :: MonadError CompileError m => TypeContext -> DotProtoType -> m HsType-dptToHsType = foldDPT dptToHsContType dpptToHsType---- Convert a dot proto type to a wrapped Haskell type-dptToHsTypeWrapped :: MonadError CompileError m => [DotProtoOption] -> TypeContext -> DotProtoType -> m HsType-dptToHsTypeWrapped opts =- foldDPT- -- The wrapper for the collection type replaces the native haskell- -- collection type, so try that first.- (\ctxt ty -> maybe (dptToHsContType ctxt ty) id (dptToHsWrappedContType ctxt opts ty))- -- Always wrap the primitive type.- (\ctxt ty -> dpptToHsTypeWrapper ty <$> dpptToHsType ctxt ty)--foldDPT :: MonadError CompileError m- => (TypeContext -> DotProtoType -> HsType -> HsType)- -> (TypeContext -> DotProtoPrimType -> m HsType)- -> TypeContext- -> DotProtoType- -> m HsType-foldDPT dptToHsCont foldPrim ctxt dpt =- let- prim = foldPrim ctxt- go = foldDPT dptToHsCont foldPrim ctxt- cont = dptToHsCont ctxt dpt- in- case dpt of- Prim pType -> cont <$> prim pType- Optional pType -> cont <$> prim pType- Repeated pType -> cont <$> prim pType- NestedRepeated pType -> cont <$> prim pType- Map k v | validMapKey k -> HsTyApp . cont <$> prim k <*> go (Prim v) -- need to 'Nest' message types- | otherwise -> throwError $ InvalidMapKeyType (show $ pPrint k)---- Translate DotProtoType constructors to wrapped Haskell container types--- (for Message serde instances).-dptToHsWrappedContType :: TypeContext -> [DotProtoOption] -> DotProtoType -> Maybe (HsType -> HsType)-dptToHsWrappedContType ctxt opts = \case- Prim (Named tyName)- | isMessage ctxt tyName -> Just $ HsTyApp (protobufType_ "Nested")- Repeated (Named tyName)- | isMessage ctxt tyName -> Just $ HsTyApp (protobufType_ "NestedVec")- Repeated ty- | isUnpacked opts -> Just $ HsTyApp (protobufType_ "UnpackedVec")- | isPacked opts -> Just $ HsTyApp (protobufType_ "PackedVec")- | isPackable ctxt ty -> Just $ HsTyApp (protobufType_ "PackedVec")- | otherwise -> Just $ HsTyApp (protobufType_ "UnpackedVec")- _ -> Nothing---- Translate DotProtoType to Haskell container types.-dptToHsContType :: TypeContext -> DotProtoType -> HsType -> HsType-dptToHsContType ctxt = \case- Prim (Named tyName) | isMessage ctxt tyName- -> HsTyApp $ primType_ "Maybe"- Optional _ -> HsTyApp $ primType_ "Maybe"- Repeated _ -> HsTyApp $ primType_ "Vector"- NestedRepeated _ -> HsTyApp $ primType_ "Vector"- Map _ _ -> HsTyApp $ primType_ "Map"- _ -> id---- Haskell wrapper for primitive dot proto types-dpptToHsTypeWrapper :: DotProtoPrimType -> HsType -> HsType-dpptToHsTypeWrapper = \case- SInt32 -> HsTyApp (protobufType_ "Signed")- SInt64 -> HsTyApp (protobufType_ "Signed")- SFixed32 -> HsTyApp (protobufType_ "Signed") . HsTyApp (protobufType_ "Fixed")- SFixed64 -> HsTyApp (protobufType_ "Signed") . HsTyApp (protobufType_ "Fixed")- Fixed32 -> HsTyApp (protobufType_ "Fixed")- Fixed64 -> HsTyApp (protobufType_ "Fixed")- _ -> id---- Convert a dot proto prim type to an unwrapped Haskell type-dpptToHsType :: MonadError CompileError m => TypeContext -> DotProtoPrimType -> m HsType-dpptToHsType ctxt = \case- Int32 -> pure $ primType_ "Int32"- Int64 -> pure $ primType_ "Int64"- SInt32 -> pure $ primType_ "Int32"- SInt64 -> pure $ primType_ "Int64"- UInt32 -> pure $ primType_ "Word32"- UInt64 -> pure $ primType_ "Word64"- Fixed32 -> pure $ primType_ "Word32"- Fixed64 -> pure $ primType_ "Word64"- SFixed32 -> pure $ primType_ "Int32"- SFixed64 -> pure $ primType_ "Int64"- String -> pure $ primType_ "Text"- Bytes -> pure $ primType_ "ByteString"- Bool -> pure $ primType_ "Bool"- Float -> pure $ primType_ "Float"- Double -> pure $ primType_ "Double"- Named msgName ->- case M.lookup msgName ctxt of- Just ty@(DotProtoTypeInfo { dotProtoTypeInfoKind = DotProtoKindEnum }) ->- HsTyApp (protobufType_ "Enumerated") <$> msgTypeFromDpTypeInfo ty msgName- Just ty -> msgTypeFromDpTypeInfo ty msgName- Nothing -> noSuchTypeError msgName---validMapKey :: DotProtoPrimType -> Bool-validMapKey = (`elem` [ Int32, Int64, SInt32, SInt64, UInt32, UInt64- , Fixed32, Fixed64, SFixed32, SFixed64- , String, Bool])--isMessage :: TypeContext -> DotProtoIdentifier -> Bool-isMessage ctxt n = Just DotProtoKindMessage == (dotProtoTypeInfoKind <$> M.lookup n ctxt)--isPacked :: [DotProtoOption] -> Bool-isPacked opts =- case find (\(DotProtoOption name _) -> name == Single "packed") opts of- Just (DotProtoOption _ (BoolLit x)) -> x- _ -> False--isUnpacked :: [DotProtoOption] -> Bool-isUnpacked opts =- case find (\(DotProtoOption name _) -> name == Single "packed") opts of- Just (DotProtoOption _ (BoolLit x)) -> not x- _ -> False---- | Returns 'True' if the given primitive type is packable. The 'TypeContext'--- is used to distinguish Named enums and messages, only the former of which are--- packable.-isPackable :: TypeContext -> DotProtoPrimType -> Bool-isPackable _ Bytes = False-isPackable _ String = False-isPackable _ Int32 = True-isPackable _ Int64 = True-isPackable _ SInt32 = True-isPackable _ SInt64 = True-isPackable _ UInt32 = True-isPackable _ UInt64 = True-isPackable _ Fixed32 = True-isPackable _ Fixed64 = True-isPackable _ SFixed32 = True-isPackable _ SFixed64 = True-isPackable _ Bool = True-isPackable _ Float = True-isPackable _ Double = True-isPackable ctxt (Named tyName) =- Just DotProtoKindEnum == (dotProtoTypeInfoKind <$> M.lookup tyName ctxt)---- *** Helper functions for names---- | Generate the Haskell type name for a 'DotProtoTypeInfo' for a message /--- enumeration being compiled. NB: We ignore the 'dotProtoTypeInfoPackage'--- field of the 'DotProtoTypeInfo' parameter, instead demanding that we have--- been provided with a valid module path in its 'dotProtoTypeInfoModulePath'--- field. The latter describes the name of the Haskell module being generated.-msgTypeFromDpTypeInfo :: MonadError CompileError m- => DotProtoTypeInfo -> DotProtoIdentifier -> m HsType-msgTypeFromDpTypeInfo- DotProtoTypeInfo { dotProtoTypeInfoParent = p- , dotProtoTypeInfoModulePath = modulePath- }- ident- | Path [] <- modulePath = throwError InternalEmptyModulePath- | otherwise = do- modName <- modulePathModName modulePath- identName <- nestedTypeName p =<< dpIdentUnqualName ident- pure $ HsTyCon (Qual modName (HsIdent identName))---- | Given a 'DotProtoIdentifier' for the parent type and the unqualified name--- of this type, generate the corresponding Haskell name-nestedTypeName :: MonadError CompileError m => DotProtoIdentifier -> String -> m String-nestedTypeName Anonymous nm = typeLikeName nm-nestedTypeName (Single parent) nm = intercalate "_" <$> sequenceA [ typeLikeName parent , typeLikeName nm ]-nestedTypeName (Dots (Path parents)) nm = intercalate "_" . (<>[nm]) <$> mapM typeLikeName parents-nestedTypeName (Qualified {}) _ = internalError "nestedTypeName: Qualified"--haskellName, jsonpbName, grpcName, protobufName, proxyName- :: String -> HsQName-haskellName name = Qual (Module "Hs") (HsIdent name)-jsonpbName name = Qual (Module "HsJSONPB") (HsIdent name)-grpcName name = Qual (Module "HsGRPC") (HsIdent name)-protobufName name = Qual (Module "HsProtobuf") (HsIdent name)-proxyName name = Qual (Module "Proxy") (HsIdent name)--#ifdef DHALL-hsDhallPB :: String-hsDhallPB = "HsDhallPb"--dhallPBName :: String -> HsQName-dhallPBName name = Qual (Module hsDhallPB) (HsIdent name)-#endif--camelCased :: String -> String-camelCased s = do- (prev, cur) <- zip (Nothing:map Just s) (map Just s ++ [Nothing])- case (prev, cur) of- (Just '_', Just x) | isAlpha x -> pure (toUpper x)- (Just '_', Nothing) -> pure '_'- (Just '_', Just '_') -> pure '_'- (_, Just '_') -> empty- (_, Just x) -> pure x- (_, _) -> empty--typeLikeName :: MonadError CompileError m => String -> m String-typeLikeName ident@(firstChar:remainingChars)- | isUpper firstChar = pure (camelCased ident)- | isLower firstChar = pure (camelCased (toUpper firstChar:remainingChars))- | firstChar == '_' = pure (camelCased ('X':ident))-typeLikeName ident = invalidTypeNameError ident--fieldLikeName :: String -> String-fieldLikeName ident@(firstChar:_)- | isUpper firstChar = let (prefix, suffix) = span isUpper ident- in map toLower prefix ++ suffix-fieldLikeName ident = ident--prefixedEnumFieldName :: String -> String -> String-prefixedEnumFieldName enumName fieldName = enumName <> fieldName--prefixedConName :: MonadError CompileError m => String -> String -> m String-prefixedConName msgName conName =- (msgName ++) <$> typeLikeName conName---- TODO: This should be ~:: MessageName -> FieldName -> ...; same elsewhere, the--- String types are a bit of a hassle.-prefixedFieldName :: MonadError CompileError m => String -> String -> m String-prefixedFieldName msgName fieldName =- (fieldLikeName msgName ++) <$> typeLikeName fieldName--dpIdentUnqualName :: MonadError CompileError m => DotProtoIdentifier -> m String-dpIdentUnqualName (Single name) = pure name-dpIdentUnqualName (Dots (Path names)) = pure (last names)-dpIdentUnqualName (Qualified _ next) = dpIdentUnqualName next-dpIdentUnqualName Anonymous = internalError "dpIdentUnqualName: Anonymous"--dpIdentQualName :: MonadError CompileError m => DotProtoIdentifier -> m String-dpIdentQualName (Single name) = pure name-dpIdentQualName (Dots (Path names)) = pure (intercalate "." names)-dpIdentQualName (Qualified _ _) = internalError "dpIdentQualName: Qualified"-dpIdentQualName Anonymous = internalError "dpIdentQualName: Anonymous"--modulePathModName :: MonadError CompileError m => Path -> m Module-modulePathModName (Path []) = throwError InternalEmptyModulePath-modulePathModName (Path comps) = Module <$> (intercalate "." <$> mapM typeLikeName comps)--_pkgIdentModName :: MonadError CompileError m => DotProtoIdentifier -> m Module-_pkgIdentModName (Single s) = Module <$> typeLikeName s-_pkgIdentModName (Dots (Path paths)) = Module <$> (intercalate "." <$> mapM typeLikeName paths)-_pkgIdentModName _ = internalError "pkgIdentModName: Malformed package name"---- * Generate instances for a 'DotProto' package--dotProtoDefinitionD- :: MonadError CompileError m- => DotProtoIdentifier -> TypeContext -> DotProtoDefinition -> m [HsDecl]-dotProtoDefinitionD _ ctxt (DotProtoMessage messageName dotProtoMessage) =- dotProtoMessageD ctxt Anonymous messageName dotProtoMessage-dotProtoDefinitionD _ _ (DotProtoEnum messageName dotProtoEnum) =- dotProtoEnumD Anonymous messageName dotProtoEnum-dotProtoDefinitionD pkgIdent ctxt (DotProtoService serviceName dotProtoService) =- dotProtoServiceD pkgIdent ctxt serviceName dotProtoService---- | Generate 'Named' instance for a type in this package-namedInstD :: String -> HsDecl-namedInstD messageName =- instDecl_ (protobufName "Named")- [ type_ messageName ]- [ HsFunBind [nameOfDecl] ]- where- nameOfDecl = match_ (HsIdent "nameOf") [HsPWildCard]- (HsUnGuardedRhs (apply fromStringE- [ HsLit (HsString messageName) ]))- []---- ** Generate types and instances for .proto messages---- | Generate data types, 'Bounded', 'Enum', 'FromJSONPB', 'Named', 'Message',--- 'ToJSONPB' instances as appropriate for the given 'DotProtoMessagePart's-dotProtoMessageD- :: MonadError CompileError m- => TypeContext- -> DotProtoIdentifier- -> DotProtoIdentifier- -> [DotProtoMessagePart]- -> m [HsDecl]-dotProtoMessageD ctxt parentIdent messageIdent message = do- messageName <- nestedTypeName parentIdent =<< dpIdentUnqualName messageIdent-- let ctxt' = maybe mempty dotProtoTypeChildContext (M.lookup messageIdent ctxt) <> ctxt-- messagePartFieldD (DotProtoMessageField (DotProtoField _ ty fieldName _ _)) = do- fullName <- prefixedFieldName messageName =<< dpIdentUnqualName fieldName- fullTy <- dptToHsType ctxt' ty- pure [ ([HsIdent fullName], HsUnBangedTy fullTy ) ]-- messagePartFieldD (DotProtoMessageOneOf fieldName _) = do- fullName <- prefixedFieldName messageName =<< dpIdentUnqualName fieldName- qualTyName <- prefixedConName messageName =<< dpIdentUnqualName fieldName- let fullTy = HsTyApp (HsTyCon (haskellName "Maybe")) . type_ $ qualTyName- pure [ ([HsIdent fullName], HsUnBangedTy fullTy) ]-- messagePartFieldD _ = pure []-- nestedDecls :: MonadError CompileError m => DotProtoDefinition -> m [HsDecl]- nestedDecls (DotProtoMessage subMsgName subMessageDef) = do- parentIdent' <- concatDotProtoIdentifier parentIdent messageIdent- dotProtoMessageD ctxt' parentIdent' subMsgName subMessageDef-- nestedDecls (DotProtoEnum subEnumName subEnumDef) = do- parentIdent' <- concatDotProtoIdentifier parentIdent messageIdent- dotProtoEnumD parentIdent' subEnumName subEnumDef-- nestedDecls _ = pure []-- nestedOneOfDecls :: MonadError CompileError m- => DotProtoIdentifier -> [DotProtoField] -> m [HsDecl]- nestedOneOfDecls identifier fields = do- fullName <- prefixedConName messageName =<< dpIdentUnqualName identifier- let oneOfCons (DotProtoField _ ty fieldName _ _) = do- consTy <- case ty of- Prim msg@(Named msgName)- | Just DotProtoKindMessage <- dotProtoTypeInfoKind <$> M.lookup msgName ctxt'- -> -- Do not wrap message summands with Maybe.- dpptToHsType ctxt' msg-- _ -> dptToHsType ctxt' ty-- consName <- prefixedConName fullName =<< dpIdentUnqualName fieldName- let ident = HsIdent consName- pure (conDecl_ ident [HsUnBangedTy consTy], ident)-- oneOfCons DotProtoEmptyField = internalError "field type : empty field"-- (cons, idents) <- fmap unzip (mapM oneOfCons fields)-- fieldNames <- mapM (dpIdentUnqualName . dotProtoFieldName) fields-- toSchemaInstance <- toSchemaInstanceDeclaration fullName fieldNames (Just idents)-- pure [ dataDecl_ fullName cons defaultMessageDeriving- , namedInstD fullName- , toSchemaInstance--#ifdef DHALL- , dhallInterpretInstDecl fullName- , dhallInjectInstDecl fullName-#endif- ]-- conDecl <- recDecl_ (HsIdent messageName) . mconcat <$>- mapM messagePartFieldD message-- nestedDecls_ <- mconcat <$>- sequence [ nestedDecls def | DotProtoMessageDefinition def <- message]-- nestedOneofs_ <- mconcat <$>- sequence [ nestedOneOfDecls ident fields | DotProtoMessageOneOf ident fields <- message ]-- messageInst <- messageInstD ctxt' parentIdent messageIdent message-- toJSONPBInst <- toJSONPBMessageInstD ctxt' parentIdent messageIdent message- fromJSONPBInst <- fromJSONPBMessageInstD ctxt' parentIdent messageIdent message-- fieldNames <- sequence $ do- messagePart <- message- dotProtoIdentifier <- case messagePart of- DotProtoMessageField dotProtoField ->- return (dotProtoFieldName dotProtoField)- DotProtoMessageOneOf dotProtoIdentifier _ ->- return dotProtoIdentifier- _ -> empty- return (dpIdentUnqualName dotProtoIdentifier)-- toSchemaInstance <- toSchemaInstanceDeclaration messageName fieldNames Nothing-- pure $ [ dataDecl_ messageName [ conDecl ] defaultMessageDeriving- , namedInstD messageName- , messageInst- , toJSONPBInst- , fromJSONPBInst- -- Generate Aeson instances in terms of JSONPB instances- , toJSONInstDecl messageName- , fromJSONInstDecl messageName- -- And the Swagger ToSchema instance corresponding to JSONPB encodings- , toSchemaInstance--#ifdef DHALL- -- Generate Dhall instances- , dhallInterpretInstDecl messageName- , dhallInjectInstDecl messageName-#endif- ]- <> nestedOneofs_- <> nestedDecls_---- *** Generate Protobuf 'Message' instances--messageInstD- :: MonadError CompileError m- => TypeContext- -> DotProtoIdentifier -> DotProtoIdentifier- -> [DotProtoMessagePart]- -> m HsDecl-messageInstD ctxt parentIdent msgIdent messageParts = do- msgName <- nestedTypeName parentIdent =<< dpIdentUnqualName msgIdent- qualifiedFields <- getQualifiedFields msgName messageParts-- let encodeMessageField QualifiedField{recordFieldName, fieldInfo} =- let recordFieldName' = HsVar (unqual_ (coerce recordFieldName)) in- case fieldInfo of- FieldNormal _fieldName fieldNum dpType options -> do- fieldE <- wrapE ctxt options dpType recordFieldName'- pure $ apply encodeMessageFieldE [ fieldNumberE fieldNum, fieldE ]-- FieldOneOf OneofField{subfields} -> do- -- Create all pattern match & expr for each constructor:- -- Constructor y -> encodeMessageField num (Nested (Just y)) -- for embedded messages- -- Constructor y -> encodeMessageField num (ForceEmit y) -- for everything else- let mkAlt (OneofSubfield fieldNum conName _ dpType options) = do- let isMaybe- | Prim (Named tyName) <- dpType- = Just DotProtoKindMessage == fmap dotProtoTypeInfoKind (M.lookup tyName ctxt)- | otherwise- = False-- let wrapJust = HsParen . HsApp (HsVar (haskellName "Just"))-- xE <- (if isMaybe then id else fmap forceEmitE)- . wrapE ctxt options dpType- . (if isMaybe then wrapJust else id)- $ HsVar (unqual_ "y")-- pure $ alt_ (HsPApp (unqual_ conName) [patVar "y"])- (HsUnGuardedAlt (apply encodeMessageFieldE [fieldNumberE fieldNum, xE]))- []-- alts <- mapM mkAlt subfields-- pure $ HsCase recordFieldName'- [ alt_ (HsPApp (haskellName "Nothing") [])- (HsUnGuardedAlt memptyE)- []- , alt_ (HsPApp (haskellName "Just") [patVar "x"])- (HsUnGuardedAlt (HsCase (HsVar (unqual_ "x")) alts))- []- ]-- let decodeMessageField QualifiedField{fieldInfo} = do- case fieldInfo of- FieldNormal _fieldName fieldNum dpType options ->- unwrapE ctxt options dpType $ apply atE [ decodeMessageFieldE, fieldNumberE fieldNum ]-- FieldOneOf OneofField{subfields} -> do- -- create a list of (fieldNumber, Cons <$> parser)- let subfieldParserE (OneofSubfield fieldNumber consName _ dpType options) = do- let fE = case dpType of- Prim (Named tyName)- | Just DotProtoKindMessage <- dotProtoTypeInfoKind <$> M.lookup tyName ctxt- -> HsParen (HsApp fmapE (HsVar (unqual_ consName)))- _ -> HsParen (HsInfixApp (HsVar (haskellName "Just"))- composeOp- (HsVar (unqual_ consName)))-- alts <- unwrapE ctxt options dpType decodeMessageFieldE-- pure $ HsTuple- [ fieldNumberE fieldNumber- , HsInfixApp (apply pureE [ fE ]) apOp alts- ]-- parsers <- mapM subfieldParserE subfields-- pure $ apply oneofE [ HsVar (haskellName "Nothing")- , HsList parsers- ]-- let dotProtoE = HsList- [ apply dotProtoFieldC- [ fieldNumberE fieldNum- , dpTypeE dpType- , dpIdentE fieldIdent- , HsList (map optionE options)- , maybeE (HsLit . HsString) comments- ]- | DotProtoMessageField (DotProtoField fieldNum dpType fieldIdent options comments)- <- messageParts- ]-- let punnedFieldsP =- [ HsPFieldPat (unqual_ fieldName) (HsPVar (HsIdent fieldName))- | QualifiedField (coerce -> fieldName) _ <- qualifiedFields- ]-- encodedFields <- mapM encodeMessageField qualifiedFields- decodedFields <- mapM decodeMessageField qualifiedFields-- let encodeMessageE = apply mconcatE [ HsList encodedFields]- let decodeMessageE = foldl (\f -> HsInfixApp f apOp)- (apply pureE [ HsVar (unqual_ msgName) ])- decodedFields-- let encodeMessageDecl = match_ (HsIdent "encodeMessage")- [HsPWildCard, HsPRec (unqual_ msgName) punnedFieldsP]- (HsUnGuardedRhs encodeMessageE) []- let decodeMessageDecl = match_ (HsIdent "decodeMessage") [ HsPWildCard ]- (HsUnGuardedRhs decodeMessageE) []- let dotProtoDecl = match_ (HsIdent "dotProto") [HsPWildCard]- (HsUnGuardedRhs dotProtoE) []-- pure $ instDecl_ (protobufName "Message")- [ type_ msgName ]- [ HsFunBind [ encodeMessageDecl ]- , HsFunBind [ decodeMessageDecl ]- , HsFunBind [ dotProtoDecl ]- ]----- *** Generate ToJSONPB/FromJSONPB instances--toJSONPBMessageInstD- :: MonadError CompileError m- => TypeContext- -> DotProtoIdentifier- -> DotProtoIdentifier- -> [DotProtoMessagePart]- -> m HsDecl-toJSONPBMessageInstD _ctxt parentIdent msgIdent messageParts = do- msgName <- nestedTypeName parentIdent =<< dpIdentUnqualName msgIdent- qualFields <- getQualifiedFields msgName messageParts-- -- E.g.- -- "another" .= f2 -- always succeeds (produces default value on missing field)- let defPairE fldName fldNum =- HsInfixApp (HsLit (HsString (coerce fldName)))- toJSONPBOp- (HsVar (unqual_ (fieldBinder fldNum)))- -- E.g.- -- HsJSONPB.pair "name" f4 -- fails on missing field- let pairE fldNm varNm =- apply (HsVar (jsonpbName "pair"))- [ HsLit (HsString (coerce fldNm))- , HsVar (unqual_ varNm)- ]-- -- Suppose we have a sum type Foo, nested inside a message Bar.- -- We want to generate the following:- --- -- > toJSONPB (Bar foo more stuff) =- -- > HsJSONPB.object- -- > [ (let encodeFoo = (<case expr scrutinising foo> :: Options -> Value)- -- > in \option -> if optEmitNamedOneof option- -- > then ("Foo" .= (PB.objectOrNull [encodeFoo] option)) option- -- > else encodeFoo option- -- > )- -- > , <encode more>- -- > , <encode stuff>- -- > ]- let oneofCaseE retJsonCtor (OneofField typeName subfields) =- HsParen- $ HsLet [ HsFunBind [ match_ (HsIdent caseName) [] (HsUnGuardedRhs caseExpr) [] ] ]- $ HsLambda l [patVar optsStr] (HsIf dontInline noInline yesInline)- where- optsStr = "options"- opts = HsVar (unqual_ optsStr)-- caseName = "encode" <> over (ix 0) toUpper typeName- caseBnd = HsVar (unqual_ caseName)-- dontInline = HsApp (HsVar (jsonpbName "optEmitNamedOneof")) opts-- noInline = HsApp (HsParen (HsInfixApp (HsLit (HsString typeName))- toJSONPBOp- (apply (HsVar (jsonpbName retJsonCtor)) [ HsList [caseBnd], opts ])))- opts-- yesInline = HsApp caseBnd opts--- -- E.g.- -- case f4_or_f9 of- -- Just (SomethingPickOneName f4)- -- -> HsJSONPB.pair "name" f4- -- Just (SomethingPickOneSomeid f9)- -- -> HsJSONPB.pair "someid" f9- -- Nothing- -- -> mempty- caseExpr = HsParen $- HsCase disjunctName (altEs <> [fallthroughE])- where- disjunctName = HsVar (unqual_ (oneofSubDisjunctBinder subfields))- altEs = do- sub@(OneofSubfield _ conName pbFldNm _ _) <- subfields- let patVarNm = oneofSubBinder sub- pure $ alt_ (HsPApp (haskellName "Just")- [ HsPParen- $ HsPApp (unqual_ conName) [patVar patVarNm]- ]- )- (HsUnGuardedAlt (pairE pbFldNm patVarNm))- []- fallthroughE =- alt_ (HsPApp (haskellName "Nothing") [])- (HsUnGuardedAlt memptyE)- []-- let patBinder = onQF (const fieldBinder) (oneofSubDisjunctBinder . subfields)-- let applyE nm oneofNm =- apply (HsVar (jsonpbName nm))- [ HsList (onQF defPairE (oneofCaseE oneofNm) <$> qualFields) ]-- let matchE nm appNm oneofAppNm =- match_- (HsIdent nm)- [ HsPApp (unqual_ msgName)- (patVar . patBinder <$> qualFields) ]- (HsUnGuardedRhs (applyE appNm oneofAppNm))- []-- pure $ instDecl_ (jsonpbName "ToJSONPB")- [ type_ msgName ]- [ HsFunBind [matchE "toJSONPB" "object" "objectOrNull"]- , HsFunBind [matchE "toEncodingPB" "pairs" "pairsOrNull" ]- ]---fromJSONPBMessageInstD- :: MonadError CompileError m- => TypeContext- -> DotProtoIdentifier- -> DotProtoIdentifier- -> [DotProtoMessagePart]- -> m HsDecl-fromJSONPBMessageInstD _ctxt parentIdent msgIdent messageParts = do- msgName <- nestedTypeName parentIdent =<< dpIdentUnqualName msgIdent- qualFields <- getQualifiedFields msgName messageParts-- let lambdaPVar = patVar "obj"- let lambdaVar = HsVar (unqual_ "obj")-- -- E.g., for message- -- message Something { oneof name_or_id { string name = _; int32 someid = _; } }- --- -- ==>- --- -- (let parseSomethingNameOrId parseObj = <FUNCTION, see tryParseDisjunctsE>- -- in ((obj .: "nameOrId") Hs.>>=- -- (HsJSONPB.withObject "nameOrId" parseSomethingNameOrId))- -- <|>- -- (parseSomethingNameOrId obj)- -- )- let oneofParserE (OneofField oneofType fields) =- HsParen $- HsLet [ HsFunBind [ match_ (HsIdent letBndStr) [patVar letArgStr ]- (HsUnGuardedRhs tryParseDisjunctsE) []- ]- ]- (HsInfixApp parseWrapped altOp parseUnwrapped)- where- oneofTyLit = HsLit (HsString oneofType) -- FIXME-- letBndStr = "parse" <> over (ix 0) toUpper oneofType- letBndName = HsVar (unqual_ letBndStr)- letArgStr = "parseObj"- letArgName = HsVar (unqual_ letArgStr)-- parseWrapped = HsParen $- HsInfixApp (HsParen (HsInfixApp lambdaVar parseJSONPBOp oneofTyLit))- bindOp- (apply (HsVar (jsonpbName "withObject")) [ oneofTyLit , letBndName ])-- parseUnwrapped = HsParen (HsApp letBndName lambdaVar)-- -- parseSomethingNameOrId parseObj =- -- Hs.msum- -- [ (Just . SomethingPickOneName) <$> (HsJSONPB.parseField parseObj "name")- -- , (Just . SomethingPickOneSomeid) <$> (HsJSONPB.parseField parseObj "someid")- -- , pure Nothing- -- ]- tryParseDisjunctsE =- HsApp msumE (HsList (map subParserE fields <> fallThruE))- where- fallThruE- = [ HsApp pureE (HsVar (haskellName "Nothing")) ]- subParserE OneofSubfield{subfieldConsName, subfieldName}- = HsInfixApp- (HsInfixApp (HsVar (haskellName "Just"))- composeOp- (HsVar (unqual_ subfieldConsName)))- fmapOp- (apply (HsVar (jsonpbName "parseField"))- [ letArgName- , HsLit (HsString (coerce subfieldName))])-- -- E.g. obj .: "someid"- let normalParserE fldNm _ =- HsInfixApp lambdaVar- parseJSONPBOp- (HsLit (HsString (coerce fldNm)))-- let parseJSONPBE =- apply (HsVar (jsonpbName "withObject"))- [ HsLit (HsString msgName)- , HsParen (HsLambda l [lambdaPVar] fieldAps)- ]- where- fieldAps = foldl (\f -> HsInfixApp f apOp)- (apply pureE [ HsVar (unqual_ msgName) ])- (onQF normalParserE oneofParserE <$> qualFields)-- let parseJSONPBDecl =- match_ (HsIdent "parseJSONPB") [] (HsUnGuardedRhs parseJSONPBE) []-- pure (instDecl_ (jsonpbName "FromJSONPB")- [ type_ msgName ]- [ HsFunBind [ parseJSONPBDecl ] ])--#ifdef DHALL--- *** Generate Dhall Interpret and Inject generic instances--dhallInterpretInstDecl :: String -> HsDecl-dhallInterpretInstDecl typeName =- instDecl_ (dhallPBName "Interpret")- [ type_ typeName ]- [ ]--dhallInjectInstDecl :: String -> HsDecl-dhallInjectInstDecl typeName =- instDecl_ (dhallPBName "Inject")- [ type_ typeName ]- [ ]-#endif---- *** Generate default Aeson To/FromJSON and Swagger ToSchema instances--- (These are defined in terms of ToJSONPB)--toJSONInstDecl :: String -> HsDecl-toJSONInstDecl typeName =- instDecl_ (jsonpbName "ToJSON")- [ type_ typeName ]- [ HsFunBind [ match_ (HsIdent "toJSON") []- (HsUnGuardedRhs (HsVar (jsonpbName "toAesonValue"))) []- ]- , HsFunBind [ match_ (HsIdent "toEncoding") []- (HsUnGuardedRhs (HsVar (jsonpbName "toAesonEncoding"))) []- ]- ]--fromJSONInstDecl :: String -> HsDecl-fromJSONInstDecl typeName =- instDecl_ (jsonpbName "FromJSON")- [ type_ typeName ]- [ HsFunBind [match_ (HsIdent "parseJSON") [] (HsUnGuardedRhs (HsVar (jsonpbName "parseJSONPB"))) []- ]- ]----- ** `ToSchema` instance code-generation--toSchemaInstanceDeclaration- :: MonadError CompileError m- => String- -- ^ Name of the message type to create an instance for- -> [String]- -- ^ Field names- -> Maybe [HsName]- -- ^ Oneof constructors- -> m HsDecl-toSchemaInstanceDeclaration messageName fieldNames maybeConstructors = do- qualifiedFieldNames <- mapM (prefixedFieldName messageName) fieldNames- let messageConstructor = HsCon (UnQual (HsIdent messageName))-- let _namedSchemaNameExpression = HsApp justC (HsLit (HsString messageName))-- -- { _paramSchemaType = HsJSONPB.SwaggerObject- -- }- let paramSchemaUpdates =- [ HsFieldUpdate _paramSchemaType _paramSchemaTypeExpression- ]- where- _paramSchemaType = jsonpbName "_paramSchemaType"-- _paramSchemaTypeExpression = HsVar (jsonpbName "SwaggerObject")-- let _schemaParamSchemaExpression = HsRecUpdate memptyE paramSchemaUpdates-- -- [ ("fieldName0", qualifiedFieldName0)- -- , ("fieldName1", qualifiedFieldName1)- -- ...- -- ]- let properties = HsList $ do- (fieldName, qualifiedFieldName) <- zip fieldNames qualifiedFieldNames-- let string = HsLit (HsString fieldName)-- let variable = HsVar (UnQual (HsIdent qualifiedFieldName))-- return (HsTuple [ string, variable ])-- let _schemaPropertiesExpression =- HsApp (HsVar (jsonpbName "insOrdFromList")) properties-- -- { _schemaParamSchema = ...- -- , _schemaProperties = ...- -- , ...- -- }- let schemaUpdates = normalUpdates ++ extraUpdates- where- normalUpdates =- [ HsFieldUpdate _schemaParamSchema _schemaParamSchemaExpression- , HsFieldUpdate _schemaProperties _schemaPropertiesExpression- ]-- extraUpdates =- case maybeConstructors of- Just _ ->- [ HsFieldUpdate _schemaMinProperties justOne- , HsFieldUpdate _schemaMaxProperties justOne- ]- Nothing ->- []-- _schemaParamSchema = jsonpbName "_schemaParamSchema"- _schemaProperties = jsonpbName "_schemaProperties"- _schemaMinProperties = jsonpbName "_schemaMinProperties"- _schemaMaxProperties = jsonpbName "_schemaMaxProperties"-- justOne = HsApp justC (HsLit (HsInt 1))-- let _namedSchemaSchemaExpression = HsRecUpdate memptyE schemaUpdates-- -- { _namedSchemaName = ...- -- , _namedSchemaSchema = ...- -- }- let namedSchemaUpdates =- [ HsFieldUpdate _namedSchemaName _namedSchemaNameExpression- , HsFieldUpdate _namedSchemaSchema _namedSchemaSchemaExpression- ]- where- _namedSchemaName = jsonpbName "_namedSchemaName"- _namedSchemaSchema = jsonpbName "_namedSchemaSchema"-- let namedSchema = HsRecConstr (jsonpbName "NamedSchema") namedSchemaUpdates-- let toDeclareName fieldName = "declare_" ++ fieldName-- let toArgument fieldName = HsApp asProxy declare- where- declare = HsVar (UnQual (HsIdent (toDeclareName fieldName)))-- asProxy = HsVar (jsonpbName "asProxy")-- -- do let declare_fieldName0 = HsJSONPB.declareSchemaRef- -- qualifiedFieldName0 <- declare_fieldName0 Proxy.Proxy- -- let declare_fieldName1 = HsJSONPB.declareSchemaRef- -- qualifiedFieldName1 <- declare_fieldName1 Proxy.Proxy- -- ...- -- let _ = pure MessageName <*> HsJSONPB.asProxy declare_fieldName0 <*> HsJSONPB.asProxy declare_fieldName1 <*> ...- -- return (...)- let expressionForMessage =- HsDo (bindingStatements ++ inferenceStatements ++ [ returnStatement ])- where- bindingStatements = do- (fieldName, qualifiedFieldName) <- zip fieldNames qualifiedFieldNames-- let declareIdentifier = HsIdent (toDeclareName fieldName)-- let rightHandSide0 =- HsUnGuardedRhs (HsVar (jsonpbName "declareSchemaRef"))-- let match = HsMatch l declareIdentifier [] rightHandSide0 []-- let statement0 = HsLetStmt [ HsFunBind [ match ] ]-- let declareVariable = HsVar (UnQual declareIdentifier)-- let proxy = HsCon (proxyName "Proxy")-- let rightHandSide1 = HsApp declareVariable proxy-- let pattern = HsPVar (HsIdent qualifiedFieldName)-- let statement1 = HsGenerator l pattern rightHandSide1-- [ statement0, statement1 ]--- inferenceStatements =- if null fieldNames then [] else [ HsLetStmt [ patternBind ] ]- where- arguments = map toArgument fieldNames-- rightHandSide =- HsUnGuardedRhs (applicativeApply messageConstructor arguments)-- patternBind = HsPatBind l HsPWildCard rightHandSide []-- returnStatement = HsQualifier (HsApp returnE (HsParen namedSchema))-- -- do let declare_fieldName0 = HsJSONPB.declareSchemaRef- -- let _ = pure ConstructorName0 <*> HsJSONPB.asProxy declare_fieldName0- -- qualifiedFieldName0 <- declare_fieldName0 Proxy.Proxy- -- let declare_fieldName1 = HsJSONPB.declareSchemaRef- -- let _ = pure ConstructorName1 <*> HsJSONPB.asProxy declare_fieldName1- -- qualifiedFieldName1 <- declare_fieldName1 Proxy.Proxy- -- ...- -- return (...)- let expressionForOneOf constructors =- HsDo (bindingStatements ++ [ returnStatement ])- where- bindingStatements = do- (fieldName, qualifiedFieldName, constructor) <- zip3 fieldNames qualifiedFieldNames constructors-- let declareIdentifier = HsIdent (toDeclareName fieldName)-- let rightHandSide0 =- HsUnGuardedRhs (HsVar (jsonpbName "declareSchemaRef"))-- let match = HsMatch l declareIdentifier [] rightHandSide0 []-- let statement0 = HsLetStmt [ HsFunBind [ match ] ]-- let declareVariable = HsVar (UnQual declareIdentifier)-- let proxy = HsCon (proxyName "Proxy")-- let rightHandSide1 = HsApp declareVariable proxy-- let pattern = HsPVar (HsIdent qualifiedFieldName)-- let statement1 = HsGenerator l pattern rightHandSide1-- let inferenceStatements =- if null fieldNames then [] else [ HsLetStmt [ patternBind ] ]- where- arguments = [ toArgument fieldName ]-- rightHandSide =- HsUnGuardedRhs (applicativeApply (HsCon (UnQual constructor)) arguments)-- patternBind = HsPatBind l HsPWildCard rightHandSide []-- [ statement0, statement1 ] ++ inferenceStatements-- returnStatement = HsQualifier (HsApp returnE (HsParen namedSchema))-- let instanceDeclaration =- instDecl_ className [ classArgument ] [ classDeclaration ]- where- className = jsonpbName "ToSchema"-- classArgument = HsTyCon (UnQual (HsIdent messageName))-- classDeclaration = HsFunBind [ match ]- where- match = match_ matchName [ HsPWildCard ] rightHandSide []- where- expression = case maybeConstructors of- Nothing -> expressionForMessage- Just constructors -> expressionForOneOf constructors-- rightHandSide = HsUnGuardedRhs expression-- matchName = HsIdent "declareNamedSchema"- return instanceDeclaration---- ** Codegen bookkeeping helpers---- | Bookeeping for qualified fields-data QualifiedField = QualifiedField- { recordFieldName :: FieldName- , fieldInfo :: FieldInfo- } deriving Show---- | Bookkeeping for fields-data FieldInfo- = FieldOneOf OneofField- | FieldNormal FieldName FieldNumber DotProtoType [DotProtoOption]- deriving Show---- | Bookkeeping for oneof fields-data OneofField = OneofField- { oneofType :: String- , subfields :: [OneofSubfield]- } deriving Show---- | Bookkeeping for oneof subfields-data OneofSubfield = OneofSubfield- { subfieldNumber :: FieldNumber- , subfieldConsName :: String- , subfieldName :: FieldName- , subfieldType :: DotProtoType- , subfieldOptions :: [DotProtoOption]- } deriving Show--getQualifiedFields- :: MonadError CompileError m- => String -> [DotProtoMessagePart] -> m [QualifiedField]-getQualifiedFields msgName msgParts = fmap catMaybes . forM msgParts $ \case- DotProtoMessageField (DotProtoField fieldNum dpType fieldIdent options _) -> do- fieldName <- dpIdentUnqualName fieldIdent- qualName <- prefixedFieldName msgName fieldName- pure $ Just $- QualifiedField (coerce qualName) (FieldNormal (coerce fieldName) fieldNum dpType options)-- DotProtoMessageOneOf _ [] ->- throwError (InternalError "getQualifiedFields: encountered oneof with no oneof fields")-- DotProtoMessageOneOf oneofIdent fields -> do- ident <- dpIdentUnqualName oneofIdent- oneofName <- prefixedFieldName msgName ident- oneofTypeName <- prefixedConName msgName ident- fieldElems <- sequence- [ do s <- dpIdentUnqualName subFieldName- c <- prefixedConName oneofTypeName s- pure (OneofSubfield fieldNum c (coerce s) dpType options)- | DotProtoField fieldNum dpType subFieldName options _ <- fields- ]- pure $ Just $ QualifiedField (coerce oneofName) (FieldOneOf (OneofField ident fieldElems))-- _ ->- pure Nothing---- | Project qualified fields, given a projection function per field type.-onQF :: (FieldName -> FieldNumber -> a) -- ^ projection for normal fields- -> (OneofField -> a) -- ^ projection for oneof fields- -> QualifiedField- -> a-onQF f _ (QualifiedField _ (FieldNormal fldName fldNum _ _)) = f fldName fldNum-onQF _ g (QualifiedField _ (FieldOneOf fld)) = g fld--fieldBinder :: FieldNumber -> String-fieldBinder = ("f" ++) . show--oneofSubBinder :: OneofSubfield -> String-oneofSubBinder = fieldBinder . subfieldNumber--oneofSubDisjunctBinder :: [OneofSubfield] -> String-oneofSubDisjunctBinder = intercalate "_or_" . fmap oneofSubBinder---- ** Helpers to wrap/unwrap types for protobuf (de-)serialization--coerceE :: Bool -> HsType -> HsType -> Maybe HsExp-coerceE _ from to | from == to = Nothing-coerceE unsafe from to = Just $ HsApp (HsApp coerceF (typeApp from)) (typeApp to)- where- -- Do not add linebreaks to typeapps as that causes parse errors- pp = prettyPrintStyleMode style{mode=OneLineMode} defaultMode- typeApp ty = HsVar (UnQual (HsIdent ("@("++ pp ty ++ ")")))- coerceF | unsafe = HsVar (haskellName "unsafeCoerce")- | otherwise = HsVar (haskellName "coerce")--wrapE :: MonadError CompileError m => TypeContext -> [DotProtoOption] -> DotProtoType -> HsExp -> m HsExp-wrapE ctxt opts dpt e = maybe e (\f -> HsParen (HsApp (HsParen f) e)) <$>- (coerceE (isMap dpt) <$> dptToHsType ctxt dpt <*> dptToHsTypeWrapped opts ctxt dpt)--unwrapE :: MonadError CompileError m => TypeContext -> [DotProtoOption] -> DotProtoType -> HsExp -> m HsExp-unwrapE ctxt opts dpt e = maybe e (\f -> HsParen (HsApp (HsParen f) e)) <$>- (coerceE (isMap dpt) <$> overParser (dptToHsTypeWrapped opts ctxt dpt) <*> overParser (dptToHsType ctxt dpt))- where- overParser = fmap $ HsTyApp (HsTyVar (HsIdent "_"))--isMap :: DotProtoType -> Bool-isMap Map{} = True-isMap _ = False--internalError :: MonadError CompileError m => String -> m a-internalError = throwError . InternalError--invalidTypeNameError :: MonadError CompileError m => String -> m a-invalidTypeNameError = throwError . InvalidTypeName--_unimplementedError :: MonadError CompileError m => String -> m a-_unimplementedError = throwError . Unimplemented--invalidMethodNameError :: MonadError CompileError m => DotProtoIdentifier -> m a-invalidMethodNameError = throwError . InvalidMethodName--noSuchTypeError :: MonadError CompileError m => DotProtoIdentifier -> m a-noSuchTypeError = throwError. NoSuchType---- ** Generate types and instances for .proto enums--dotProtoEnumD- :: MonadError CompileError m- => DotProtoIdentifier- -> DotProtoIdentifier- -> [DotProtoEnumPart]- -> m [HsDecl]-dotProtoEnumD parentIdent enumIdent enumParts =- do enumName <- nestedTypeName parentIdent =<<- dpIdentUnqualName enumIdent-- enumCons <- sortBy (comparing fst) <$>- sequence [ (i,) . prefixedEnumFieldName enumName <$> dpIdentUnqualName conIdent- | DotProtoEnumField conIdent i _options <- enumParts ]-- let enumNameE = HsLit (HsString enumName)- -- TODO assert that there is more than one enumeration constructor- ((minEnumVal, maxEnumVal), enumConNames) = first (minimum &&& maximum) $ unzip enumCons-- boundsE = HsTuple- [ HsExpTypeSig l (intE minEnumVal) (HsQualType [] (HsTyCon (haskellName "Int")))- , intE maxEnumVal- ]-- toEnumD = toEnumDPatterns <> [ toEnumFailure ]- fromEnumD =- [ match_ (HsIdent "fromEnum") [ HsPApp (unqual_ conName) [] ]- (HsUnGuardedRhs (intE conIdx))- []- | (conIdx, conName) <- enumCons- ]- succD = zipWith succDPattern enumConNames (tail enumConNames) <> [ succFailure ]- predD = zipWith predDPattern (tail enumConNames) enumConNames <> [ predFailure ]-- toEnumDPatterns =- [ match_ (HsIdent "toEnum")- [ intP conIdx ]- (HsUnGuardedRhs (HsVar (unqual_ conName))) []- | (conIdx, conName) <- enumCons ]-- succDPattern thisCon nextCon =- match_ (HsIdent "succ") [ HsPApp (unqual_ thisCon) [] ]- (HsUnGuardedRhs (HsVar (unqual_ nextCon))) []- predDPattern thisCon prevCon =- match_ (HsIdent "pred") [ HsPApp (unqual_ thisCon) [] ]- (HsUnGuardedRhs (HsVar (unqual_ prevCon))) []-- toEnumFailure = match_ (HsIdent "toEnum") [ HsPVar (HsIdent "i") ]- (HsUnGuardedRhs- (apply toEnumErrorE [enumNameE , HsVar (unqual_ "i") , boundsE]))- []- succFailure = match_ (HsIdent "succ") [ HsPWildCard ]- (HsUnGuardedRhs (HsApp succErrorE enumNameE)) []- predFailure = match_ (HsIdent "pred") [ HsPWildCard ]- (HsUnGuardedRhs (HsApp predErrorE enumNameE)) []-- parseJSONPBDecls :: [HsMatch]- parseJSONPBDecls =- [ let pat nm =- HsPApp (jsonpbName "String")- [ HsPLit (HsString (fromMaybe <*> stripPrefix enumName $ nm)) ]- in- match_ (HsIdent "parseJSONPB") [pat conName]- (HsUnGuardedRhs- (HsApp pureE (HsVar (unqual_ conName))))- []- | conName <- enumConNames- ]- <> [ match_ (HsIdent "parseJSONPB") [patVar "v"]- (HsUnGuardedRhs- (apply (HsVar (jsonpbName "typeMismatch"))- [ HsLit (HsString enumName), HsVar (unqual_ "v") ]))- []- ]-- toJSONPBDecl =- match_ (HsIdent "toJSONPB") [ patVar "x", HsPWildCard ]- (HsUnGuardedRhs- (HsApp (HsVar (jsonpbName "enumFieldString"))- (HsVar (unqual_ "x"))))- []-- toEncodingPBDecl =- match_ (HsIdent "toEncodingPB") [ patVar "x", HsPWildCard ]- (HsUnGuardedRhs- (HsApp (HsVar (jsonpbName "enumFieldEncoding"))- (HsVar (unqual_ "x"))))- []-- pure [ dataDecl_ enumName- [ conDecl_ (HsIdent con) [] | con <- enumConNames ]- defaultEnumDeriving- , namedInstD enumName- , instDecl_ (haskellName "Enum") [ type_ enumName ]- [ HsFunBind toEnumD, HsFunBind fromEnumD- , HsFunBind succD, HsFunBind predD ]- , instDecl_ (jsonpbName "ToJSONPB") [ type_ enumName ]- [ HsFunBind [toJSONPBDecl]- , HsFunBind [toEncodingPBDecl]- ]- , instDecl_ (jsonpbName "FromJSONPB") [ type_ enumName ]- [ HsFunBind parseJSONPBDecls ]- -- Generate Aeson instances in terms of JSONPB instances- , toJSONInstDecl enumName- , fromJSONInstDecl enumName--#ifdef DHALL- -- Generate Dhall instances- , dhallInterpretInstDecl enumName- , dhallInjectInstDecl enumName-#endif-- -- And the Finite instance, used to infer a Swagger ToSchema instance- -- for this enumerated type.- , instDecl_ (protobufName "Finite") [ type_ enumName ] []- ]---- ** Generate code for dot proto services--dotProtoServiceD- :: MonadError CompileError m- => DotProtoIdentifier- -> TypeContext- -> DotProtoIdentifier- -> [DotProtoServicePart]- -> m [HsDecl]-dotProtoServiceD pkgIdent ctxt serviceIdent service = do- serviceNameUnqual <- dpIdentUnqualName serviceIdent- packageName <- dpIdentQualName pkgIdent-- serviceName <- typeLikeName serviceNameUnqual-- let endpointPrefix = "/" ++ packageName ++ "." ++ serviceName ++ "/"-- serviceFieldD (DotProtoServiceRPC- rpcName- (request, requestStreaming)- (response, responseStreaming)- _- ) = do- fullName <- prefixedFieldName serviceName =<<- dpIdentUnqualName rpcName-- methodName <- case rpcName of- Single nm -> pure nm- _ -> invalidMethodNameError rpcName-- requestTy <- dpptToHsType ctxt (Named request)- responseTy <- dpptToHsType ctxt (Named response)-- let streamingType =- case (requestStreaming, responseStreaming) of- (Streaming, Streaming) -> biDiStreamingC- (Streaming, NonStreaming) -> clientStreamingC- (NonStreaming, Streaming) -> serverStreamingC- (NonStreaming, NonStreaming) -> normalC-- pure [ ( endpointPrefix ++ methodName- , fullName, requestStreaming, responseStreaming- , HsUnBangedTy $- HsTyFun (tyApp (HsTyVar (HsIdent "request")) [streamingType, requestTy, responseTy])- (tyApp ioT [tyApp (HsTyVar (HsIdent "response")) [streamingType, responseTy]])- )- ]-- serviceFieldD _ = pure []-- fieldsD <- mconcat <$> mapM serviceFieldD service-- serverFuncName <- prefixedFieldName serviceName "server"- clientFuncName <- prefixedFieldName serviceName "client"-- let conDecl = recDecl_ (HsIdent serviceName)- [ ([HsIdent hsName], ty) | (_, hsName, _, _, ty) <- fieldsD ]-- serverT = tyApp (HsTyCon (unqual_ serviceName))- [ serverRequestT, serverResponseT ]-- serviceServerTypeD = HsTypeSig l [ HsIdent serverFuncName ]- (HsQualType [] (HsTyFun serverT (HsTyFun serviceOptionsC ioActionT)))-- serviceServerD =- let serverFuncD =- match_ (HsIdent serverFuncName)- [ HsPRec (unqual_ serviceName)- [ HsPFieldPat (unqual_ methodName)- (HsPVar (HsIdent methodName))- | (_, methodName, _, _, _) <- fieldsD- ]- , HsPApp (unqual_ "ServiceOptions")- [ patVar "serverHost"- , patVar "serverPort"- , patVar "useCompression"- , patVar "userAgentPrefix"- , patVar "userAgentSuffix"- , patVar "initialMetadata"- , patVar "sslConfig"- , patVar "logger"- ]- ]- (HsUnGuardedRhs (apply serverLoopE [ serverOptsE ]))- []-- handlerE handlerC adapterE methodName hsName =- apply handlerC [ apply methodNameC [ HsLit (HsString methodName) ]- , apply adapterE [ HsVar (unqual_ hsName) ]- ]-- update u v = HsFieldUpdate (unqual_ u) (HsVar (unqual_ v))-- serverOptsE = HsRecUpdate defaultOptionsE- [ HsFieldUpdate (grpcName "optNormalHandlers")- (HsList [ handlerE unaryHandlerC convertServerHandlerE endpointName hsName- | (endpointName, hsName, NonStreaming, NonStreaming, _) <- fieldsD- ]- )-- , HsFieldUpdate (grpcName "optClientStreamHandlers")- (HsList [ handlerE clientStreamHandlerC convertServerReaderHandlerE endpointName hsName- | (endpointName, hsName, Streaming, NonStreaming, _) <- fieldsD- ]- )-- , HsFieldUpdate (grpcName "optServerStreamHandlers")- (HsList [ handlerE serverStreamHandlerC convertServerWriterHandlerE endpointName hsName- | (endpointName, hsName, NonStreaming, Streaming, _) <- fieldsD- ]- )-- , HsFieldUpdate (grpcName "optBiDiStreamHandlers")- (HsList [ handlerE biDiStreamHandlerC convertServerRWHandlerE endpointName hsName- | (endpointName, hsName, Streaming, Streaming, _) <- fieldsD- ]- )- , update "optServerHost" "serverHost"- , update "optServerPort" "serverPort"- , update "optUseCompression" "useCompression"- , update "optUserAgentPrefix" "userAgentPrefix"- , update "optUserAgentSuffix" "userAgentSuffix"- , update "optInitialMetadata" "initialMetadata"- , update "optSSLConfig" "sslConfig"- , update "optLogger" "logger"- ]- in- HsFunBind [serverFuncD]-- clientT = tyApp (HsTyCon (unqual_ serviceName)) [ clientRequestT, clientResultT ]-- serviceClientTypeD =- HsTypeSig l [ HsIdent clientFuncName ]- (HsQualType [] (HsTyFun grpcClientT (HsTyApp ioT clientT)))-- serviceClientD =- let clientFuncD = match_ (HsIdent clientFuncName)- [ HsPVar (HsIdent "client") ]- ( HsUnGuardedRhs clientRecE ) []-- clientRecE = foldl (\f -> HsInfixApp f apOp)- (apply pureE [ HsVar (unqual_ serviceName) ])- [ HsParen $ HsInfixApp clientRequestE' apOp (registerClientMethodE endpointName)- | (endpointName, _, _, _, _) <- fieldsD- ]-- clientRequestE' = apply pureE [ apply clientRequestE [ HsVar (unqual_ "client") ] ]-- registerClientMethodE endpoint =- apply clientRegisterMethodE [ HsVar (unqual_ "client")- , apply methodNameC [ HsLit (HsString endpoint) ]- ]- in- HsFunBind [ clientFuncD ]-- pure [ HsDataDecl l [] (HsIdent serviceName)- [ HsIdent "request", HsIdent "response" ]- [ conDecl ] defaultServiceDeriving-- , serviceServerTypeD- , serviceServerD-- , serviceClientTypeD- , serviceClientD- ]---- * Common Haskell expressions, constructors, and operators--dotProtoFieldC, primC, optionalC, repeatedC, nestedRepeatedC, namedC, mapC,- fieldNumberC, singleC, dotsC, pathC, nestedC, anonymousC, dotProtoOptionC,- identifierC, stringLitC, intLitC, floatLitC, boolLitC, trueC, falseC,- unaryHandlerC, clientStreamHandlerC, serverStreamHandlerC, biDiStreamHandlerC,- methodNameC, nothingC, justC, forceEmitC, mconcatE, encodeMessageFieldE,- fromStringE, decodeMessageFieldE, pureE, returnE, memptyE, msumE, atE, oneofE,- succErrorE, predErrorE, toEnumErrorE, fmapE, defaultOptionsE, serverLoopE,- convertServerHandlerE, convertServerReaderHandlerE, convertServerWriterHandlerE,- convertServerRWHandlerE, clientRegisterMethodE, clientRequestE :: HsExp--dotProtoFieldC = HsVar (protobufName "DotProtoField")-primC = HsVar (protobufName "Prim")-optionalC = HsVar (protobufName "Optional")-repeatedC = HsVar (protobufName "Repeated")-nestedRepeatedC = HsVar (protobufName "NestedRepeated")-namedC = HsVar (protobufName "Named")-mapC = HsVar (protobufName "Map")-fieldNumberC = HsVar (protobufName "FieldNumber")-singleC = HsVar (protobufName "Single")-pathC = HsVar (protobufName "Path")-dotsC = HsVar (protobufName "Dots")-nestedC = HsVar (protobufName "Nested")-anonymousC = HsVar (protobufName "Anonymous")-dotProtoOptionC = HsVar (protobufName "DotProtoOption")-identifierC = HsVar (protobufName "Identifier")-stringLitC = HsVar (protobufName "StringLit")-intLitC = HsVar (protobufName "IntLit")-floatLitC = HsVar (protobufName "FloatLit")-boolLitC = HsVar (protobufName "BoolLit")-forceEmitC = HsVar (protobufName "ForceEmit")-encodeMessageFieldE = HsVar (protobufName "encodeMessageField")-decodeMessageFieldE = HsVar (protobufName "decodeMessageField")-atE = HsVar (protobufName "at")-oneofE = HsVar (protobufName "oneof")--trueC = HsVar (haskellName "True")-falseC = HsVar (haskellName "False")-nothingC = HsVar (haskellName "Nothing")-justC = HsVar (haskellName "Just")-mconcatE = HsVar (haskellName "mconcat")-fromStringE = HsVar (haskellName "fromString")-pureE = HsVar (haskellName "pure")-returnE = HsVar (haskellName "return")-memptyE = HsVar (haskellName "mempty")-msumE = HsVar (haskellName "msum")-succErrorE = HsVar (haskellName "succError")-predErrorE = HsVar (haskellName "predError")-toEnumErrorE = HsVar (haskellName "toEnumError")-fmapE = HsVar (haskellName "fmap")--unaryHandlerC = HsVar (grpcName "UnaryHandler")-clientStreamHandlerC = HsVar (grpcName "ClientStreamHandler")-serverStreamHandlerC = HsVar (grpcName "ServerStreamHandler")-biDiStreamHandlerC = HsVar (grpcName "BiDiStreamHandler")-methodNameC = HsVar (grpcName "MethodName")-defaultOptionsE = HsVar (grpcName "defaultOptions")-serverLoopE = HsVar (grpcName "serverLoop")-convertServerHandlerE = HsVar (grpcName "convertGeneratedServerHandler")-convertServerReaderHandlerE = HsVar (grpcName "convertGeneratedServerReaderHandler")-convertServerWriterHandlerE = HsVar (grpcName "convertGeneratedServerWriterHandler")-convertServerRWHandlerE = HsVar (grpcName "convertGeneratedServerRWHandler")-clientRegisterMethodE = HsVar (grpcName "clientRegisterMethod")-clientRequestE = HsVar (grpcName "clientRequest")--biDiStreamingC, serverStreamingC, clientStreamingC, normalC, serviceOptionsC,- ioActionT, serverRequestT, serverResponseT, clientRequestT, clientResultT,- ioT, grpcClientT :: HsType-biDiStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "BiDiStreaming"))-serverStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "ServerStreaming"))-clientStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "ClientStreaming"))-normalC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "Normal"))-serviceOptionsC = HsTyCon (Qual (Module "HsGRPC") (HsIdent "ServiceOptions"))-serverRequestT = HsTyCon (grpcName "ServerRequest")-serverResponseT = HsTyCon (grpcName "ServerResponse")-clientRequestT = HsTyCon (grpcName "ClientRequest")-clientResultT = HsTyCon (grpcName "ClientResult")-grpcClientT = HsTyCon (grpcName "Client")-ioActionT = tyApp ioT [ HsTyTuple [] ]-ioT = HsTyCon (haskellName "IO")--apOp :: HsQOp-apOp = HsQVarOp (UnQual (HsSymbol "<*>"))--fmapOp :: HsQOp-fmapOp = HsQVarOp (UnQual (HsSymbol "<$>"))--composeOp :: HsQOp-composeOp = HsQVarOp (Qual haskellNS (HsSymbol "."))--bindOp :: HsQOp-bindOp = HsQVarOp (Qual haskellNS (HsSymbol ">>="))--altOp :: HsQOp-altOp = HsQVarOp (UnQual (HsSymbol "<|>"))--toJSONPBOp :: HsQOp-toJSONPBOp = HsQVarOp (UnQual (HsSymbol ".="))--parseJSONPBOp :: HsQOp-parseJSONPBOp = HsQVarOp (UnQual (HsSymbol ".:"))--intE :: Integral a => a -> HsExp-intE x = (if x < 0 then HsParen else id) . HsLit . HsInt . fromIntegral $ x--intP :: Integral a => a -> HsPat-intP x = (if x < 0 then HsPParen else id) . HsPLit . HsInt . fromIntegral $ x---- ** Expressions for protobuf-wire types--forceEmitE :: HsExp -> HsExp-forceEmitE = HsParen . HsApp forceEmitC--fieldNumberE :: FieldNumber -> HsExp-fieldNumberE = HsParen . HsApp fieldNumberC . intE . getFieldNumber--maybeE :: (a -> HsExp) -> Maybe a -> HsExp-maybeE _ Nothing = nothingC-maybeE f (Just a) = HsApp justC (f a)--dpIdentE :: DotProtoIdentifier -> HsExp-dpIdentE (Single n) = apply singleC [ HsLit (HsString n) ]-dpIdentE (Dots (Path ns)) = apply dotsC [apply pathC [ HsList (map (HsLit . HsString) ns) ] ]-dpIdentE (Qualified a b) = apply nestedC [ dpIdentE a, dpIdentE b ]-dpIdentE Anonymous = anonymousC--dpValueE :: DotProtoValue -> HsExp-dpValueE (Identifier nm) = apply identifierC [ dpIdentE nm ]-dpValueE (StringLit s) = apply stringLitC [ HsLit (HsString s) ]-dpValueE (IntLit i) = apply intLitC [ HsLit (HsInt (fromIntegral i)) ]-dpValueE (FloatLit f) = apply floatLitC [ HsLit (HsFrac (toRational f)) ]-dpValueE (BoolLit True) = apply boolLitC [ trueC ]-dpValueE (BoolLit False) = apply boolLitC [ falseC ]--optionE :: DotProtoOption -> HsExp-optionE (DotProtoOption name value) =- apply dotProtoOptionC [ dpIdentE name, dpValueE value ]---- | Translate a dot proto type to its Haskell AST type-dpTypeE :: DotProtoType -> HsExp-dpTypeE (Prim p) = apply primC [ dpPrimTypeE p ]-dpTypeE (Optional p) = apply optionalC [ dpPrimTypeE p ]-dpTypeE (Repeated p) = apply repeatedC [ dpPrimTypeE p ]-dpTypeE (NestedRepeated p) = apply nestedRepeatedC [ dpPrimTypeE p ]-dpTypeE (Map k v) = apply mapC [ dpPrimTypeE k, dpPrimTypeE v]----- | Translate a dot proto primitive type to a Haskell AST primitive type.-dpPrimTypeE :: DotProtoPrimType -> HsExp-dpPrimTypeE ty =- let wrap = HsVar . protobufName in- case ty of- Named n -> apply namedC [ dpIdentE n ]-- Int32 -> wrap "Int32"- Int64 -> wrap "Int64"- SInt32 -> wrap "SInt32"- SInt64 -> wrap "SInt64"- UInt32 -> wrap "UInt32"- UInt64 -> wrap "UInt64"- Fixed32 -> wrap "Fixed32"- Fixed64 -> wrap "Fixed64"- SFixed32 -> wrap "SFixed32"- SFixed64 -> wrap "SFixed64"- String -> wrap "String"- Bytes -> wrap "Bytes"- Bool -> wrap "Bool"- Float -> wrap "Float"- Double -> wrap "Double"--defaultImports :: Bool -> [HsImportDecl]-defaultImports usesGrpc =- [ importDecl_ preludeM True (Just haskellNS) Nothing--#ifdef DHALL- , importDecl_ proto3SuiteDhallPBM True (Just (Module hsDhallPB)) Nothing-#endif-- , importDecl_ dataProtobufWireDotProtoM True (Just protobufNS) Nothing- , importDecl_ dataProtobufWireTypesM True (Just protobufNS) Nothing- , importDecl_ dataProtobufWireClassM True (Just protobufNS) Nothing- , importDecl_ proto3SuiteJSONPBM True (Just jsonpbNS) Nothing- , importDecl_ proto3SuiteJSONPBM False Nothing- (Just (False, [ HsIAbs (HsSymbol ".=")- , HsIAbs (HsSymbol ".:")- ]- )- )- , importDecl_ proto3WireM True (Just protobufNS) Nothing- , importDecl_ controlApplicativeM False Nothing- (Just (False, [ HsIAbs (HsSymbol "<*>")- , HsIAbs (HsSymbol "<|>")- , HsIAbs (HsSymbol "<$>")- ]- )- )- , importDecl_ controlApplicativeM True (Just haskellNS) Nothing- , importDecl_ controlDeepSeqM True (Just haskellNS) Nothing- , importDecl_ controlMonadM True (Just haskellNS) Nothing- , importDecl_ dataTextM True- (Just haskellNS) (Just (False, [ importSym "Text" ]))- , importDecl_ dataByteStringM True (Just haskellNS) Nothing- , importDecl_ dataCoerceM True (Just haskellNS) Nothing- , importDecl_ dataStringM True (Just haskellNS)- (Just (False, [ importSym "fromString" ]))- , importDecl_ dataVectorM True (Just haskellNS)- (Just (False, [ importSym "Vector" ]))- , importDecl_ dataMapM True (Just haskellNS)- (Just (False, [ importSym "Map", importSym "mapKeysMonotonic" ]))- , importDecl_ dataIntM True (Just haskellNS)- (Just (False, [ importSym "Int16", importSym "Int32", importSym "Int64" ]))- , importDecl_ dataWordM True (Just haskellNS)- (Just (False, [ importSym "Word16", importSym "Word32", importSym "Word64" ]))- , importDecl_ dataProxy True (Just proxyNS) Nothing- , importDecl_ ghcGenericsM True (Just haskellNS) Nothing- , importDecl_ ghcEnumM True (Just haskellNS) Nothing- , importDecl_ unsafeCoerceM True (Just haskellNS) Nothing- ]- <>- if usesGrpc- then [ importDecl_ networkGrpcHighLevelGeneratedM False (Just grpcNS) Nothing- , importDecl_ networkGrpcHighLevelClientM False (Just grpcNS) Nothing- , importDecl_ networkGrpcHighLevelServerM False (Just grpcNS)- (Just (True, [ importSym "serverLoop" ]))- , importDecl_ networkGrpcHighLevelServerUnregM False (Just grpcNS)- (Just (False, [ importSym "serverLoop" ]))- ]- else []- where- preludeM = Module "Prelude"- dataProtobufWireDotProtoM = Module "Proto3.Suite.DotProto"- dataProtobufWireClassM = Module "Proto3.Suite.Class"- dataProtobufWireTypesM = Module "Proto3.Suite.Types"- proto3SuiteJSONPBM = Module "Proto3.Suite.JSONPB"- proto3WireM = Module "Proto3.Wire"- controlApplicativeM = Module "Control.Applicative"- controlDeepSeqM = Module "Control.DeepSeq"- controlMonadM = Module "Control.Monad"- dataCoerceM = Module "Data.Coerce"- dataTextM = Module "Data.Text.Lazy"- dataByteStringM = Module "Data.ByteString"- dataStringM = Module "Data.String"- dataIntM = Module "Data.Int"- dataVectorM = Module "Data.Vector"- dataMapM = Module "Data.Map"- dataWordM = Module "Data.Word"- dataProxy = Module "Data.Proxy"- ghcGenericsM = Module "GHC.Generics"- ghcEnumM = Module "GHC.Enum"- unsafeCoerceM = Module "Unsafe.Coerce"- networkGrpcHighLevelGeneratedM = Module "Network.GRPC.HighLevel.Generated"- networkGrpcHighLevelServerM = Module "Network.GRPC.HighLevel.Server"- networkGrpcHighLevelClientM = Module "Network.GRPC.HighLevel.Client"- networkGrpcHighLevelServerUnregM = Module "Network.GRPC.HighLevel.Server.Unregistered"--#ifdef DHALL- proto3SuiteDhallPBM = Module "Proto3.Suite.DhallPB"-#endif-- grpcNS = Module "HsGRPC"- jsonpbNS = Module "HsJSONPB"- protobufNS = Module "HsProtobuf"- proxyNS = Module "Proxy"-- importSym = HsIAbs . HsIdent--haskellNS :: Module-haskellNS = Module "Hs"--defaultMessageDeriving :: [HsQName]-defaultMessageDeriving = map haskellName [ "Show", "Eq", "Ord", "Generic", "NFData" ]--defaultEnumDeriving :: [HsQName]-defaultEnumDeriving = map haskellName [ "Show", "Bounded", "Eq", "Ord", "Generic", "NFData" ]--defaultServiceDeriving :: [HsQName]-defaultServiceDeriving = map haskellName [ "Generic" ]---- * Wrappers around haskell-src-exts constructors--apply :: HsExp -> [HsExp] -> HsExp-apply f = HsParen . foldl HsApp f--applicativeApply :: HsExp -> [HsExp] -> HsExp-applicativeApply f = foldl snoc nil- where- nil = HsApp pureE f-- snoc g x = HsInfixApp g apOp x--tyApp :: HsType -> [HsType] -> HsType-tyApp = foldl HsTyApp--module_ :: Module -> Maybe [HsExportSpec] -> [HsImportDecl] -> [HsDecl] -> HsModule-module_ = HsModule l--importDecl_ :: Module -> Bool -> Maybe Module -> Maybe (Bool, [HsImportSpec]) -> HsImportDecl-importDecl_ = HsImportDecl l--dataDecl_ :: String -> [HsConDecl] -> [HsQName] -> HsDecl-dataDecl_ messageName = HsDataDecl l [] (HsIdent messageName) []--recDecl_ :: HsName -> [([HsName], HsBangType)] -> HsConDecl-recDecl_ = HsRecDecl l--conDecl_ :: HsName -> [HsBangType] -> HsConDecl-conDecl_ = HsConDecl l--instDecl_ :: HsQName -> [HsType] -> [HsDecl] -> HsDecl-instDecl_ = HsInstDecl l []--match_ :: HsName -> [HsPat] -> HsRhs -> [HsDecl] -> HsMatch-match_ = HsMatch l--unqual_ :: String -> HsQName-unqual_ = UnQual . HsIdent--protobufType_, primType_ :: String -> HsType-protobufType_ = HsTyCon . protobufName-primType_ = HsTyCon . haskellName--type_ :: String -> HsType-type_ = HsTyCon . unqual_--patVar :: String -> HsPat-patVar = HsPVar . HsIdent--alt_ :: HsPat -> HsGuardedAlts -> [HsDecl] -> HsAlt-alt_ = HsAlt l+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ViewPatterns #-}++{-| This module provides functions to generate Haskell declarations for protobuf+ messages+-}++module Proto3.Suite.DotProto.Generate+ ( CompileError(..)+ , TypeContext+ , CompileArgs(..)+ , compileDotProtoFile+ , compileDotProtoFileOrDie+ , hsModuleForDotProto+ , renderHsModuleForDotProto+ , readDotProtoWithContext+ ) where++import Control.Applicative+import Control.Lens ((&), ix, over, has, filtered)+import Control.Monad.Except+import Data.Char+import Data.Coerce+import Data.Either (partitionEithers)+import Data.List (find, intercalate, nub, sortBy, stripPrefix)+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Monoid+import Data.Ord (comparing)+import qualified Data.Set as S+import Data.String (fromString)+import qualified Data.Text as T+import Filesystem.Path.CurrentOS ((</>), (<.>))+import qualified Filesystem.Path.CurrentOS as FP+import Language.Haskell.Parser (ParseResult(..), parseModule)+import Language.Haskell.Pretty+import Language.Haskell.Syntax+import qualified NeatInterpolation as Neat+import Prelude hiding (FilePath)+import Proto3.Suite.DotProto+import Proto3.Suite.DotProto.AST.Lens+import Proto3.Suite.DotProto.Internal+import Proto3.Suite.DotProto.Rendering (Pretty(..))+import Proto3.Wire.Types (FieldNumber (..))+import System.IO (writeFile, readFile)+import qualified Turtle+import Turtle (FilePath)+++--+-- * Public interface+--++data CompileArgs = CompileArgs+ { includeDir :: [FilePath]+ , extraInstanceFiles :: [FilePath]+ , inputProto :: FilePath+ , outputDir :: FilePath+ }++-- | Generate a Haskell module corresponding to a @.proto@ file+compileDotProtoFile :: CompileArgs -> IO (Either CompileError ())+compileDotProtoFile CompileArgs{..} = runExceptT $ do+ (dotProto, importTypeContext) <- readDotProtoWithContext includeDir inputProto++ modulePathPieces <- traverse typeLikeName . components . metaModulePath . protoMeta $ dotProto++ let relativePath = FP.concat (map fromString $ NE.toList modulePathPieces) <.> "hs"+ let modulePath = outputDir </> relativePath++ Turtle.mktree (Turtle.directory modulePath)++ extraInstances <- foldMapM getExtraInstances extraInstanceFiles++ haskellModule <- renderHsModuleForDotProto extraInstances dotProto importTypeContext++ liftIO (writeFile (FP.encodeString modulePath) haskellModule)++-- | As 'compileDotProtoFile', except terminates the program with an error+-- message on failure.+compileDotProtoFileOrDie :: CompileArgs -> IO ()+compileDotProtoFileOrDie args = compileDotProtoFile args >>= \case+ Left e -> do+ -- TODO: pretty print the error messages+ let errText = Turtle.format Turtle.w e+ let dotProtoPathText = Turtle.format Turtle.fp (inputProto args)+ dieLines [Neat.text|+ Error: failed to compile "${dotProtoPathText}":++ ${errText}+ |]+ _ -> pure ()++-- | Compile a 'DotProto' AST into a 'String' representing the Haskell+-- source of a module implementing types and instances for the .proto+-- messages and enums.+renderHsModuleForDotProto+ :: MonadError CompileError m+ => ([HsImportDecl],[HsDecl]) -> DotProto -> TypeContext -> m String+renderHsModuleForDotProto extraInstanceFiles dotProto importCtxt = do+ haskellModule <- hsModuleForDotProto extraInstanceFiles dotProto importCtxt+ return (T.unpack header ++ prettyPrint haskellModule)+ where+ header = [Neat.text|+ {-# LANGUAGE DeriveGeneric #-}+ {-# LANGUAGE DeriveAnyClass #-}+ {-# LANGUAGE DataKinds #-}+ {-# LANGUAGE GADTs #-}+ {-# LANGUAGE TypeApplications #-}+ {-# LANGUAGE OverloadedStrings #-}+ {-# OPTIONS_GHC -fno-warn-unused-imports #-}+ {-# OPTIONS_GHC -fno-warn-name-shadowing #-}+ {-# OPTIONS_GHC -fno-warn-unused-matches #-}++ -- | Generated by Haskell protocol buffer compiler. DO NOT EDIT!+ |]++-- | Compile a Haskell module AST given a 'DotProto' package AST.+-- Instances given in @eis@ override those otherwise generated.+hsModuleForDotProto+ :: MonadError CompileError m+ => ([HsImportDecl], [HsDecl])+ -- ^ Extra user-define instances that override default generated instances+ -> DotProto+ -- ^+ -> TypeContext+ -- ^+ -> m HsModule+hsModuleForDotProto+ (extraImports, extraInstances)+ dotProto@DotProto{ protoMeta = DotProtoMeta { metaModulePath = modulePath }+ , protoPackage+ , protoDefinitions+ }+ importTypeContext+ = do+ packageIdentifier <- protoPackageName protoPackage+ moduleName <- modulePathModName modulePath++ typeContextImports <- ctxtImports importTypeContext++ let hasService = has (traverse._DotProtoService) protoDefinitions++ let importDeclarations =+ concat [ defaultImports hasService, extraImports, typeContextImports ]++ typeContext <- dotProtoTypeContext dotProto++ let toDotProtoDeclaration =+ dotProtoDefinitionD packageIdentifier (typeContext <> importTypeContext)++ let extraInstances' = instancesForModule moduleName extraInstances++ decls <- replaceHsInstDecls extraInstances' <$>+ foldMapM toDotProtoDeclaration protoDefinitions++ return (module_ moduleName Nothing importDeclarations decls)++getExtraInstances+ :: (MonadIO m, MonadError CompileError m)+ => FilePath -> m ([HsImportDecl], [HsDecl])+getExtraInstances extraInstanceFile = do++ contents <- liftIO (readFile (FP.encodeString extraInstanceFile))++ case parseModule contents of+ ParseOk (HsModule _srcloc _mod _es idecls decls) -> do+ let isInstDecl HsInstDecl{} = True+ isInstDecl _ = False++ return (idecls, filter isInstDecl decls) --TODO give compile result++ ParseFailed srcLoc err -> do+ let srcLocText = Turtle.format Turtle.w srcLoc++ let errText = T.pack err++ let message = [Neat.text|+ Error: Failed to parse instance file++ ${srcLocText}: ${errText}+ |]++ internalError (T.unpack message)++-- | This very specific function will only work for the qualification on the very first type+-- in the object of an instance declaration. Those are the only sort of instance declarations+-- generated within this code, so it suffices.+instancesForModule :: Module -> [HsDecl] -> [HsDecl]+instancesForModule m = foldr go []+ where go x xs = case x of+ HsInstDecl a b c (HsTyCon (Qual tm i):ts) d ->+ if m == tm then HsInstDecl a b c (HsTyCon (UnQual i):ts) d:xs else xs+ _ -> xs++-- | For each thing in @base@ replaces it if it finds a matching @override@+replaceHsInstDecls :: [HsDecl] -> [HsDecl] -> [HsDecl]+replaceHsInstDecls overrides base = concatMap mbReplace base+ where+ -- instances defined separately from data type definition:+ mbReplace hid@(HsInstDecl _ _ qn tys _) =+ (: []) . fromMaybe hid $ search qn tys++ -- instances listed in "deriving" clause of data type definition:+ mbReplace (HsDataDecl loc ctx tyn names def insts) =+ let (uncustomized, customized) = partitionEithers (map (deriv tyn) insts)+ in HsDataDecl loc ctx tyn names def uncustomized : customized++ -- irrelevant declarations remain unchanged:+ mbReplace hid = [hid]++ deriv tyn qn = maybe (Left qn) Right $ search qn [HsTyCon (UnQual tyn)]++ search qn tys = find (\x -> Just (unQual qn,tys) == getSig x) overrides++ getSig (HsInstDecl _ _ qn tys _) = Just (unQual qn,tys)+ getSig _ = Nothing++ unQual (Qual _ n) = Just n+ unQual (UnQual n) = Just n+ unQual (Special _) = Nothing++-- | Parses the file at the given path and produces an AST along with a+-- 'TypeContext' representing all types from imported @.proto@ files, using the+-- first parameter as a list of paths to search for imported files. Terminates+-- with exit code 1 when an included file cannot be found in the search path.+readDotProtoWithContext+ :: (MonadError CompileError m, MonadIO m)+ => [FilePath]+ -> FilePath+ -> m (DotProto, TypeContext)+readDotProtoWithContext [] toplevelProto = do+ -- If we're not given a search path, default to using the current working+ -- directory, as `protoc` does+ cwd <- Turtle.pwd+ readDotProtoWithContext [cwd] toplevelProto++readDotProtoWithContext searchPaths toplevelProto = do+ dp <- importProto searchPaths toplevelProto toplevelProto+ let importIt = readImportTypeContext searchPaths toplevelProto (S.singleton toplevelProto)+ tc <- foldMapM importIt (protoImports dp)+ pure (dp, tc)++-- | Build the type context for an import, resolving transitive imports.+readImportTypeContext+ :: (MonadError CompileError m, MonadIO m)+ => [FilePath]+ -> FilePath+ -> S.Set FilePath+ -> DotProtoImport+ -> m TypeContext+readImportTypeContext searchPaths toplevelFP alreadyRead (DotProtoImport _ path)+ | path `S.member` alreadyRead = throwError (CircularImport path)+ | otherwise = do+ import_ <- importProto searchPaths toplevelFP path+ importPkg <- protoPackageName (protoPackage import_)++ let fixImportTyInfo tyInfo =+ tyInfo { dotProtoTypeInfoPackage = DotProtoPackageSpec importPkg+ , dotProtoTypeInfoModulePath = metaModulePath . protoMeta $ import_+ }+ importTypeContext <- fmap fixImportTyInfo <$> dotProtoTypeContext import_++ qualifiedTypeContext <- mapKeysM (concatDotProtoIdentifier importPkg) importTypeContext++ let isPublic (DotProtoImport q _) = q == DotProtoImportPublic+ transitiveImportsTC <-+ foldMapOfM (traverse . filtered isPublic)+ (readImportTypeContext searchPaths toplevelFP (S.insert path alreadyRead))+ (protoImports import_)++ pure $ importTypeContext <> qualifiedTypeContext <> transitiveImportsTC++-- | Given a type context, generates the Haskell import statements necessary+-- to import all the required types.+ctxtImports :: MonadError CompileError m => TypeContext -> m [HsImportDecl]+ctxtImports = fmap (map mkImport . nub)+ . traverse (modulePathModName . dotProtoTypeInfoModulePath)+ . M.elems+ where+ mkImport modName = importDecl_ modName True Nothing Nothing++--------------------------------------------------------------------------------+--+-- * Helper functions for Haskell code generation+--++-- ** Names++-- | Generate the Haskell type name for a 'DotProtoTypeInfo' for a message /+-- enumeration being compiled. NB: We ignore the 'dotProtoTypeInfoPackage'+-- field of the 'DotProtoTypeInfo' parameter, instead demanding that we have+-- been provided with a valid module path in its 'dotProtoTypeInfoModulePath'+-- field. The latter describes the name of the Haskell module being generated.+msgTypeFromDpTypeInfo :: MonadError CompileError m+ => DotProtoTypeInfo -> DotProtoIdentifier -> m HsType+msgTypeFromDpTypeInfo DotProtoTypeInfo{..} ident = do+ modName <- modulePathModName dotProtoTypeInfoModulePath+ identName <- qualifiedMessageName dotProtoTypeInfoParent ident+ pure $ HsTyCon (Qual modName (HsIdent identName))++haskellName, jsonpbName, grpcName, protobufName, proxyName :: String -> HsQName+haskellName name = Qual (Module "Hs") (HsIdent name)+jsonpbName name = Qual (Module "HsJSONPB") (HsIdent name)+grpcName name = Qual (Module "HsGRPC") (HsIdent name)+protobufName name = Qual (Module "HsProtobuf") (HsIdent name)+proxyName name = Qual (Module "Proxy") (HsIdent name)++modulePathModName :: MonadError CompileError m => Path -> m Module+modulePathModName (Path comps) = Module . intercalate "." <$> traverse typeLikeName (NE.toList comps)++_pkgIdentModName :: MonadError CompileError m => DotProtoIdentifier -> m Module+_pkgIdentModName (Single s) = Module <$> typeLikeName s+_pkgIdentModName (Dots path) = modulePathModName path+_pkgIdentModName x = throwError (InvalidPackageName x)+++-- ** Dhall++#ifdef DHALL+hsDhallPB :: String+hsDhallPB = "HsDhallPb"++dhallPBName :: String -> HsQName+dhallPBName name = Qual (Module hsDhallPB) (HsIdent name)++-- *** Generate Dhall Interpret and Inject generic instances++dhallInterpretInstDecl :: String -> HsDecl+dhallInterpretInstDecl typeName =+ instDecl_ (dhallPBName "Interpret")+ [ type_ typeName ]+ [ ]++dhallInjectInstDecl :: String -> HsDecl+dhallInjectInstDecl typeName =+ instDecl_ (dhallPBName "Inject")+ [ type_ typeName ]+ [ ]+#endif++-- ** Helpers to wrap/unwrap types for protobuf (de-)serialization++coerceE :: Bool -> HsType -> HsType -> Maybe HsExp+coerceE _ from to | from == to = Nothing+coerceE unsafe from to = Just $ HsApp (HsApp coerceF (typeApp from)) (typeApp to)+ where+ -- Do not add linebreaks to typeapps as that causes parse errors+ pp = prettyPrintStyleMode style{mode=OneLineMode} defaultMode+ typeApp ty = uvar_ ("@("++ pp ty ++ ")")+ coerceF | unsafe = HsVar (haskellName "unsafeCoerce")+ | otherwise = HsVar (haskellName "coerce")++wrapE :: MonadError CompileError m => TypeContext -> [DotProtoOption] -> DotProtoType -> HsExp -> m HsExp+wrapE ctxt opts dpt e = maybe e (\f -> apply f [e]) <$>+ (coerceE (isMap dpt) <$> dptToHsType ctxt dpt <*> dptToHsTypeWrapped opts ctxt dpt)++unwrapE :: MonadError CompileError m => TypeContext -> [DotProtoOption] -> DotProtoType -> HsExp -> m HsExp+unwrapE ctxt opts dpt e = maybe e (\f -> apply f [e]) <$>+ (coerceE (isMap dpt) <$> overParser (dptToHsTypeWrapped opts ctxt dpt) <*> overParser (dptToHsType ctxt dpt))+ where+ overParser = fmap $ HsTyApp (HsTyVar (HsIdent "_"))+++--------------------------------------------------------------------------------+--+-- * Functions to convert 'DotProtoType' into Haskell types+--++-- | Convert a dot proto type to a Haskell type+dptToHsType :: MonadError CompileError m => TypeContext -> DotProtoType -> m HsType+dptToHsType = foldDPT dptToHsContType dpptToHsType++-- | Convert a dot proto type to a wrapped Haskell type+dptToHsTypeWrapped :: MonadError CompileError m => [DotProtoOption] -> TypeContext -> DotProtoType -> m HsType+dptToHsTypeWrapped opts =+ foldDPT+ -- The wrapper for the collection type replaces the native haskell+ -- collection type, so try that first.+ (\ctxt ty -> maybe (dptToHsContType ctxt ty) id (dptToHsWrappedContType ctxt opts ty))+ -- Always wrap the primitive type.+ (\ctxt ty -> dpptToHsTypeWrapper ty <$> dpptToHsType ctxt ty)++foldDPT :: MonadError CompileError m+ => (TypeContext -> DotProtoType -> HsType -> HsType)+ -> (TypeContext -> DotProtoPrimType -> m HsType)+ -> TypeContext+ -> DotProtoType+ -> m HsType+foldDPT dptToHsCont foldPrim ctxt dpt =+ let+ prim = foldPrim ctxt+ go = foldDPT dptToHsCont foldPrim ctxt+ cont = dptToHsCont ctxt dpt+ in+ case dpt of+ Prim pType -> cont <$> prim pType+ Optional pType -> cont <$> prim pType+ Repeated pType -> cont <$> prim pType+ NestedRepeated pType -> cont <$> prim pType+ Map k v | validMapKey k -> HsTyApp . cont <$> prim k <*> go (Prim v) -- need to 'Nest' message types+ | otherwise -> throwError $ InvalidMapKeyType (show $ pPrint k)++-- | Translate DotProtoType constructors to wrapped Haskell container types+-- (for Message serde instances).+dptToHsWrappedContType :: TypeContext -> [DotProtoOption] -> DotProtoType -> Maybe (HsType -> HsType)+dptToHsWrappedContType ctxt opts = \case+ Prim (Named tyName)+ | isMessage ctxt tyName -> Just $ HsTyApp (protobufType_ "Nested")+ Repeated (Named tyName)+ | isMessage ctxt tyName -> Just $ HsTyApp (protobufType_ "NestedVec")+ Repeated ty+ | isUnpacked opts -> Just $ HsTyApp (protobufType_ "UnpackedVec")+ | isPacked opts -> Just $ HsTyApp (protobufType_ "PackedVec")+ | isPackable ctxt ty -> Just $ HsTyApp (protobufType_ "PackedVec")+ | otherwise -> Just $ HsTyApp (protobufType_ "UnpackedVec")+ _ -> Nothing++-- | Translate DotProtoType to Haskell container types.+dptToHsContType :: TypeContext -> DotProtoType -> HsType -> HsType+dptToHsContType ctxt = \case+ Prim (Named tyName) | isMessage ctxt tyName+ -> HsTyApp $ primType_ "Maybe"+ Optional _ -> HsTyApp $ primType_ "Maybe"+ Repeated _ -> HsTyApp $ primType_ "Vector"+ NestedRepeated _ -> HsTyApp $ primType_ "Vector"+ Map _ _ -> HsTyApp $ primType_ "Map"+ _ -> id++-- | Haskell wrapper for primitive dot proto types+dpptToHsTypeWrapper :: DotProtoPrimType -> HsType -> HsType+dpptToHsTypeWrapper = \case+ SInt32 -> HsTyApp (protobufType_ "Signed")+ SInt64 -> HsTyApp (protobufType_ "Signed")+ SFixed32 -> HsTyApp (protobufType_ "Signed") . HsTyApp (protobufType_ "Fixed")+ SFixed64 -> HsTyApp (protobufType_ "Signed") . HsTyApp (protobufType_ "Fixed")+ Fixed32 -> HsTyApp (protobufType_ "Fixed")+ Fixed64 -> HsTyApp (protobufType_ "Fixed")+ _ -> id++-- | Convert a dot proto prim type to an unwrapped Haskell type+dpptToHsType :: MonadError CompileError m => TypeContext -> DotProtoPrimType -> m HsType+dpptToHsType ctxt = \case+ Int32 -> pure $ primType_ "Int32"+ Int64 -> pure $ primType_ "Int64"+ SInt32 -> pure $ primType_ "Int32"+ SInt64 -> pure $ primType_ "Int64"+ UInt32 -> pure $ primType_ "Word32"+ UInt64 -> pure $ primType_ "Word64"+ Fixed32 -> pure $ primType_ "Word32"+ Fixed64 -> pure $ primType_ "Word64"+ SFixed32 -> pure $ primType_ "Int32"+ SFixed64 -> pure $ primType_ "Int64"+ String -> pure $ primType_ "Text"+ Bytes -> pure $ primType_ "ByteString"+ Bool -> pure $ primType_ "Bool"+ Float -> pure $ primType_ "Float"+ Double -> pure $ primType_ "Double"+ Named msgName ->+ case M.lookup msgName ctxt of+ Just ty@(DotProtoTypeInfo { dotProtoTypeInfoKind = DotProtoKindEnum }) ->+ HsTyApp (protobufType_ "Enumerated") <$> msgTypeFromDpTypeInfo ty msgName+ Just ty -> msgTypeFromDpTypeInfo ty msgName+ Nothing -> noSuchTypeError msgName+++validMapKey :: DotProtoPrimType -> Bool+validMapKey = (`elem` [ Int32, Int64, SInt32, SInt64, UInt32, UInt64+ , Fixed32, Fixed64, SFixed32, SFixed64+ , String, Bool])+++--------------------------------------------------------------------------------+--+-- * Code generation+--++-- ** Generate instances for a 'DotProto' package++dotProtoDefinitionD :: MonadError CompileError m+ => DotProtoIdentifier -> TypeContext -> DotProtoDefinition -> m [HsDecl]+dotProtoDefinitionD pkgIdent ctxt = \case+ DotProtoMessage _ messageName messageParts ->+ dotProtoMessageD ctxt Anonymous messageName messageParts++ DotProtoEnum _ enumName enumParts ->+ dotProtoEnumD Anonymous enumName enumParts++ DotProtoService _ serviceName serviceParts ->+ dotProtoServiceD pkgIdent ctxt serviceName serviceParts++-- | Generate 'Named' instance for a type in this package+namedInstD :: String -> HsDecl+namedInstD messageName =+ instDecl_ (protobufName "Named")+ [ type_ messageName ]+ [ HsFunBind [nameOfDecl] ]+ where+ nameOfDecl = match_ (HsIdent "nameOf") [HsPWildCard]+ (HsUnGuardedRhs (apply fromStringE+ [ str_ messageName ]))+ []++hasDefaultInstD :: String -> HsDecl+hasDefaultInstD messageName =+ instDecl_ (protobufName "HasDefault")+ [ type_ messageName ]+ [ ]++-- ** Generate types and instances for .proto messages++-- | Generate data types, 'Bounded', 'Enum', 'FromJSONPB', 'Named', 'Message',+-- 'ToJSONPB' instances as appropriate for the given 'DotProtoMessagePart's+dotProtoMessageD+ :: forall m+ . MonadError CompileError m+ => TypeContext+ -> DotProtoIdentifier+ -> DotProtoIdentifier+ -> [DotProtoMessagePart]+ -> m [HsDecl]+dotProtoMessageD ctxt parentIdent messageIdent messageParts = do+ messageName <- qualifiedMessageName parentIdent messageIdent++ let mkDataDecl flds =+ dataDecl_ messageName+ [ recDecl_ (HsIdent messageName) flds ]+ defaultMessageDeriving++ let getName = \case+ DotProtoMessageField fld -> [dotProtoFieldName fld]+ DotProtoMessageOneOf ident _ -> [ident]+ _ -> []++ foldMapM id+ [ sequence+ [ mkDataDecl <$> foldMapM (messagePartFieldD messageName) messageParts+ , pure (namedInstD messageName)+ , pure (hasDefaultInstD messageName)+ , messageInstD ctxt' parentIdent messageIdent messageParts++ , toJSONPBMessageInstD ctxt' parentIdent messageIdent messageParts+ , fromJSONPBMessageInstD ctxt' parentIdent messageIdent messageParts++ -- Generate Aeson instances in terms of JSONPB instances+ , pure (toJSONInstDecl messageName)+ , pure (fromJSONInstDecl messageName)++ -- And the Swagger ToSchema instance corresponding to JSONPB encodings+ , toSchemaInstanceDeclaration messageName Nothing+ =<< foldMapM (traverse dpIdentUnqualName . getName) messageParts++#ifdef DHALL+ -- Generate Dhall instances+ , pure (dhallInterpretInstDecl messageName)+ , pure (dhallInjectInstDecl messageName)+#endif+ ]++ -- Nested regular and oneof message decls+ , foldMapOfM (traverse . _DotProtoMessageDefinition)+ nestedDecls+ messageParts++ , foldMapOfM (traverse . _DotProtoMessageOneOf)+ (uncurry $ nestedOneOfDecls messageName)+ messageParts+ ]++ where+ ctxt' :: TypeContext+ ctxt' = maybe mempty dotProtoTypeChildContext (M.lookup messageIdent ctxt)+ <> ctxt++ messagePartFieldD :: String -> DotProtoMessagePart -> m [([HsName], HsBangType)]+ messagePartFieldD messageName (DotProtoMessageField DotProtoField{..}) = do+ fullName <- prefixedFieldName messageName =<< dpIdentUnqualName dotProtoFieldName+ fullTy <- dptToHsType ctxt' dotProtoFieldType+ pure [ ([HsIdent fullName], HsUnBangedTy fullTy ) ]++ messagePartFieldD messageName (DotProtoMessageOneOf fieldName _) = do+ fullName <- prefixedFieldName messageName =<< dpIdentUnqualName fieldName+ qualTyName <- prefixedConName messageName =<< dpIdentUnqualName fieldName+ let fullTy = HsTyApp (HsTyCon (haskellName "Maybe")) . type_ $ qualTyName+ pure [ ([HsIdent fullName], HsUnBangedTy fullTy) ]++ messagePartFieldD _ _ = pure []++ nestedDecls :: DotProtoDefinition -> m [HsDecl]+ nestedDecls (DotProtoMessage _ subMsgName subMessageDef) = do+ parentIdent' <- concatDotProtoIdentifier parentIdent messageIdent+ dotProtoMessageD ctxt' parentIdent' subMsgName subMessageDef++ nestedDecls (DotProtoEnum _ subEnumName subEnumDef) = do+ parentIdent' <- concatDotProtoIdentifier parentIdent messageIdent+ dotProtoEnumD parentIdent' subEnumName subEnumDef++ nestedDecls _ = pure []++ nestedOneOfDecls :: String -> DotProtoIdentifier -> [DotProtoField] -> m [HsDecl]+ nestedOneOfDecls messageName identifier fields = do+ fullName <- prefixedConName messageName =<< dpIdentUnqualName identifier++ (cons, idents) <- fmap unzip (mapM (oneOfCons fullName) fields)++ toSchemaInstance <- toSchemaInstanceDeclaration fullName (Just idents)+ =<< mapM (dpIdentUnqualName . dotProtoFieldName) fields++ pure [ dataDecl_ fullName cons defaultMessageDeriving+ , namedInstD fullName+ , toSchemaInstance++#ifdef DHALL+ , dhallInterpretInstDecl fullName+ , dhallInjectInstDecl fullName+#endif+ ]++ oneOfCons :: String -> DotProtoField -> m (HsConDecl, HsName)+ oneOfCons fullName DotProtoField{..} = do+ consTy <- case dotProtoFieldType of+ Prim msg@(Named msgName)+ | isMessage ctxt' msgName+ -> -- Do not wrap message summands with Maybe.+ dpptToHsType ctxt' msg++ _ -> dptToHsType ctxt' dotProtoFieldType++ consName <- prefixedConName fullName =<< dpIdentUnqualName dotProtoFieldName+ let ident = HsIdent consName+ pure (conDecl_ ident [HsUnBangedTy consTy], ident)++ oneOfCons _ DotProtoEmptyField = internalError "field type : empty field"++-- *** Generate Protobuf 'Message' instances++messageInstD+ :: forall m+ . MonadError CompileError m+ => TypeContext+ -> DotProtoIdentifier+ -> DotProtoIdentifier+ -> [DotProtoMessagePart]+ -> m HsDecl+messageInstD ctxt parentIdent msgIdent messageParts = do+ msgName <- qualifiedMessageName parentIdent msgIdent+ qualifiedFields <- getQualifiedFields msgName messageParts++ encodedFields <- mapM encodeMessageField qualifiedFields+ decodedFields <- mapM decodeMessageField qualifiedFields++ let encodeMessageDecl = match_ (HsIdent "encodeMessage")+ [HsPWildCard, HsPRec (unqual_ msgName) punnedFieldsP]+ (HsUnGuardedRhs encodeMessageE) []++ encodeMessageE = apply mconcatE [HsList encodedFields]++ punnedFieldsP = map (fp . coerce . recordFieldName) qualifiedFields+ where fp nm = HsPFieldPat (unqual_ nm) (HsPVar (HsIdent nm))+++ let decodeMessageDecl = match_ (HsIdent "decodeMessage") [ HsPWildCard ]+ (HsUnGuardedRhs decodeMessageE) []++ decodeMessageE = foldl (\f -> HsInfixApp f apOp)+ (apply pureE [ uvar_ msgName ])+ decodedFields++ let dotProtoDecl = match_ (HsIdent "dotProto") [HsPWildCard]+ (HsUnGuardedRhs dotProtoE) []++ dotProtoE = HsList $ do+ DotProtoMessageField DotProtoField{..} <- messageParts+ pure $ apply dotProtoFieldC+ [ fieldNumberE dotProtoFieldNumber+ , dpTypeE dotProtoFieldType+ , dpIdentE dotProtoFieldName+ , HsList (map optionE dotProtoFieldOptions)+ , str_ dotProtoFieldComment+ ]+++ pure $ instDecl_ (protobufName "Message")+ [ type_ msgName ]+ [ HsFunBind [ encodeMessageDecl ]+ , HsFunBind [ decodeMessageDecl ]+ , HsFunBind [ dotProtoDecl ]+ ]+ where+ encodeMessageField :: QualifiedField -> m HsExp+ encodeMessageField QualifiedField{recordFieldName, fieldInfo} =+ let recordFieldName' = uvar_ (coerce recordFieldName) in+ case fieldInfo of+ FieldNormal _fieldName fieldNum dpType options -> do+ fieldE <- wrapE ctxt options dpType recordFieldName'+ pure $ apply encodeMessageFieldE [ fieldNumberE fieldNum, fieldE ]++ FieldOneOf OneofField{subfields} -> do+ alts <- mapM mkAlt subfields+ pure $ HsCase recordFieldName'+ [ alt_ (HsPApp (haskellName "Nothing") [])+ (HsUnGuardedAlt memptyE)+ []+ , alt_ (HsPApp (haskellName "Just") [patVar "x"])+ (HsUnGuardedAlt (HsCase (uvar_ "x") alts))+ []+ ]+ where+ -- Create all pattern match & expr for each constructor:+ -- Constructor y -> encodeMessageField num (Nested (Just y)) -- for embedded messages+ -- Constructor y -> encodeMessageField num (ForceEmit y) -- for everything else+ mkAlt (OneofSubfield fieldNum conName _ dpType options) = do+ let isMaybe+ | Prim (Named tyName) <- dpType+ = isMessage ctxt tyName+ | otherwise+ = False++ let wrapJust = HsParen . HsApp (HsVar (haskellName "Just"))++ xE <- (if isMaybe then id else fmap forceEmitE)+ . wrapE ctxt options dpType+ . (if isMaybe then wrapJust else id)+ $ uvar_ "y"++ pure $ alt_ (HsPApp (unqual_ conName) [patVar "y"])+ (HsUnGuardedAlt (apply encodeMessageFieldE [fieldNumberE fieldNum, xE]))+ []+++ decodeMessageField :: QualifiedField -> m HsExp+ decodeMessageField QualifiedField{fieldInfo} =+ case fieldInfo of+ FieldNormal _fieldName fieldNum dpType options ->+ unwrapE ctxt options dpType $ apply atE [ decodeMessageFieldE, fieldNumberE fieldNum ]++ FieldOneOf OneofField{subfields} -> do+ parsers <- mapM subfieldParserE subfields+ pure $ apply oneofE [ HsVar (haskellName "Nothing")+ , HsList parsers+ ]+ where+ -- create a list of (fieldNumber, Cons <$> parser)+ subfieldParserE (OneofSubfield fieldNumber consName _ dpType options) = do+ let fE | Prim (Named tyName) <- dpType, isMessage ctxt tyName+ = HsParen (HsApp fmapE (uvar_ consName))+ | otherwise+ = HsParen (HsInfixApp (HsVar (haskellName "Just"))+ composeOp+ (uvar_ consName))++ alts <- unwrapE ctxt options dpType decodeMessageFieldE++ pure $ HsTuple+ [ fieldNumberE fieldNumber+ , HsInfixApp (apply pureE [ fE ]) apOp alts+ ]+++-- *** Generate ToJSONPB/FromJSONPB instances++toJSONPBMessageInstD+ :: MonadError CompileError m+ => TypeContext+ -> DotProtoIdentifier+ -> DotProtoIdentifier+ -> [DotProtoMessagePart]+ -> m HsDecl+toJSONPBMessageInstD _ctxt parentIdent msgIdent messageParts = do+ msgName <- qualifiedMessageName parentIdent msgIdent+ qualFields <- getQualifiedFields msgName messageParts++ let applyE nm oneofNm =+ apply (HsVar (jsonpbName nm))+ [ HsList (foldQF defPairE (oneofCaseE oneofNm) <$> qualFields) ]++ let patBinder = foldQF (const fieldBinder) (oneofSubDisjunctBinder . subfields)+ let matchE nm appNm oneofAppNm =+ match_+ (HsIdent nm)+ [ HsPApp (unqual_ msgName)+ (patVar . patBinder <$> qualFields) ]+ (HsUnGuardedRhs (applyE appNm oneofAppNm))+ []++ pure $ instDecl_ (jsonpbName "ToJSONPB")+ [ type_ msgName ]+ [ HsFunBind [matchE "toJSONPB" "object" "objectOrNull"]+ , HsFunBind [matchE "toEncodingPB" "pairs" "pairsOrNull" ]+ ]++ where+ -- E.g.+ -- "another" .= f2 -- always succeeds (produces default value on missing field)+ defPairE fldName fldNum =+ HsInfixApp (str_ (coerce fldName))+ toJSONPBOp+ (uvar_ (fieldBinder fldNum))++ -- E.g.+ -- HsJSONPB.pair "name" f4 -- fails on missing field+ pairE fldNm varNm =+ apply (HsVar (jsonpbName "pair"))+ [ str_ (coerce fldNm) , uvar_ varNm]++ -- Suppose we have a sum type Foo, nested inside a message Bar.+ -- We want to generate the following:+ --+ -- > toJSONPB (Bar foo more stuff) =+ -- > HsJSONPB.object+ -- > [ (let encodeFoo = (<case expr scrutinising foo> :: Options -> Value)+ -- > in \option -> if optEmitNamedOneof option+ -- > then ("Foo" .= (PB.objectOrNull [encodeFoo] option)) option+ -- > else encodeFoo option+ -- > )+ -- > , <encode more>+ -- > , <encode stuff>+ -- > ]+ oneofCaseE retJsonCtor (OneofField typeName subfields) =+ HsParen+ $ HsLet [ HsFunBind [ match_ (HsIdent caseName) [] (HsUnGuardedRhs caseExpr) [] ] ]+ $ HsLambda l [patVar optsStr] (HsIf dontInline noInline yesInline)+ where+ optsStr = "options"+ opts = uvar_ optsStr++ caseName = "encode" <> over (ix 0) toUpper typeName+ caseBnd = uvar_ caseName++ dontInline = HsApp (HsVar (jsonpbName "optEmitNamedOneof")) opts++ noInline = HsApp (HsParen (HsInfixApp (str_ typeName)+ toJSONPBOp+ (apply (HsVar (jsonpbName retJsonCtor))+ [ HsList [caseBnd], opts ])))+ opts++ yesInline = HsApp caseBnd opts+++ -- E.g.+ -- case f4_or_f9 of+ -- Just (SomethingPickOneName f4)+ -- -> HsJSONPB.pair "name" f4+ -- Just (SomethingPickOneSomeid f9)+ -- -> HsJSONPB.pair "someid" f9+ -- Nothing+ -- -> mempty+ caseExpr = HsParen $+ HsCase disjunctName (altEs <> [fallthroughE])+ where+ disjunctName = uvar_ (oneofSubDisjunctBinder subfields)+ altEs = do+ sub@(OneofSubfield _ conName pbFldNm _ _) <- subfields+ let patVarNm = oneofSubBinder sub+ pure $ alt_ (HsPApp (haskellName "Just")+ [ HsPParen+ (HsPApp (unqual_ conName) [patVar patVarNm])+ ]+ )+ (HsUnGuardedAlt (pairE pbFldNm patVarNm))+ []+ fallthroughE =+ alt_ (HsPApp (haskellName "Nothing") [])+ (HsUnGuardedAlt memptyE)+ []++fromJSONPBMessageInstD+ :: MonadError CompileError m+ => TypeContext+ -> DotProtoIdentifier+ -> DotProtoIdentifier+ -> [DotProtoMessagePart]+ -> m HsDecl+fromJSONPBMessageInstD _ctxt parentIdent msgIdent messageParts = do+ msgName <- qualifiedMessageName parentIdent msgIdent+ qualFields <- getQualifiedFields msgName messageParts++ let parseJSONPBE =+ apply (HsVar (jsonpbName "withObject"))+ [ str_ msgName+ , HsParen (HsLambda l [lambdaPVar] fieldAps)+ ]+ where+ fieldAps = foldl (\f -> HsInfixApp f apOp)+ (apply pureE [ uvar_ msgName ])+ (foldQF normalParserE oneofParserE <$> qualFields)++ let parseJSONPBDecl =+ match_ (HsIdent "parseJSONPB") [] (HsUnGuardedRhs parseJSONPBE) []++ pure (instDecl_ (jsonpbName "FromJSONPB")+ [ type_ msgName ]+ [ HsFunBind [ parseJSONPBDecl ] ])+ where+ lambdaPVar = patVar "obj"+ lambdaVar = uvar_ "obj"++ -- E.g., for message+ -- message Something { oneof name_or_id { string name = _; int32 someid = _; } }+ --+ -- ==>+ --+ -- (let parseSomethingNameOrId parseObj = <FUNCTION, see tryParseDisjunctsE>+ -- in ((obj .: "nameOrId") Hs.>>=+ -- (HsJSONPB.withObject "nameOrId" parseSomethingNameOrId))+ -- <|>+ -- (parseSomethingNameOrId obj)+ -- )+ oneofParserE (OneofField oneofType fields) =+ HsParen $+ HsLet [ HsFunBind [ match_ (HsIdent letBndStr) [patVar letArgStr ]+ (HsUnGuardedRhs tryParseDisjunctsE) []+ ]+ ]+ (HsInfixApp parseWrapped altOp parseUnwrapped)+ where+ oneofTyLit = str_ oneofType -- FIXME++ letBndStr = "parse" <> over (ix 0) toUpper oneofType+ letBndName = uvar_ letBndStr+ letArgStr = "parseObj"+ letArgName = uvar_ letArgStr++ parseWrapped = HsParen $+ HsInfixApp (HsParen (HsInfixApp lambdaVar parseJSONPBOp oneofTyLit))+ bindOp+ (apply (HsVar (jsonpbName "withObject")) [ oneofTyLit , letBndName ])++ parseUnwrapped = HsParen (HsApp letBndName lambdaVar)++ -- parseSomethingNameOrId parseObj =+ -- Hs.msum+ -- [ (Just . SomethingPickOneName) <$> (HsJSONPB.parseField parseObj "name")+ -- , (Just . SomethingPickOneSomeid) <$> (HsJSONPB.parseField parseObj "someid")+ -- , pure Nothing+ -- ]+ tryParseDisjunctsE =+ HsApp msumE (HsList (map subParserE fields <> fallThruE))+ where+ fallThruE+ = [ HsApp pureE (HsVar (haskellName "Nothing")) ]+ subParserE OneofSubfield{subfieldConsName, subfieldName}+ = HsInfixApp+ (HsInfixApp (HsVar (haskellName "Just"))+ composeOp+ (uvar_ subfieldConsName))+ fmapOp+ (apply (HsVar (jsonpbName "parseField"))+ [ letArgName+ , str_ (coerce subfieldName)])++ -- E.g. obj .: "someid"+ normalParserE fldNm _ =+ HsInfixApp lambdaVar+ parseJSONPBOp+ (str_(coerce fldNm))++-- *** Generate default Aeson To/FromJSON and Swagger ToSchema instances+-- (These are defined in terms of ToJSONPB)++toJSONInstDecl :: String -> HsDecl+toJSONInstDecl typeName =+ instDecl_ (jsonpbName "ToJSON")+ [ type_ typeName ]+ [ HsFunBind [ match_ (HsIdent "toJSON") []+ (HsUnGuardedRhs (HsVar (jsonpbName "toAesonValue"))) []+ ]+ , HsFunBind [ match_ (HsIdent "toEncoding") []+ (HsUnGuardedRhs (HsVar (jsonpbName "toAesonEncoding"))) []+ ]+ ]++fromJSONInstDecl :: String -> HsDecl+fromJSONInstDecl typeName =+ instDecl_ (jsonpbName "FromJSON")+ [ type_ typeName ]+ [ HsFunBind [match_ (HsIdent "parseJSON") []+ (HsUnGuardedRhs (HsVar (jsonpbName "parseJSONPB"))) []+ ]+ ]+++-- *** Generate `ToSchema` instance++toSchemaInstanceDeclaration+ :: MonadError CompileError m+ => String+ -- ^ Name of the message type to create an instance for+ -> Maybe [HsName]+ -- ^ Oneof constructors+ -> [String]+ -- ^ Field names+ -> m HsDecl+toSchemaInstanceDeclaration messageName maybeConstructors fieldNames = do+ qualifiedFieldNames <- mapM (prefixedFieldName messageName) fieldNames++ let messageConstructor = HsCon (UnQual (HsIdent messageName))++ let _namedSchemaNameExpression = HsApp justC (str_ messageName)++ -- { _paramSchemaType = HsJSONPB.SwaggerObject+ -- }+ let paramSchemaUpdates =+ [ HsFieldUpdate _paramSchemaType _paramSchemaTypeExpression+ ]+ where+ _paramSchemaType = jsonpbName "_paramSchemaType"++#if MIN_VERSION_swagger2(2,4,0)+ _paramSchemaTypeExpression = HsApp justC (HsVar (jsonpbName "SwaggerObject"))+#else+ _paramSchemaTypeExpression = HsVar (jsonpbName "SwaggerObject")+#endif++ let _schemaParamSchemaExpression = HsRecUpdate memptyE paramSchemaUpdates++ -- [ ("fieldName0", qualifiedFieldName0)+ -- , ("fieldName1", qualifiedFieldName1)+ -- ...+ -- ]+ let properties = HsList $ do+ (fieldName, qualifiedFieldName) <- zip fieldNames qualifiedFieldNames+ return (HsTuple [ str_ fieldName, uvar_ qualifiedFieldName ])++ let _schemaPropertiesExpression =+ HsApp (HsVar (jsonpbName "insOrdFromList")) properties++ -- { _schemaParamSchema = ...+ -- , _schemaProperties = ...+ -- , ...+ -- }+ let schemaUpdates = normalUpdates ++ extraUpdates+ where+ normalUpdates =+ [ HsFieldUpdate _schemaParamSchema _schemaParamSchemaExpression+ , HsFieldUpdate _schemaProperties _schemaPropertiesExpression+ ]++ extraUpdates =+ case maybeConstructors of+ Just _ ->+ [ HsFieldUpdate _schemaMinProperties justOne+ , HsFieldUpdate _schemaMaxProperties justOne+ ]+ Nothing ->+ []++ _schemaParamSchema = jsonpbName "_schemaParamSchema"+ _schemaProperties = jsonpbName "_schemaProperties"+ _schemaMinProperties = jsonpbName "_schemaMinProperties"+ _schemaMaxProperties = jsonpbName "_schemaMaxProperties"++ justOne = HsApp justC (HsLit (HsInt 1))++ let _namedSchemaSchemaExpression = HsRecUpdate memptyE schemaUpdates++ -- { _namedSchemaName = ...+ -- , _namedSchemaSchema = ...+ -- }+ let namedSchemaUpdates =+ [ HsFieldUpdate _namedSchemaName _namedSchemaNameExpression+ , HsFieldUpdate _namedSchemaSchema _namedSchemaSchemaExpression+ ]+ where+ _namedSchemaName = jsonpbName "_namedSchemaName"+ _namedSchemaSchema = jsonpbName "_namedSchemaSchema"++ let namedSchema = HsRecConstr (jsonpbName "NamedSchema") namedSchemaUpdates++ let toDeclareName fieldName = "declare_" ++ fieldName++ let toArgument fieldName = HsApp asProxy declare+ where+ declare = uvar_ (toDeclareName fieldName)++ asProxy = HsVar (jsonpbName "asProxy")++ -- do let declare_fieldName0 = HsJSONPB.declareSchemaRef+ -- qualifiedFieldName0 <- declare_fieldName0 Proxy.Proxy+ -- let declare_fieldName1 = HsJSONPB.declareSchemaRef+ -- qualifiedFieldName1 <- declare_fieldName1 Proxy.Proxy+ -- ...+ -- let _ = pure MessageName <*> HsJSONPB.asProxy declare_fieldName0 <*> HsJSONPB.asProxy declare_fieldName1 <*> ...+ -- return (...)+ let expressionForMessage =+ HsDo (bindingStatements ++ inferenceStatement ++ [ returnStatement ])+ where+ bindingStatements = do+ (fieldName, qualifiedFieldName) <- zip fieldNames qualifiedFieldNames++ let declareIdentifier = HsIdent (toDeclareName fieldName)++ let stmt0 = HsLetStmt [ HsFunBind+ [ HsMatch l declareIdentifier []+ (HsUnGuardedRhs (HsVar (jsonpbName "declareSchemaRef"))) []+ ]+ ]++ let stmt1 = HsGenerator l (HsPVar (HsIdent qualifiedFieldName))+ (HsApp (HsVar (UnQual declareIdentifier))+ (HsCon (proxyName "Proxy")))+ [ stmt0, stmt1]+++ inferenceStatement =+ if null fieldNames then [] else [ HsLetStmt [ patternBind ] ]+ where+ arguments = map toArgument fieldNames++ patternBind = HsPatBind l HsPWildCard+ (HsUnGuardedRhs (applicativeApply messageConstructor arguments)) []++ returnStatement = HsQualifier (HsApp returnE (HsParen namedSchema))++ -- do let declare_fieldName0 = HsJSONPB.declareSchemaRef+ -- let _ = pure ConstructorName0 <*> HsJSONPB.asProxy declare_fieldName0+ -- qualifiedFieldName0 <- declare_fieldName0 Proxy.Proxy+ -- let declare_fieldName1 = HsJSONPB.declareSchemaRef+ -- let _ = pure ConstructorName1 <*> HsJSONPB.asProxy declare_fieldName1+ -- qualifiedFieldName1 <- declare_fieldName1 Proxy.Proxy+ -- ...+ -- return (...)+ let expressionForOneOf constructors =+ HsDo (bindingStatements ++ [ returnStatement ])+ where+ bindingStatements = do+ (fieldName, qualifiedFieldName, constructor)+ <- zip3 fieldNames qualifiedFieldNames constructors++ let declareIdentifier = HsIdent (toDeclareName fieldName)++ let stmt0 = HsLetStmt [ HsFunBind+ [ HsMatch l declareIdentifier []+ (HsUnGuardedRhs (HsVar (jsonpbName "declareSchemaRef"))) []+ ]+ ]+ let stmt1 = HsGenerator l (HsPVar (HsIdent qualifiedFieldName))+ (HsApp (HsVar (UnQual declareIdentifier))+ (HsCon (proxyName "Proxy")))+ let inferenceStatement =+ if null fieldNames then [] else [ HsLetStmt [ patternBind ] ]+ where+ arguments = [ toArgument fieldName ]++ patternBind = HsPatBind l HsPWildCard+ (HsUnGuardedRhs (applicativeApply (HsCon (UnQual constructor)) arguments)) []++ [stmt0, stmt1] ++ inferenceStatement+++ returnStatement = HsQualifier (HsApp returnE (HsParen namedSchema))++ let instanceDeclaration =+ instDecl_ className [ classArgument ] [ classDeclaration ]+ where+ className = jsonpbName "ToSchema"++ classArgument = HsTyCon (UnQual (HsIdent messageName))++ classDeclaration = HsFunBind [ match ]+ where+ match = match_ matchName [ HsPWildCard ] rightHandSide []+ where+ expression = case maybeConstructors of+ Nothing -> expressionForMessage+ Just constructors -> expressionForOneOf constructors++ rightHandSide = HsUnGuardedRhs expression++ matchName = HsIdent "declareNamedSchema"++ return instanceDeclaration+++-- ** Generate types and instances for .proto enums++dotProtoEnumD+ :: MonadError CompileError m+ => DotProtoIdentifier+ -> DotProtoIdentifier+ -> [DotProtoEnumPart]+ -> m [HsDecl]+dotProtoEnumD parentIdent enumIdent enumParts = do+ enumName <- qualifiedMessageName parentIdent enumIdent++ let enumeratorDecls =+ [ (i, conIdent) | DotProtoEnumField conIdent i _options <- enumParts ]++ case enumeratorDecls of+ [] -> throwError $ EmptyEnumeration enumName+ (i, conIdent) : _+ | i == 0 -> return ()+ | otherwise -> throwError $ NonzeroFirstEnumeration enumName conIdent i++ enumCons <- fmap (sortBy (comparing fst)) $+ traverse (traverse+ (fmap (prefixedEnumFieldName enumName) . dpIdentUnqualName))+ enumeratorDecls++ let enumConNames = map snd enumCons++ minBoundD =+ [ match_ (HsIdent "minBound")+ []+ (HsUnGuardedRhs (uvar_ (head enumConNames)))+ []+ ]++ maxBoundD =+ [ match_ (HsIdent "maxBound")+ []+ (HsUnGuardedRhs (uvar_ (last enumConNames)))+ []+ ]++ compareD =+ [ match_ (HsIdent "compare")+ [ patVar "x", patVar "y" ]+ (HsUnGuardedRhs+ (HsApp+ (HsApp+ (HsVar (haskellName "compare"))+ (HsParen+ (HsApp (HsVar(protobufName "fromProtoEnum"))+ (uvar_ "x")+ )+ )+ )+ (HsParen+ (HsApp (HsVar (protobufName "fromProtoEnum"))+ (uvar_ "y")+ )+ )+ )+ )+ []+ ]++ fromProtoEnumD =+ [ match_ (HsIdent "fromProtoEnum") [ HsPApp (unqual_ conName) [] ]+ (HsUnGuardedRhs (intE conIdx))+ []+ | (conIdx, conName) <- enumCons+ ]++ toProtoEnumMayD =+ [ match_ (HsIdent "toProtoEnumMay")+ [ intP conIdx ]+ (HsUnGuardedRhs (HsApp justC (uvar_ conName)))+ []+ | (conIdx, conName) <- enumCons ] +++ [ match_ (HsIdent "toProtoEnumMay")+ [ HsPWildCard ]+ (HsUnGuardedRhs nothingC)+ []+ ]++ parseJSONPBDecls :: [HsMatch]+ parseJSONPBDecls = foldr ((:) . matchConName) [mismatch] enumConNames+ where+ matchConName conName = match_ (HsIdent "parseJSONPB") [pat conName]+ (HsUnGuardedRhs+ (HsApp pureE (uvar_ conName)))+ []++ pat nm = HsPApp (jsonpbName "String") [ HsPLit (HsString (tryStripEnumName nm)) ]++ tryStripEnumName = fromMaybe <*> stripPrefix enumName++ mismatch = match_ (HsIdent "parseJSONPB") [patVar "v"]+ (HsUnGuardedRhs+ (apply (HsVar (jsonpbName "typeMismatch"))+ [ str_ enumName, uvar_ "v" ]))+ []+++ toJSONPBDecl =+ match_ (HsIdent "toJSONPB") [ patVar "x", HsPWildCard ]+ (HsUnGuardedRhs+ (HsApp (HsVar (jsonpbName "enumFieldString"))+ (uvar_ "x")))+ []++ toEncodingPBDecl =+ match_ (HsIdent "toEncodingPB") [ patVar "x", HsPWildCard ]+ (HsUnGuardedRhs+ (HsApp (HsVar (jsonpbName "enumFieldEncoding"))+ (uvar_ "x")))+ []++ pure [ dataDecl_ enumName+ [ conDecl_ (HsIdent con) [] | con <- enumConNames ]+ defaultEnumDeriving+ , namedInstD enumName+ , hasDefaultInstD enumName+ , instDecl_ (haskellName "Bounded") [ type_ enumName ]+ [ HsFunBind minBoundD+ , HsFunBind maxBoundD+ ]+ , instDecl_ (haskellName "Ord") [ type_ enumName ]+ [ HsFunBind compareD ]+ , instDecl_ (protobufName "ProtoEnum") [ type_ enumName ]+ [ HsFunBind toProtoEnumMayD+ , HsFunBind fromProtoEnumD+ ]+ , instDecl_ (jsonpbName "ToJSONPB") [ type_ enumName ]+ [ HsFunBind [toJSONPBDecl]+ , HsFunBind [toEncodingPBDecl]+ ]+ , instDecl_ (jsonpbName "FromJSONPB") [ type_ enumName ]+ [ HsFunBind parseJSONPBDecls ]+ -- Generate Aeson instances in terms of JSONPB instances+ , toJSONInstDecl enumName+ , fromJSONInstDecl enumName++#ifdef DHALL+ -- Generate Dhall instances+ , dhallInterpretInstDecl enumName+ , dhallInjectInstDecl enumName+#endif++ -- And the Finite instance, used to infer a Swagger ToSchema instance+ -- for this enumerated type.+ , instDecl_ (protobufName "Finite") [ type_ enumName ] []+ ]++-- ** Generate code for dot proto services++dotProtoServiceD+ :: MonadError CompileError m+ => DotProtoIdentifier+ -> TypeContext+ -> DotProtoIdentifier+ -> [DotProtoServicePart]+ -> m [HsDecl]+dotProtoServiceD pkgIdent ctxt serviceIdent service = do+ serviceName <- typeLikeName =<< dpIdentUnqualName serviceIdent+ packageName <- dpIdentQualName pkgIdent++ let endpointPrefix = "/" ++ packageName ++ "." ++ serviceName ++ "/"++ let serviceFieldD (DotProtoServiceRPCMethod RPCMethod{..}) = do+ fullName <- prefixedFieldName serviceName =<< dpIdentUnqualName rpcMethodName++ methodName <- case rpcMethodName of+ Single nm -> pure nm+ _ -> invalidMethodNameError rpcMethodName++ requestTy <- dpptToHsType ctxt (Named rpcMethodRequestType)+ responseTy <- dpptToHsType ctxt (Named rpcMethodResponseType)++ let streamingType =+ case (rpcMethodRequestStreaming, rpcMethodResponseStreaming) of+ (Streaming, Streaming) -> biDiStreamingC+ (Streaming, NonStreaming) -> clientStreamingC+ (NonStreaming, Streaming) -> serverStreamingC+ (NonStreaming, NonStreaming) -> normalC++ pure [ ( endpointPrefix ++ methodName+ , fullName, rpcMethodRequestStreaming, rpcMethodResponseStreaming+ , HsUnBangedTy $+ HsTyFun (tyApp (HsTyVar (HsIdent "request"))+ [streamingType, requestTy, responseTy])+ (tyApp ioT+ [tyApp (HsTyVar (HsIdent "response"))+ [streamingType, responseTy]+ ]+ )+ )+ ]++ serviceFieldD _ = pure []++ fieldsD <- foldMapM serviceFieldD service++ serverFuncName <- prefixedFieldName serviceName "server"+ clientFuncName <- prefixedFieldName serviceName "client"++ let conDecl = recDecl_ (HsIdent serviceName)+ [ ([HsIdent hsName], ty) | (_, hsName, _, _, ty) <- fieldsD ]++ let serverT = tyApp (HsTyCon (unqual_ serviceName))+ [ serverRequestT, serverResponseT ]++ let serviceServerTypeD =+ HsTypeSig l [ HsIdent serverFuncName ]+ (HsQualType [] (HsTyFun serverT (HsTyFun serviceOptionsC ioActionT)))++ let serviceServerD = HsFunBind [serverFuncD]+ where+ serverFuncD =+ match_ (HsIdent serverFuncName)+ [ HsPRec (unqual_ serviceName)+ [ HsPFieldPat (unqual_ methodName) (HsPVar (HsIdent methodName))+ | (_, methodName, _, _, _) <- fieldsD+ ]+ , HsPApp (unqual_ "ServiceOptions")+ [ patVar "serverHost"+ , patVar "serverPort"+ , patVar "useCompression"+ , patVar "userAgentPrefix"+ , patVar "userAgentSuffix"+ , patVar "initialMetadata"+ , patVar "sslConfig"+ , patVar "logger"+ ]+ ]+ (HsUnGuardedRhs (apply serverLoopE [ serverOptsE ]))+ []++ handlerE handlerC adapterE methodName hsName =+ apply handlerC [ apply methodNameC [ str_ methodName ]+ , apply adapterE [ uvar_ hsName ]+ ]++ update u v = HsFieldUpdate (unqual_ u) (uvar_ v)++ serverOptsE = HsRecUpdate defaultOptionsE+ [ HsFieldUpdate (grpcName "optNormalHandlers") $+ HsList [ handlerE unaryHandlerC convertServerHandlerE endpointName hsName+ | (endpointName, hsName, NonStreaming, NonStreaming, _) <- fieldsD+ ]++ , HsFieldUpdate (grpcName "optClientStreamHandlers") $+ HsList [ handlerE clientStreamHandlerC convertServerReaderHandlerE endpointName hsName+ | (endpointName, hsName, Streaming, NonStreaming, _) <- fieldsD+ ]+++ , HsFieldUpdate (grpcName "optServerStreamHandlers") $+ HsList [ handlerE serverStreamHandlerC convertServerWriterHandlerE endpointName hsName+ | (endpointName, hsName, NonStreaming, Streaming, _) <- fieldsD+ ]+++ , HsFieldUpdate (grpcName "optBiDiStreamHandlers") $+ HsList [ handlerE biDiStreamHandlerC convertServerRWHandlerE endpointName hsName+ | (endpointName, hsName, Streaming, Streaming, _) <- fieldsD+ ]++ , update "optServerHost" "serverHost"+ , update "optServerPort" "serverPort"+ , update "optUseCompression" "useCompression"+ , update "optUserAgentPrefix" "userAgentPrefix"+ , update "optUserAgentSuffix" "userAgentSuffix"+ , update "optInitialMetadata" "initialMetadata"+ , update "optSSLConfig" "sslConfig"+ , update "optLogger" "logger"+ ]+++ let clientT = tyApp (HsTyCon (unqual_ serviceName)) [ clientRequestT, clientResultT ]++ let serviceClientTypeD =+ HsTypeSig l [ HsIdent clientFuncName ]+ (HsQualType [] (HsTyFun grpcClientT (HsTyApp ioT clientT)))++ let serviceClientD = HsFunBind [ clientFuncD ]+ where+ clientFuncD = match_ (HsIdent clientFuncName)+ [ HsPVar (HsIdent "client") ]+ ( HsUnGuardedRhs clientRecE ) []++ clientRecE = foldl (\f -> HsInfixApp f apOp)+ (apply pureE [ uvar_ serviceName ])+ [ HsParen $ HsInfixApp clientRequestE' apOp (registerClientMethodE endpointName)+ | (endpointName, _, _, _, _) <- fieldsD+ ]++ clientRequestE' = apply pureE [ apply clientRequestE [ uvar_ "client" ] ]++ registerClientMethodE endpoint =+ apply clientRegisterMethodE [ uvar_ "client"+ , apply methodNameC [ str_ endpoint ]+ ]++ pure [ HsDataDecl l [] (HsIdent serviceName)+ [ HsIdent "request", HsIdent "response" ]+ [ conDecl ] defaultServiceDeriving++ , serviceServerTypeD+ , serviceServerD++ , serviceClientTypeD+ , serviceClientD+ ]++--------------------------------------------------------------------------------++--+-- * Common Haskell expressions, constructors, and operators+--++dotProtoFieldC, primC, optionalC, repeatedC, nestedRepeatedC, namedC, mapC,+ fieldNumberC, singleC, dotsC, pathC, nestedC, anonymousC, dotProtoOptionC,+ identifierC, stringLitC, intLitC, floatLitC, boolLitC, trueC, falseC,+ unaryHandlerC, clientStreamHandlerC, serverStreamHandlerC, biDiStreamHandlerC,+ methodNameC, nothingC, justC, forceEmitC, mconcatE, encodeMessageFieldE,+ fromStringE, decodeMessageFieldE, pureE, returnE, memptyE, msumE, atE, oneofE,+ fmapE, defaultOptionsE, serverLoopE, convertServerHandlerE,+ convertServerReaderHandlerE, convertServerWriterHandlerE,+ convertServerRWHandlerE, clientRegisterMethodE, clientRequestE :: HsExp++dotProtoFieldC = HsVar (protobufName "DotProtoField")+primC = HsVar (protobufName "Prim")+optionalC = HsVar (protobufName "Optional")+repeatedC = HsVar (protobufName "Repeated")+nestedRepeatedC = HsVar (protobufName "NestedRepeated")+namedC = HsVar (protobufName "Named")+mapC = HsVar (protobufName "Map")+fieldNumberC = HsVar (protobufName "FieldNumber")+singleC = HsVar (protobufName "Single")+pathC = HsVar (protobufName "Path")+dotsC = HsVar (protobufName "Dots")+nestedC = HsVar (protobufName "Nested")+anonymousC = HsVar (protobufName "Anonymous")+dotProtoOptionC = HsVar (protobufName "DotProtoOption")+identifierC = HsVar (protobufName "Identifier")+stringLitC = HsVar (protobufName "StringLit")+intLitC = HsVar (protobufName "IntLit")+floatLitC = HsVar (protobufName "FloatLit")+boolLitC = HsVar (protobufName "BoolLit")+forceEmitC = HsVar (protobufName "ForceEmit")+encodeMessageFieldE = HsVar (protobufName "encodeMessageField")+decodeMessageFieldE = HsVar (protobufName "decodeMessageField")+atE = HsVar (protobufName "at")+oneofE = HsVar (protobufName "oneof")++trueC = HsVar (haskellName "True")+falseC = HsVar (haskellName "False")+nothingC = HsVar (haskellName "Nothing")+justC = HsVar (haskellName "Just")+mconcatE = HsVar (haskellName "mconcat")+fromStringE = HsVar (haskellName "fromString")+pureE = HsVar (haskellName "pure")+returnE = HsVar (haskellName "return")+memptyE = HsVar (haskellName "mempty")+msumE = HsVar (haskellName "msum")+fmapE = HsVar (haskellName "fmap")++unaryHandlerC = HsVar (grpcName "UnaryHandler")+clientStreamHandlerC = HsVar (grpcName "ClientStreamHandler")+serverStreamHandlerC = HsVar (grpcName "ServerStreamHandler")+biDiStreamHandlerC = HsVar (grpcName "BiDiStreamHandler")+methodNameC = HsVar (grpcName "MethodName")+defaultOptionsE = HsVar (grpcName "defaultOptions")+serverLoopE = HsVar (grpcName "serverLoop")+convertServerHandlerE = HsVar (grpcName "convertGeneratedServerHandler")+convertServerReaderHandlerE = HsVar (grpcName "convertGeneratedServerReaderHandler")+convertServerWriterHandlerE = HsVar (grpcName "convertGeneratedServerWriterHandler")+convertServerRWHandlerE = HsVar (grpcName "convertGeneratedServerRWHandler")+clientRegisterMethodE = HsVar (grpcName "clientRegisterMethod")+clientRequestE = HsVar (grpcName "clientRequest")++biDiStreamingC, serverStreamingC, clientStreamingC, normalC, serviceOptionsC,+ ioActionT, serverRequestT, serverResponseT, clientRequestT, clientResultT,+ ioT, grpcClientT :: HsType+biDiStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "BiDiStreaming"))+serverStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "ServerStreaming"))+clientStreamingC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "ClientStreaming"))+normalC = HsTyCon (Qual (Module "'HsGRPC") (HsIdent "Normal"))+serviceOptionsC = HsTyCon (Qual (Module "HsGRPC") (HsIdent "ServiceOptions"))+serverRequestT = HsTyCon (grpcName "ServerRequest")+serverResponseT = HsTyCon (grpcName "ServerResponse")+clientRequestT = HsTyCon (grpcName "ClientRequest")+clientResultT = HsTyCon (grpcName "ClientResult")+grpcClientT = HsTyCon (grpcName "Client")+ioActionT = tyApp ioT [ HsTyTuple [] ]+ioT = HsTyCon (haskellName "IO")++apOp :: HsQOp+apOp = HsQVarOp (UnQual (HsSymbol "<*>"))++fmapOp :: HsQOp+fmapOp = HsQVarOp (UnQual (HsSymbol "<$>"))++composeOp :: HsQOp+composeOp = HsQVarOp (Qual haskellNS (HsSymbol "."))++bindOp :: HsQOp+bindOp = HsQVarOp (Qual haskellNS (HsSymbol ">>="))++altOp :: HsQOp+altOp = HsQVarOp (UnQual (HsSymbol "<|>"))++toJSONPBOp :: HsQOp+toJSONPBOp = HsQVarOp (UnQual (HsSymbol ".="))++parseJSONPBOp :: HsQOp+parseJSONPBOp = HsQVarOp (UnQual (HsSymbol ".:"))++neConsOp :: HsQOp+neConsOp = HsQVarOp (Qual haskellNS (HsSymbol ":|"))++intE :: Integral a => a -> HsExp+intE x = (if x < 0 then HsParen else id) . HsLit . HsInt . fromIntegral $ x++intP :: Integral a => a -> HsPat+intP x = (if x < 0 then HsPParen else id) . HsPLit . HsInt . fromIntegral $ x++-- ** Expressions for protobuf-wire types++forceEmitE :: HsExp -> HsExp+forceEmitE = HsParen . HsApp forceEmitC++fieldNumberE :: FieldNumber -> HsExp+fieldNumberE = HsParen . HsApp fieldNumberC . intE . getFieldNumber++dpIdentE :: DotProtoIdentifier -> HsExp+dpIdentE (Single n) = apply singleC [ str_ n ]+dpIdentE (Dots (Path (n NE.:| ns)))+ = apply dotsC [ apply pathC [ HsParen (HsInfixApp (str_ n) neConsOp (HsList (map str_ ns))) ] ]+dpIdentE (Qualified a b) = apply nestedC [ dpIdentE a, dpIdentE b ]+dpIdentE Anonymous = anonymousC++dpValueE :: DotProtoValue -> HsExp+dpValueE (Identifier nm) = apply identifierC [ dpIdentE nm ]+dpValueE (StringLit s) = apply stringLitC [ str_ s ]+dpValueE (IntLit i) = apply intLitC [ HsLit (HsInt (fromIntegral i)) ]+dpValueE (FloatLit f) = apply floatLitC [ HsLit (HsFrac (toRational f)) ]+dpValueE (BoolLit True) = apply boolLitC [ trueC ]+dpValueE (BoolLit False) = apply boolLitC [ falseC ]++optionE :: DotProtoOption -> HsExp+optionE (DotProtoOption name value) =+ apply dotProtoOptionC [ dpIdentE name, dpValueE value ]++-- | Translate a dot proto type to its Haskell AST type+dpTypeE :: DotProtoType -> HsExp+dpTypeE (Prim p) = apply primC [ dpPrimTypeE p ]+dpTypeE (Optional p) = apply optionalC [ dpPrimTypeE p ]+dpTypeE (Repeated p) = apply repeatedC [ dpPrimTypeE p ]+dpTypeE (NestedRepeated p) = apply nestedRepeatedC [ dpPrimTypeE p ]+dpTypeE (Map k v) = apply mapC [ dpPrimTypeE k, dpPrimTypeE v]+++-- | Translate a dot proto primitive type to a Haskell AST primitive type.+dpPrimTypeE :: DotProtoPrimType -> HsExp+dpPrimTypeE ty =+ let wrap = HsVar . protobufName in+ case ty of+ Named n -> apply namedC [ dpIdentE n ]++ Int32 -> wrap "Int32"+ Int64 -> wrap "Int64"+ SInt32 -> wrap "SInt32"+ SInt64 -> wrap "SInt64"+ UInt32 -> wrap "UInt32"+ UInt64 -> wrap "UInt64"+ Fixed32 -> wrap "Fixed32"+ Fixed64 -> wrap "Fixed64"+ SFixed32 -> wrap "SFixed32"+ SFixed64 -> wrap "SFixed64"+ String -> wrap "String"+ Bytes -> wrap "Bytes"+ Bool -> wrap "Bool"+ Float -> wrap "Float"+ Double -> wrap "Double"++defaultImports :: Bool -> [HsImportDecl]+defaultImports usesGrpc =+ [ importDecl_ (m "Prelude") & qualified haskellNS & everything+ , importDecl_ (m "Proto3.Suite.Class") & qualified protobufNS & everything+#ifdef DHALL+ , importDecl_ (m "Proto3.Suite.DhallPB") & qualified (m hsDhallPB) & everything+#endif+ , importDecl_ (m "Proto3.Suite.DotProto") & qualified protobufNS & everything+ , importDecl_ (m "Proto3.Suite.JSONPB") & qualified jsonpbNS & everything+ , importDecl_ (m "Proto3.Suite.JSONPB") & unqualified & selecting [s".=", s".:"]+ , importDecl_ (m "Proto3.Suite.Types") & qualified protobufNS & everything+ , importDecl_ (m "Proto3.Wire") & qualified protobufNS & everything+ , importDecl_ (m "Control.Applicative") & qualified haskellNS & everything+ , importDecl_ (m "Control.Applicative") & unqualified & selecting [s"<*>", s"<|>", s"<$>"]+ , importDecl_ (m "Control.DeepSeq") & qualified haskellNS & everything+ , importDecl_ (m "Control.Monad") & qualified haskellNS & everything+ , importDecl_ (m "Data.ByteString") & qualified haskellNS & everything+ , importDecl_ (m "Data.Coerce") & qualified haskellNS & everything+ , importDecl_ (m "Data.Int") & qualified haskellNS & selecting [i"Int16", i"Int32", i"Int64"]+ , importDecl_ (m "Data.List.NonEmpty") & qualified haskellNS & selecting [HsIThingAll (HsIdent "NonEmpty")]+ , importDecl_ (m "Data.Map") & qualified haskellNS & selecting [i"Map", i"mapKeysMonotonic"]+ , importDecl_ (m "Data.Proxy") & qualified proxyNS & everything+ , importDecl_ (m "Data.String") & qualified haskellNS & selecting [i"fromString"]+ , importDecl_ (m "Data.Text.Lazy") & qualified haskellNS & selecting [i"Text"]+ , importDecl_ (m "Data.Vector") & qualified haskellNS & selecting [i"Vector"]+ , importDecl_ (m "Data.Word") & qualified haskellNS & selecting [i"Word16", i"Word32", i"Word64"]+ , importDecl_ (m "GHC.Enum") & qualified haskellNS & everything+ , importDecl_ (m "GHC.Generics") & qualified haskellNS & everything+ , importDecl_ (m "Unsafe.Coerce") & qualified haskellNS & everything+ ]+ <>+ (if not usesGrpc then [] else+ [ importDecl_ (m "Network.GRPC.HighLevel.Generated") & alias grpcNS & everything+ , importDecl_ (m "Network.GRPC.HighLevel.Client") & alias grpcNS & everything+ , importDecl_ (m "Network.GRPC.HighLevel.Server") & alias grpcNS & hiding [i"serverLoop"]+ , importDecl_ (m "Network.GRPC.HighLevel.Server.Unregistered") & alias grpcNS & selecting [i"serverLoop"]+ ])+ where+ m = Module+ i = HsIVar . HsIdent+ s = HsIVar . HsSymbol++ grpcNS = m "HsGRPC"+ jsonpbNS = m "HsJSONPB"+ protobufNS = m "HsProtobuf"+ proxyNS = m "Proxy"++ -- staged constructors for importDecl+ qualified :: Module -> (Bool -> Maybe Module -> a) -> a+ qualified m' f = f True (Just m')++ unqualified :: (Bool -> Maybe Module -> a) -> a+ unqualified f = f False Nothing++ -- import unqualified AND also under a namespace+ alias :: Module -> (Bool -> Maybe Module -> a) -> a+ alias m' f = f False (Just m')++ selecting :: [HsImportSpec] -> (Maybe (Bool, [HsImportSpec]) -> a) -> a+ selecting is f = f (Just (False, is))++ hiding :: [HsImportSpec] -> (Maybe (Bool, [HsImportSpec]) -> a) -> a+ hiding is f = f (Just (True, is))++ everything :: (Maybe (Bool, [HsImportSpec]) -> a) -> a+ everything f = f Nothing++haskellNS :: Module+haskellNS = Module "Hs"++defaultMessageDeriving :: [HsQName]+defaultMessageDeriving = map haskellName [ "Show", "Eq", "Ord", "Generic", "NFData" ]++defaultEnumDeriving :: [HsQName]+defaultEnumDeriving = map haskellName [ "Show", "Eq", "Generic", "NFData" ]++defaultServiceDeriving :: [HsQName]+defaultServiceDeriving = map haskellName [ "Generic" ]++--------------------------------------------------------------------------------+--+-- * Wrappers around haskell-src-exts constructors+--++apply :: HsExp -> [HsExp] -> HsExp+apply f = HsParen . foldl HsApp f++applicativeApply :: HsExp -> [HsExp] -> HsExp+applicativeApply f = foldl snoc nil+ where+ nil = HsApp pureE f++ snoc g x = HsInfixApp g apOp x++tyApp :: HsType -> [HsType] -> HsType+tyApp = foldl HsTyApp++module_ :: Module -> Maybe [HsExportSpec] -> [HsImportDecl] -> [HsDecl] -> HsModule+module_ = HsModule l++importDecl_ :: Module -> Bool -> Maybe Module -> Maybe (Bool, [HsImportSpec]) -> HsImportDecl+importDecl_ = HsImportDecl l++dataDecl_ :: String -> [HsConDecl] -> [HsQName] -> HsDecl+dataDecl_ messageName = HsDataDecl l [] (HsIdent messageName) []++recDecl_ :: HsName -> [([HsName], HsBangType)] -> HsConDecl+recDecl_ = HsRecDecl l++conDecl_ :: HsName -> [HsBangType] -> HsConDecl+conDecl_ = HsConDecl l++instDecl_ :: HsQName -> [HsType] -> [HsDecl] -> HsDecl+instDecl_ = HsInstDecl l []++match_ :: HsName -> [HsPat] -> HsRhs -> [HsDecl] -> HsMatch+match_ = HsMatch l++unqual_ :: String -> HsQName+unqual_ = UnQual . HsIdent++uvar_ :: String -> HsExp+uvar_ = HsVar . unqual_++protobufType_, primType_ :: String -> HsType+protobufType_ = HsTyCon . protobufName+primType_ = HsTyCon . haskellName++type_ :: String -> HsType+type_ = HsTyCon . unqual_++patVar :: String -> HsPat+patVar = HsPVar . HsIdent++alt_ :: HsPat -> HsGuardedAlts -> [HsDecl] -> HsAlt+alt_ = HsAlt l++str_ :: String -> HsExp+str_ = HsLit . HsString -- | For some reason, haskell-src-exts needs this 'SrcLoc' parameter -- for some data constructors. Its value does not affect
src/Proto3/Suite/DotProto/Generate/Swagger.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-}@@ -17,7 +18,11 @@ ) where +#if MIN_VERSION_swagger2(2,4,0)+import Control.Lens ((&), (?~))+#else import Control.Lens ((&), (.~), (?~))+#endif import Data.Aeson (Value (String)) import Data.Aeson.Encode.Pretty (encodePretty) import Data.ByteString (ByteString)@@ -55,7 +60,11 @@ declareNamedSchema _ = return (NamedSchema Nothing schema_) where schema_ = mempty+#if MIN_VERSION_swagger2(2,4,0)+ & type_ ?~ SwaggerArray+#else & type_ .~ SwaggerArray+#endif & items ?~ SwaggerItemsObject (Inline byteSchema) {-| This is a convenience function that uses type inference to select the@@ -66,7 +75,7 @@ -- | Pretty-prints a schema. Useful when playing around with schemas in the -- REPL.-ppSchema :: ToSchema a => proxy a -> IO ()+ppSchema :: ToSchema a => Proxy a -> IO () ppSchema = LC8.putStrLn . encodePretty . toSchema -- | JSONPB schemas for protobuf enumerations@@ -77,7 +86,11 @@ let enumMemberNames = dropPrefix . fst <$> enumerate (proxy# :: Proxy# e) return $ NamedSchema (Just enumName) $ mempty+#if MIN_VERSION_swagger2(2,4,0)+ & type_ ?~ SwaggerString+#else & type_ .~ SwaggerString+#endif & enum_ ?~ fmap String enumMemberNames instance ToSchema (Fixed Int32) where
src/Proto3/Suite/DotProto/Internal.hs view
@@ -1,31 +1,84 @@ -- | This module provides misc internal helpers and utilities +{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} {-# LANGUAGE ViewPatterns #-} module Proto3.Suite.DotProto.Internal where +import Control.Applicative import qualified Control.Foldl as FL-import Control.Lens (over)+import Control.Lens (Lens', lens, over) import Control.Lens.Cons (_head)-import Data.Char (toUpper)+import Control.Monad+import Control.Monad.Except+import Data.Bifunctor (first)+import Data.Char+import Data.Coerce+import Data.Either+import Data.Foldable+import Data.Functor.Compose+import Data.Int (Int32)+import Data.List (find, intercalate)+import qualified Data.List.NonEmpty as NE+import qualified Data.Map as M import Data.Maybe (fromMaybe)+import Data.Semigroup (Semigroup(..)) import qualified Data.Text as T-import System.FilePath (isPathSeparator)-import qualified Filesystem.Path.CurrentOS as FP+import Data.Tuple (swap) import Filesystem.Path.CurrentOS ((</>))+import qualified Filesystem.Path.CurrentOS as FP import qualified NeatInterpolation as Neat import Prelude hiding (FilePath)-import Proto3.Suite.DotProto+import Proto3.Suite.DotProto.AST+import Proto3.Suite.DotProto.AST.Lens+import Proto3.Suite.DotProto.Parsing+import Proto3.Wire.Types (FieldNumber (..))+import System.FilePath (isPathSeparator) import Text.Parsec (ParseError)+import qualified Turtle import Turtle (ExitCode (..), FilePath, MonadIO, Text)-import qualified Turtle import Turtle.Format ((%)) import qualified Turtle.Format as F +-------------------------------------------------------------------------------+--+-- * Utilities+--++#if !(MIN_VERSION_mtl(2,2,2))+liftEither :: MonadError e m => Either e a -> m a+liftEither = either throwError pure+#endif++-- | Like 'foldMap', but with an effectful projection.+foldMapM ::+ (Foldable t, Monad m, Monoid b, Semigroup b) => (a -> m b) -> t a -> m b+foldMapM f = foldM (\b a -> (b <>) <$> f a) mempty++-- | Like 'Control.Lens.Getter.Getting', but allows for retrieving the 'r'+-- element in some Applicative context 'm'.+type GettingM r s a = forall m. Applicative m => (a -> Compose m (Const r) a) -> s -> Compose m (Const r) s++-- | Given an effectful projection from 'a' into a monoid 'r', retrieve the sum+-- of all 'a' values in an 's' structure as targetted by the 'GettingM' optic.+-- Note that the Monoid constraint on 'r' is implicit via 'Const', but we+-- note it in the type for clarity.+foldMapOfM :: (Applicative m, Monoid r) => GettingM r s a -> (a -> m r) -> s -> m r+foldMapOfM l f = fmap getConst . getCompose . l (Compose . fmap Const . f)++mapKeysM :: (Monad m, Ord k2) => (k1 -> m k2) -> M.Map k1 a -> m (M.Map k2 a)+mapKeysM f = fmap M.fromList . traverse (fmap swap . traverse f . swap) . M.assocs+ -- $setup -- >>> :set -XOverloadedStrings @@ -34,6 +87,11 @@ mapM_ Turtle.err msg Turtle.exit (ExitFailure 1) +--------------------------------------------------------------------------------+--+-- * Reading files+--+ -- | toModulePath takes an include-relative path to a .proto file and produces a -- "module path" which is used during code generation. --@@ -65,23 +123,23 @@ -- Left "path contained unexpected .. after canonicalization, please use form x.y.z.proto" -- -- >>> toModulePath "google/protobuf/timestamp.proto"--- Right (Path {components = ["Google","Protobuf","Timestamp"]})+-- Right (Path {components = "Google" :| ["Protobuf","Timestamp"]}) -- -- >>> toModulePath "a/b/c/google.protobuf.timestamp.proto"--- Right (Path {components = ["A","B","C","Google","Protobuf","Timestamp"]})+-- Right (Path {components = "A" :| ["B","C","Google","Protobuf","Timestamp"]}) -- -- >>> toModulePath "foo/FiLeName_underscore.and.then.some.dots.proto"--- Right (Path {components = ["Foo","FiLeName_underscore","And","Then","Some","Dots"]})+-- Right (Path {components = "Foo" :| ["FiLeName_underscore","And","Then","Some","Dots"]}) -- -- >>> toModulePath "foo/bar/././baz/../boggle.proto"--- Right (Path {components = ["Foo","Bar","Boggle"]})+-- Right (Path {components = "Foo" :| ["Bar","Boggle"]}) -- -- >>> toModulePath "./foo.proto"--- Right (Path {components = ["Foo"]})+-- Right (Path {components = "Foo" :| []}) -- -- NB: We ignore preceding single '.' characters -- >>> toModulePath ".foo.proto"--- Right (Path {components = ["Foo"]})+-- Right (Path {components = "Foo" :| []}) toModulePath :: FilePath -> Either String Path toModulePath fp0@(fromMaybe fp0 . FP.stripPrefix "./" -> fp) | Turtle.absolute fp@@ -92,11 +150,11 @@ = case FP.stripPrefix "../" fp of Just{} -> Left "expected include-relative path, but the path started with ../" Nothing- | T.isInfixOf ".." (Turtle.format F.fp . FP.collapse $ fp)+ | T.isInfixOf ".." . Turtle.format F.fp . FP.collapse $ fp -> Left "path contained unexpected .. after canonicalization, please use form x.y.z.proto" | otherwise- -> Right- . Path+ -> maybe (Left "empty path after canonicalization") (Right . Path)+ . NE.nonEmpty . dropWhile null -- Remove a potential preceding empty component which -- arose from a preceding '.' in the input path, which we -- want to ignore. E.g. ".foo.proto" => ["","Foo"].@@ -108,27 +166,55 @@ . Turtle.dropExtension $ fp -fatalBadModulePath :: MonadIO m => FilePath -> String -> m a-fatalBadModulePath (Turtle.format F.fp -> fp) (T.pack -> rsn) =- dieLines [Neat.text|- Error: failed when computing the "module path" for "${fp}": ${rsn}-- Please ensure that the provided path to a .proto file is specified as- relative to some --includeDir path and that it has the .proto suffix.- |]- -- | @importProto searchPaths toplevel inc@ attempts to import include-relative -- @inc@ after locating it somewhere in the @searchPaths@; @toplevel@ is simply -- the path of toplevel .proto being processed so we can report it in an error -- message. This function terminates the program if it cannot find the file to -- import or if it cannot construct a valid module path from it.-importProto :: MonadIO m- => [FilePath] -> FilePath -> FilePath -> m (Either ParseError DotProto)-importProto paths (Turtle.format F.fp -> toplevelProtoText) protoFP =+importProto :: (MonadIO m, MonadError CompileError m)+ => [FilePath] -> FilePath -> FilePath -> m DotProto+importProto paths toplevelProto protoFP = findProto paths protoFP >>= \case- Found mp fp -> parseProtoFile mp fp- BadModulePath e -> fatalBadModulePath protoFP e- NotFound -> dieLines [Neat.text|+ Left e+ -> dieLines (badModulePathErrorMsg protoFP e)+ Right Nothing+ | toplevelProto == protoFP+ -> dieLines (toplevelNotFoundErrorMsg paths toplevelProto)+ | otherwise+ -> dieLines (importNotFoundErrorMsg paths toplevelProto protoFP)+ Right (Just (mp, fp))+ -> liftEither . first CompileParseError =<< parseProtoFile mp fp++type FindProtoResult = Either String (Maybe (Path, FilePath))++-- | Attempts to locate the first (if any) filename that exists on the given+-- search paths, and constructs the "module path" from the given+-- include-relative filename (2nd parameter). Terminates the program with an+-- error if the given pathname is not relative.+findProto :: MonadIO m => [FilePath] -> FilePath -> m FindProtoResult+findProto searchPaths protoFP+ | Turtle.absolute protoFP = dieLines absolutePathErrorMsg+ | otherwise = forM (toModulePath protoFP) $ \mp ->+ flip Turtle.fold FL.head $ do+ sp <- Turtle.select searchPaths+ let fp = sp </> protoFP+ True <- Turtle.testfile fp+ pure (mp, fp)++-- * Pretty Error Messages++badModulePathErrorMsg :: FilePath -> String -> T.Text+badModulePathErrorMsg (Turtle.format F.fp -> fp) (T.pack -> rsn) =+ [Neat.text|+ Error: failed when computing the "module path" for "${fp}": ${rsn}++ Please ensure that the provided path to a .proto file is specified as+ relative to some --includeDir path and that it has the .proto suffix.+ |]++importNotFoundErrorMsg :: [FilePath] -> FilePath -> FilePath -> T.Text+importNotFoundErrorMsg paths toplevelProto protoFP =+ [Neat.text| Error: while processing include statements in "${toplevelProtoText}", failed to find the imported file "${protoFPText}", after looking in the following locations (controlled via the --includeDir switch(es)):@@ -136,39 +222,340 @@ $pathsText |] where- pathsText = T.unlines (Turtle.format (" "%F.fp) . (</> protoFP) <$> paths)+ pathsText = T.unlines (Turtle.format (" "%F.fp) . (</> protoFP) <$> paths)+ toplevelProtoText = Turtle.format F.fp toplevelProto protoFPText = Turtle.format F.fp protoFP -data FindProtoResult- = Found Path FilePath- | NotFound- | BadModulePath String- deriving (Eq, Show)+toplevelNotFoundErrorMsg :: [FilePath] -> FilePath -> T.Text+toplevelNotFoundErrorMsg searchPaths toplevelProto =+ [Neat.text|+ Error: failed to find file "${toplevelProtoText}", after looking in+ the following locations (controlled via the --includeDir switch(es)): --- | Attempts to locate the first (if any) filename that exists on the given--- search paths, and constructs the "module path" from the given--- include-relative filename (2nd parameter). Terminates the program with an--- error if the given pathname is not relative.-findProto :: MonadIO m => [FilePath] -> FilePath -> m FindProtoResult-findProto searchPaths protoFP- | Turtle.absolute protoFP = dieLines [Neat.text|- Error: Absolute paths to .proto files, whether on the command line or- in include directives, are not currently permitted; rather, all .proto- filenames must be relative to the current directory, or relative to some- search path specified via --includeDir.+ $searchPathsText+ |]+ where+ searchPathsText = T.unlines (Turtle.format (" "%F.fp) . (</> toplevelProto) <$> searchPaths)+ toplevelProtoText = Turtle.format F.fp toplevelProto - This is because we currently use the include-relative name to decide- the structure of the Haskell module tree that we emit during code- generation.- |]- | otherwise = case toModulePath protoFP of- Left e -> pure (BadModulePath e)- Right mp -> do- mfp <- flip Turtle.fold FL.head $ do- sp <- Turtle.select searchPaths- let fp = sp </> protoFP- True <- Turtle.testfile fp- pure fp- case mfp of- Nothing -> pure NotFound- Just fp -> pure (Found mp fp)+absolutePathErrorMsg :: T.Text+absolutePathErrorMsg =+ [Neat.text|+ Error: Absolute paths to .proto files, whether on the command line or+ in include directives, are not currently permitted; rather, all .proto+ filenames must be relative to the current directory, or relative to some+ search path specified via --includeDir.++ This is because we currently use the include-relative name to decide+ the structure of the Haskell module tree that we emit during code+ generation.+ |]++--------------------------------------------------------------------------------+--+-- * Type context+--++-- | A mapping from .proto type identifiers to their type information+type TypeContext = M.Map DotProtoIdentifier DotProtoTypeInfo++-- | Information about messages and enumerations+data DotProtoTypeInfo = DotProtoTypeInfo+ { dotProtoTypeInfoPackage :: DotProtoPackageSpec+ -- ^ The package this type is defined in+ , dotProtoTypeInfoParent :: DotProtoIdentifier+ -- ^ The message this type is nested under, or 'Anonymous' if it's top-level+ , dotProtoTypeChildContext :: TypeContext+ -- ^ The context that should be used for declarations within the+ -- scope of this type+ , dotProtoTypeInfoKind :: DotProtoKind+ -- ^ Whether this type is an enumeration or message+ , dotProtoTypeInfoModulePath :: Path+ -- ^ The include-relative module path used when importing this module+ } deriving Show++tiParent :: Lens' DotProtoTypeInfo DotProtoIdentifier+tiParent = lens dotProtoTypeInfoParent (\d p -> d{ dotProtoTypeInfoParent = p })++-- | Whether a definition is an enumeration or a message+data DotProtoKind = DotProtoKindEnum+ | DotProtoKindMessage+ deriving (Show, Eq, Ord, Enum, Bounded)++-- ** Generating type contexts from ASTs++dotProtoTypeContext :: MonadError CompileError m => DotProto -> m TypeContext+dotProtoTypeContext DotProto{..} =+ foldMapM (definitionTypeContext (metaModulePath protoMeta)) protoDefinitions++definitionTypeContext :: MonadError CompileError m+ => Path -> DotProtoDefinition -> m TypeContext+definitionTypeContext modulePath (DotProtoMessage _ msgIdent parts) = do+ let updateParent = tiParent (concatDotProtoIdentifier msgIdent)++ childTyContext <- foldMapOfM (traverse . _DotProtoMessageDefinition)+ (definitionTypeContext modulePath >=> traverse updateParent)+ parts++ qualifiedChildTyContext <- mapKeysM (concatDotProtoIdentifier msgIdent) childTyContext++ let tyInfo = DotProtoTypeInfo { dotProtoTypeInfoPackage = DotProtoNoPackage+ , dotProtoTypeInfoParent = Anonymous+ , dotProtoTypeChildContext = childTyContext+ , dotProtoTypeInfoKind = DotProtoKindMessage+ , dotProtoTypeInfoModulePath = modulePath+ }++ pure $ M.singleton msgIdent tyInfo <> qualifiedChildTyContext++definitionTypeContext modulePath (DotProtoEnum _ enumIdent _) = do+ let tyInfo = DotProtoTypeInfo { dotProtoTypeInfoPackage = DotProtoNoPackage+ , dotProtoTypeInfoParent = Anonymous+ , dotProtoTypeChildContext = mempty+ , dotProtoTypeInfoKind = DotProtoKindEnum+ , dotProtoTypeInfoModulePath = modulePath+ }+ pure (M.singleton enumIdent tyInfo)++definitionTypeContext _ _ = pure mempty+++isMessage :: TypeContext -> DotProtoIdentifier -> Bool+isMessage ctxt n = Just DotProtoKindMessage == (dotProtoTypeInfoKind <$> M.lookup n ctxt)++isPacked :: [DotProtoOption] -> Bool+isPacked opts =+ case find (\(DotProtoOption name _) -> name == Single "packed") opts of+ Just (DotProtoOption _ (BoolLit x)) -> x+ _ -> False++isUnpacked :: [DotProtoOption] -> Bool+isUnpacked opts =+ case find (\(DotProtoOption name _) -> name == Single "packed") opts of+ Just (DotProtoOption _ (BoolLit x)) -> not x+ _ -> False++-- | Returns 'True' if the given primitive type is packable. The 'TypeContext'+-- is used to distinguish Named enums and messages, only the former of which are+-- packable.+isPackable :: TypeContext -> DotProtoPrimType -> Bool+isPackable _ Bytes = False+isPackable _ String = False+isPackable _ Int32 = True+isPackable _ Int64 = True+isPackable _ SInt32 = True+isPackable _ SInt64 = True+isPackable _ UInt32 = True+isPackable _ UInt64 = True+isPackable _ Fixed32 = True+isPackable _ Fixed64 = True+isPackable _ SFixed32 = True+isPackable _ SFixed64 = True+isPackable _ Bool = True+isPackable _ Float = True+isPackable _ Double = True+isPackable ctxt (Named tyName) =+ Just DotProtoKindEnum == (dotProtoTypeInfoKind <$> M.lookup tyName ctxt)++isMap :: DotProtoType -> Bool+isMap Map{} = True+isMap _ = False++--------------------------------------------------------------------------------+--+-- * Name resolution+--++concatDotProtoIdentifier :: MonadError CompileError m+ => DotProtoIdentifier -> DotProtoIdentifier -> m DotProtoIdentifier+concatDotProtoIdentifier i1 i2 = case (i1, i2) of+ (Qualified{} , _ ) -> internalError "concatDotProtoIdentifier: Qualified"+ (_ , Qualified{} ) -> internalError "concatDotProtoIdentifier Qualified"+ (Anonymous , Anonymous ) -> pure Anonymous+ (Anonymous , b ) -> pure b+ (a , Anonymous ) -> pure a+ (Single a , b ) -> concatDotProtoIdentifier (Dots (Path (pure a))) b+ (a , Single b ) -> concatDotProtoIdentifier a (Dots (Path (pure b)))+ (Dots (Path a), Dots (Path b)) -> pure (Dots (Path (a <> b)))++camelCased :: String -> String+camelCased s = do+ (prev, cur) <- zip (Nothing:map Just s) (map Just s ++ [Nothing])+ case (prev, cur) of+ (Just '_', Just x)+ | isAlpha x -> pure (toUpper x)+ (Just '_', Nothing) -> pure '_'+ (Just '_', Just '_') -> pure '_'+ (_, Just '_') -> empty+ (_, Just x) -> pure x+ (_, _) -> empty++typeLikeName :: MonadError CompileError m => String -> m String+typeLikeName ident@(c:cs)+ | isUpper c = pure (camelCased ident)+ | isLower c = pure (camelCased (toUpper c : cs))+ | '_' == c = pure (camelCased ('X':ident))+typeLikeName ident = invalidTypeNameError ident++fieldLikeName :: String -> String+fieldLikeName ident@(c:_)+ | isUpper c = let (prefix, suffix) = span isUpper ident+ in map toLower prefix ++ suffix+fieldLikeName ident = ident++prefixedEnumFieldName :: String -> String -> String+prefixedEnumFieldName enumName fieldName = enumName <> fieldName++prefixedConName :: MonadError CompileError m => String -> String -> m String+prefixedConName msgName conName = (msgName ++) <$> typeLikeName conName++-- TODO: This should be ~:: MessageName -> FieldName -> ...; same elsewhere, the+-- String types are a bit of a hassle.+prefixedFieldName :: MonadError CompileError m => String -> String -> m String+prefixedFieldName msgName fieldName = (fieldLikeName msgName ++) <$> typeLikeName fieldName++dpIdentUnqualName :: MonadError CompileError m => DotProtoIdentifier -> m String+dpIdentUnqualName (Single name) = pure name+dpIdentUnqualName (Dots (Path names)) = pure (NE.last names)+dpIdentUnqualName (Qualified _ next) = dpIdentUnqualName next+dpIdentUnqualName Anonymous = internalError "dpIdentUnqualName: Anonymous"++dpIdentQualName :: MonadError CompileError m => DotProtoIdentifier -> m String+dpIdentQualName (Single name) = pure name+dpIdentQualName (Dots (Path names)) = pure (intercalate "." (NE.toList names))+dpIdentQualName (Qualified _ _) = internalError "dpIdentQualName: Qualified"+dpIdentQualName Anonymous = internalError "dpIdentQualName: Anonymous"++-- | Given a 'DotProtoIdentifier' for the parent type and the unqualified name+-- of this type, generate the corresponding Haskell name+nestedTypeName :: MonadError CompileError m => DotProtoIdentifier -> String -> m String+nestedTypeName Anonymous nm = typeLikeName nm+nestedTypeName (Single parent) nm = intercalate "_" <$> traverse typeLikeName [parent, nm]+nestedTypeName (Dots (Path parents)) nm = intercalate "_" . (<> [nm]) <$> traverse typeLikeName (NE.toList parents)+nestedTypeName (Qualified {}) _ = internalError "nestedTypeName: Qualified"++qualifiedMessageName :: MonadError CompileError m => DotProtoIdentifier -> DotProtoIdentifier -> m String+qualifiedMessageName parentIdent msgIdent = nestedTypeName parentIdent =<< dpIdentUnqualName msgIdent++--------------------------------------------------------------------------------+--+-- ** Codegen bookkeeping helpers+--++-- | Bookeeping for qualified fields+data QualifiedField = QualifiedField+ { recordFieldName :: FieldName+ , fieldInfo :: FieldInfo+ } deriving Show++-- | Bookkeeping for fields+data FieldInfo+ = FieldOneOf OneofField+ | FieldNormal FieldName FieldNumber DotProtoType [DotProtoOption]+ deriving Show++-- | Bookkeeping for oneof fields+data OneofField = OneofField+ { oneofType :: String+ , subfields :: [OneofSubfield]+ } deriving Show++-- | Bookkeeping for oneof subfields+data OneofSubfield = OneofSubfield+ { subfieldNumber :: FieldNumber+ , subfieldConsName :: String+ , subfieldName :: FieldName+ , subfieldType :: DotProtoType+ , subfieldOptions :: [DotProtoOption]+ } deriving Show++getQualifiedFields :: MonadError CompileError m+ => String -> [DotProtoMessagePart] -> m [QualifiedField]+getQualifiedFields msgName msgParts = flip foldMapM msgParts $ \case+ DotProtoMessageField DotProtoField{..} -> do+ fieldName <- dpIdentUnqualName dotProtoFieldName+ qualName <- prefixedFieldName msgName fieldName+ pure . (:[]) $ QualifiedField { recordFieldName = coerce qualName+ , fieldInfo = FieldNormal (coerce fieldName)+ dotProtoFieldNumber+ dotProtoFieldType+ dotProtoFieldOptions+ }++ DotProtoMessageOneOf _ [] ->+ throwError (InternalError "getQualifiedFields: encountered oneof with no oneof fields")++ DotProtoMessageOneOf oneofIdent fields -> do+ ident <- dpIdentUnqualName oneofIdent+ oneofName <- prefixedFieldName msgName ident+ oneofTypeName <- prefixedConName msgName ident++ let mkSubfield DotProtoField{..} = do+ s <- dpIdentUnqualName dotProtoFieldName+ c <- prefixedConName oneofTypeName s+ pure [OneofSubfield dotProtoFieldNumber c (coerce s) dotProtoFieldType dotProtoFieldOptions]+ mkSubfield DotProtoEmptyField = pure []++ fieldElems <- foldMapM mkSubfield fields++ pure . (:[]) $ QualifiedField { recordFieldName = coerce oneofName+ , fieldInfo = FieldOneOf (OneofField ident fieldElems)+ }+ _ -> pure []++-- | Project qualified fields, given a projection function per field type.+foldQF :: (FieldName -> FieldNumber -> a) -- ^ projection for normal fields+ -> (OneofField -> a) -- ^ projection for oneof fields+ -> QualifiedField+ -> a+foldQF f _ (QualifiedField _ (FieldNormal fldName fldNum _ _)) = f fldName fldNum+foldQF _ g (QualifiedField _ (FieldOneOf fld)) = g fld++fieldBinder :: FieldNumber -> String+fieldBinder = ("f" ++) . show++oneofSubBinder :: OneofSubfield -> String+oneofSubBinder = fieldBinder . subfieldNumber++oneofSubDisjunctBinder :: [OneofSubfield] -> String+oneofSubDisjunctBinder = intercalate "_or_" . fmap oneofSubBinder++--------------------------------------------------------------------------------+--+-- * Errors+--++data CompileError+ = CircularImport FilePath+ | CompileParseError ParseError+ | InternalError String+ | InvalidPackageName DotProtoIdentifier+ | InvalidMethodName DotProtoIdentifier+ | InvalidTypeName String+ | InvalidMapKeyType String+ | NoPackageDeclaration+ | NoSuchType DotProtoIdentifier+ | NonzeroFirstEnumeration String DotProtoIdentifier Int32+ | EmptyEnumeration String+ | Unimplemented String+ deriving (Show, Eq)+++internalError :: MonadError CompileError m => String -> m a+internalError = throwError . InternalError++invalidTypeNameError :: MonadError CompileError m => String -> m a+invalidTypeNameError = throwError . InvalidTypeName++_unimplementedError :: MonadError CompileError m => String -> m a+_unimplementedError = throwError . Unimplemented++invalidMethodNameError :: MonadError CompileError m => DotProtoIdentifier -> m a+invalidMethodNameError = throwError . InvalidMethodName++noSuchTypeError :: MonadError CompileError m => DotProtoIdentifier -> m a+noSuchTypeError = throwError . NoSuchType++protoPackageName :: MonadError CompileError m => DotProtoPackageSpec -> m DotProtoIdentifier+protoPackageName (DotProtoPackageSpec name) = pure name+protoPackageName DotProtoNoPackage = throwError NoPackageDeclaration
src/Proto3/Suite/DotProto/Parsing.hs view
@@ -1,9 +1,12 @@ -- | This module contains a near-direct translation of the proto3 grammar -- It uses String for easier compatibility with DotProto.Generator, which needs it for not very good reasons -{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} module Proto3.Suite.DotProto.Parsing@@ -13,6 +16,7 @@ import Control.Applicative hiding (empty) import Control.Monad+import qualified Data.List.NonEmpty as NE import Data.Functor import qualified Data.Text as T import qualified Filesystem.Path.CurrentOS as FP@@ -34,16 +38,19 @@ -- module path to be injected into the AST as part of 'DotProtoMeta' metadata on -- a successful parse. parseProto :: Path -> String -> Either ParseError DotProto-parseProto modulePath = parse (runProtoParser (topLevel modulePath)) ""+parseProto modulePath = parseProtoWithFile modulePath "" +parseProtoWithFile :: Path -> String -> String -> Either ParseError DotProto+parseProtoWithFile modulePath filePath = parse (runProtoParser (topLevel modulePath)) filePath+ -- | @parseProtoFile mp fp@ reads and parses the .proto file found at @fp@. @mp@ -- is used downstream during code generation when we need to generate names -- which are a function of the source .proto file's filename and its path -- relative to some @--includeDir@. parseProtoFile :: Turtle.MonadIO m => Path -> Turtle.FilePath -> m (Either ParseError DotProto)-parseProtoFile modulePath =- fmap (parseProto modulePath) . Turtle.liftIO . readFile . FP.encodeString+parseProtoFile modulePath (FP.encodeString -> fp) =+ parseProtoWithFile modulePath fp <$> Turtle.liftIO (readFile fp) ---------------------------------------- -- convenience@@ -54,9 +61,9 @@ , Parsing, CharParsing, LookAheadParsing) instance TokenParsing ProtoParser where- someSpace = TokenStyle.buildSomeSpaceParser- (ProtoParser someSpace)- TokenStyle.javaCommentStyle+ someSpace = TokenStyle.buildSomeSpaceParser+ (ProtoParser someSpace)+ TokenStyle.javaCommentStyle -- use the default implementation for other methods: -- nesting, semi, highlight, token @@ -76,10 +83,10 @@ -- Parses a full identifier, without consuming trailing space. _identifier :: ProtoParser DotProtoIdentifier-_identifier = do is <- identifierName `sepBy1` string "."- return $ case is of- [i] -> Single i- _ -> Dots (Path is)+_identifier = identifierName `sepBy1` string "." >>= \case+ [] -> fail "impossible"+ [i] -> pure (Single i)+ (i:is) -> pure (Dots (Path (i NE.:| is))) singleIdentifier :: ProtoParser DotProtoIdentifier singleIdentifier = Single <$> token identifierName@@ -232,9 +239,9 @@ -- service statements servicePart :: ProtoParser DotProtoServicePart-servicePart = rpc- <|> (DotProtoServiceOption <$> topOption)- <|> empty $> DotProtoServiceEmpty+servicePart = DotProtoServiceRPCMethod <$> rpc+ <|> DotProtoServiceOption <$> topOption+ <|> DotProtoServiceEmpty <$ empty rpcOptions :: ProtoParser [DotProtoOption] rpcOptions = braces $ many topOption@@ -245,20 +252,20 @@ -- NB: Distinguish "stream stream.foo" from "stream.foo" try (symbol "stream" *> sid Streaming) <|> sid NonStreaming -rpc :: ProtoParser DotProtoServicePart+rpc :: ProtoParser RPCMethod rpc = do symbol "rpc"- name <- singleIdentifier- subjecttype <- parens rpcClause+ rpcMethodName <- singleIdentifier+ (rpcMethodRequestType, rpcMethodRequestStreaming) <- parens rpcClause symbol "returns"- returntype <- parens rpcClause- options <- rpcOptions <|> (semi $> [])- return $ DotProtoServiceRPC name subjecttype returntype options+ (rpcMethodResponseType, rpcMethodResponseStreaming) <- parens rpcClause+ rpcMethodOptions <- rpcOptions <|> (semi $> [])+ return RPCMethod{..} service :: ProtoParser DotProtoDefinition service = do symbol "service" name <- singleIdentifier statements <- braces (many servicePart)- return $ DotProtoService name statements+ return $ DotProtoService mempty name statements -------------------------------------------------------------------------------- -- message definitions@@ -267,7 +274,7 @@ message = do symbol "message" name <- singleIdentifier body <- braces (many messagePart)- return $ DotProtoMessage name body+ return $ DotProtoMessage mempty name body messageOneOf :: ProtoParser DotProtoMessagePart messageOneOf = do symbol "oneof"@@ -299,7 +306,7 @@ mnumber <- fieldNumber moptions <- optionAnnotation semi- return $ DotProtoField mnumber mtype mname moptions Nothing+ return $ DotProtoField mnumber mtype mname moptions mempty -------------------------------------------------------------------------------- -- enumerations@@ -322,7 +329,7 @@ enum = do symbol "enum" ename <- singleIdentifier ebody <- braces (many enumStatement)- return $ DotProtoEnum ename ebody+ return $ DotProtoEnum mempty ename ebody -------------------------------------------------------------------------------- -- field reservations
src/Proto3/Suite/DotProto/Rendering.hs view
@@ -20,6 +20,7 @@ ) where import Data.Char+import qualified Data.List.NonEmpty as NE import qualified Data.Text as T import Filesystem.Path.CurrentOS (toText) #if (MIN_VERSION_base(4,11,0))@@ -97,19 +98,28 @@ instance Pretty DotProtoOption where pPrint (DotProtoOption key value) = pPrint key <+> PP.text "=" <+> pPrint value +renderComment :: String -> PP.Doc+renderComment = PP.vcat . map ((PP.text "//" <+>) . textIfNonempty) . lines+ where+ textIfNonempty [] = PP.empty+ textIfNonempty text = PP.text text++-- Put the final closing brace on the next line.+-- This is important, since the final field might have a comment, and+-- the brace cannot be part of the comment.+-- We could use block comments instead, once the parser/lexer supports them.+vbraces :: PP.Doc -> PP.Doc -> PP.Doc+vbraces header body = header <+> PP.char '{' $$ PP.nest 2 body $$ PP.char '}'+ prettyPrintProtoDefinition :: RenderingOptions -> DotProtoDefinition -> PP.Doc prettyPrintProtoDefinition opts = defn where defn :: DotProtoDefinition -> PP.Doc- defn (DotProtoMessage name parts) = PP.text "message" <+> pPrint name <+> (braces $ PP.vcat $ msgPart name <$> parts)- defn (DotProtoEnum name parts) = PP.text "enum" <+> pPrint name <+> (PP.braces $ PP.vcat $ enumPart name <$> parts)- defn (DotProtoService name parts) = PP.text "service" <+> pPrint name <+> (PP.braces $ PP.vcat $ pPrint <$> parts)-- -- Put the final closing brace on the next line.- -- This is important, since the final field might have a comment, and- -- the brace cannot be part of the comment.- -- We could use block comments instead, once the parser/lexer supports them.- braces :: PP.Doc -> PP.Doc- braces = ($$ PP.text "}") . (PP.text "{" <+>)+ defn (DotProtoMessage comment name parts) = renderComment comment $$+ vbraces (PP.text "message" <+> pPrint name) (PP.vcat $ msgPart name <$> parts)+ defn (DotProtoEnum comment name parts) = renderComment comment $$+ vbraces (PP.text "enum" <+> pPrint name) (PP.vcat $ enumPart name <$> parts)+ defn (DotProtoService comment name parts) = renderComment comment $$+ vbraces (PP.text "service" <+> pPrint name) (PP.vcat $ pPrint <$> parts) msgPart :: DotProtoIdentifier -> DotProtoMessagePart -> PP.Doc msgPart msgName (DotProtoMessageField f) = field msgName f@@ -118,7 +128,7 @@ = PP.text "reserved" <+> (PP.hcat . PP.punctuate (PP.text ", ") $ pPrint <$> reservations) <> PP.text ";"- msgPart msgName (DotProtoMessageOneOf name fields) = PP.text "oneof" <+> pPrint name <+> (PP.braces $ PP.vcat $ field msgName <$> fields)+ msgPart msgName (DotProtoMessageOneOf name fields) = vbraces (PP.text "oneof" <+> pPrint name) (PP.vcat $ field msgName <$> fields) field :: DotProtoIdentifier -> DotProtoField -> PP.Doc field msgName (DotProtoField number mtype name options comments)@@ -128,14 +138,14 @@ <+> pPrint number <+> optionAnnotation options <> PP.text ";"- <> maybe PP.empty (PP.text . (" // " ++)) comments+ $$ PP.nest 2 (renderComment comments) field _ DotProtoEmptyField = PP.empty enumPart :: DotProtoIdentifier -> DotProtoEnumPart -> PP.Doc enumPart msgName (DotProtoEnumField name value options) = roEnumMemberName opts msgName name <+> PP.text "="- <+> pPrint value+ <+> pPrint (fromIntegral value :: Int) <+> optionAnnotation options <> PP.text ";" enumPart _ (DotProtoEnumOption opt)@@ -144,15 +154,15 @@ = PP.empty instance Pretty DotProtoServicePart where- pPrint (DotProtoServiceRPC name (callname, callstrm) (retname, retstrm) options)+ pPrint (DotProtoServiceRPCMethod RPCMethod{..}) = PP.text "rpc"- <+> pPrint name- <+> PP.parens (pPrint callstrm <+> pPrint callname)+ <+> pPrint rpcMethodName+ <+> PP.parens (pPrint rpcMethodRequestStreaming <+> pPrint rpcMethodRequestType) <+> PP.text "returns"- <+> PP.parens (pPrint retstrm <+> pPrint retname)- <+> case options of+ <+> PP.parens (pPrint rpcMethodResponseStreaming <+> pPrint rpcMethodResponseType)+ <+> case rpcMethodOptions of [] -> PP.text ";"- _ -> PP.braces . PP.vcat $ topOption <$> options+ _ -> PP.braces . PP.vcat $ topOption <$> rpcMethodOptions pPrint (DotProtoServiceOption option) = topOption option pPrint DotProtoServiceEmpty = PP.empty @@ -162,7 +172,7 @@ instance Pretty DotProtoIdentifier where pPrint (Single name) = PP.text name- pPrint (Dots (Path names)) = PP.hcat . PP.punctuate (PP.text ".") $ PP.text <$> names+ pPrint (Dots (Path names)) = PP.hcat . PP.punctuate (PP.text ".") $ PP.text <$> NE.toList names pPrint (Qualified qualifier identifier) = PP.parens (pPrint qualifier) <> PP.text "." <> pPrint identifier pPrint Anonymous = PP.empty @@ -218,4 +228,4 @@ packageFromDefs :: String -> [DotProtoDefinition] -> DotProto packageFromDefs package defs =- DotProto [] [] (DotProtoPackageSpec $ Single package) defs (DotProtoMeta $ Path [])+ DotProto [] [] (DotProtoPackageSpec $ Single package) defs (DotProtoMeta fakePath)
src/Proto3/Suite/JSONPB/Class.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE RecordWildCards #-}@@ -92,11 +93,14 @@ import qualified Data.Text.Lazy.Encoding as TL import qualified Data.Vector as V import GHC.Exts (Proxy#, proxy#)+import GHC.Generics (Generic) import GHC.Int (Int32, Int64) import GHC.Word (Word32, Word64) import Proto3.Suite.Class (HasDefault (def, isDefault), Named (nameOf)) import Proto3.Suite.Types (Enumerated (..), Fixed (..))+import Proto3.Wire.Class (ProtoEnum(..))+import Test.QuickCheck.Arbitrary (Arbitrary(..)) -- * Typeclass definitions @@ -223,8 +227,11 @@ -- -- > MyMessage (Animal (Cat "Simba")) => { "animal": { "cat": "Simba" } } --- } deriving Show+ } deriving (Eq, Generic, Show) +instance Arbitrary Options where+ arbitrary = Options <$> arbitrary <*> arbitrary+ -- | Default options for JSON encoding. By default, all options are @True@. defaultOptions :: Options defaultOptions = Options@@ -477,7 +484,7 @@ toJSONPB = enumToJSONPB toJSONPB A.Null toEncodingPB = enumToJSONPB toEncodingPB E.null_ -instance (Bounded e, Enum e, FromJSONPB e) => FromJSONPB (Enumerated e) where+instance (ProtoEnum e, FromJSONPB e) => FromJSONPB (Enumerated e) where parseJSONPB A.Null = pure def -- So CG does not have to handle this case in -- every generated instance parseJSONPB v = Enumerated . Right <$> parseJSONPB v
src/Proto3/Suite/Tutorial.hs view
@@ -33,12 +33,13 @@ module Proto3.Suite.Tutorial where import Data.Int (Int32)-import Proto3.Suite (Enumerated, Nested, NestedVec, PackedVec,- Message, Named, Finite,- DotProtoDefinition, enum, message, packageFromDefs, toProtoFileDef) import Data.Word (Word32) import GHC.Exts (Proxy#, proxy#) import GHC.Generics+import Proto3.Suite (Enumerated, Nested, NestedVec, PackedVec,+ Message, Named, Finite, DotProtoDefinition,+ enum, message, packageFromDefs, toProtoFileDef)+import Proto3.Wire.Class (ProtoEnum) -- | -- == Defining Message Types@@ -92,20 +93,20 @@ -- | -- == Enumerations ----- Enumerated types can be used by deriving the 'Enum', 'Finite' and 'Named'--- classes. Each of these instances are implied by a 'Generic' instance, so can--- be derived as follows:+-- Enumerated types can be used by deriving the 'Bounded', 'Enum', 'ProtoEnum',+-- 'Finite', and 'Named' classes. Each of these instances are implied by+-- a 'Generic' instance, so can be derived as follows: -- -- > data Shape -- > = Circle -- > | Square -- > | Triangle--- > deriving (Generic, Enum, Finite, Named)+-- > deriving (Bounded, Eq, Enum, Finite, Generic, Named, Ord, ProtoEnum) data Shape = Circle | Square | Triangle- deriving (Bounded, Eq, Enum, Finite, Generic, Named, Ord)+ deriving (Bounded, Eq, Enum, Finite, Generic, Named, Ord, ProtoEnum) -- | -- == Generating a .proto file
src/Proto3/Suite/Types.hs view
@@ -31,9 +31,11 @@ import Control.DeepSeq (NFData) import GHC.Exts (IsList(..)) import GHC.Generics+import Data.Int (Int32) import Data.Semigroup (Semigroup) import qualified Data.Vector as V import GHC.TypeLits (Symbol)+import Proto3.Wire.Class (ProtoEnum(..)) import Test.QuickCheck (Arbitrary(..)) -- | 'Fixed' provides a way to encode integers in the fixed-width wire formats.@@ -48,16 +50,14 @@ -- | 'Enumerated' lifts any type with an 'IsEnum' instance so that it can be encoded -- with 'HasEncoding'.-newtype Enumerated a = Enumerated { enumerated :: Either Int a }+newtype Enumerated a = Enumerated { enumerated :: Either Int32 a } deriving (Show, Eq, Ord, Generic, NFData , Functor, Foldable, Traversable) -instance (Bounded a, Enum a) => Arbitrary (Enumerated a) where+instance ProtoEnum a => Arbitrary (Enumerated a) where arbitrary = do i <- arbitrary- if i < fromEnum (minBound :: a) || i > fromEnum (maxBound :: a)- then return $ Enumerated $ Left i- else return $ Enumerated $ Right (toEnum i)+ return . Enumerated $ maybe (Left i) Right (toProtoEnumMay i) -- | 'PackedVec' provides a way to encode packed lists of basic protobuf types into -- the wire format.
tests/ArbitraryGeneratedTestTypes.hs view
@@ -5,9 +5,9 @@ import qualified Data.Text.Lazy as T import qualified Data.Vector as V import qualified Proto3.Suite.Types as DotProto-import Test.QuickCheck (Arbitrary, arbitrary,- arbitraryBoundedEnum, listOf)+import Test.QuickCheck (Arbitrary, arbitrary, listOf) import qualified Test.QuickCheck as QC+import Test.QuickCheck.Arbitrary.Generic (genericArbitrary) import TestProto import qualified TestProtoImport import qualified TestProtoOneof@@ -27,7 +27,7 @@ <*> arbitrary instance Arbitrary WithEnum_TestEnum where- arbitrary = arbitraryBoundedEnum+ arbitrary = genericArbitrary instance Arbitrary WithEnum where arbitrary = WithEnum <$> arbitrary@@ -59,7 +59,7 @@ <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbEnums <*> arbEnums where- arbEnums = V.fromList <$> listOf (DotProto.Enumerated . Right <$> arbitraryBoundedEnum)+ arbEnums = V.fromList <$> listOf (DotProto.Enumerated . Right <$> genericArbitrary) instance Arbitrary SignedInts where arbitrary = SignedInts <$> arbitrary <*> arbitrary@@ -130,7 +130,7 @@ , TestProtoOneof.SomethingPickOneDummyMsg1 <$> arbitrary , TestProtoOneof.SomethingPickOneDummyMsg2 <$> arbitrary , TestProtoOneof.SomethingPickOneDummyEnum . DotProto.Enumerated . Right- <$> arbitraryBoundedEnum+ <$> genericArbitrary ] instance Arbitrary TestProtoOneof.WithImported where
tests/Main.hs view
@@ -13,6 +13,7 @@ import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString.Lazy as BL import Data.Either (isRight)+import qualified Data.List.NonEmpty as NE import Data.String import Data.Semigroup ((<>)) import GHC.Exts (fromList, Proxy#)@@ -50,7 +51,6 @@ #ifdef DHALL , dhallTests #endif- ] --------------------------------------------------------------------------------@@ -223,7 +223,8 @@ testDotProtoParse :: FilePath -> DotProto -> Assertion testDotProtoParse file ast = do contents <- readFile file- case parseProto (Path []) contents of+ let path = metaModulePath $ protoMeta ast+ case parseProto path contents of Left err -> error $ show err Right result -> ast @=? result @@ -232,7 +233,8 @@ testDotProtoRoundtrip :: DotProto -> Assertion testDotProtoRoundtrip ast =- Right ast @=? parseProto (Path []) (toProtoFileDef ast)+ let path = metaModulePath $ protoMeta ast in+ Right ast @=? parseProto path (toProtoFileDef ast) dotProtoUnitTests :: TestTree dotProtoUnitTests = testGroup ".proto parsing tests"@@ -244,7 +246,7 @@ ] trivialDotProto :: DotProto-trivialDotProto = DotProto [] [] DotProtoNoPackage [] (DotProtoMeta (Path []))+trivialDotProto = DotProto [] [] DotProtoNoPackage [] (DotProtoMeta (Path $ "test-files" NE.:| ["trivial"])) dotProtoParseTrivial :: TestTree dotProtoParseTrivial = testCase@@ -263,12 +265,12 @@ dotProtoSimpleMessage :: DotProto dotProtoSimpleMessage = DotProto [] [] DotProtoNoPackage- [ DotProtoMessage (Single "MessageTest")+ [ DotProtoMessage "" (Single "MessageTest") [ DotProtoMessageField $- DotProtoField (fieldNumber 1) (Prim Int32) (Single "testfield") [] Nothing+ DotProtoField (fieldNumber 1) (Prim Int32) (Single "testfield") [] "" ] ]- (DotProtoMeta (Path []))+ (DotProtoMeta (Path ("test-files" NE.:| ["simple"]))) dotProtoRoundtripSimpleMessage :: TestTree dotProtoRoundtripSimpleMessage = testCase@@ -281,7 +283,7 @@ where roundtrip :: DotProto -> Property roundtrip ast = let generated = toProtoFileDef ast- in case parseProto (Path []) generated of+ in case parseProto fakePath generated of Left err -> error $ formatParseError err generated Right result -> counterexample (formatMismatch ast generated result ) (ast == result) @@ -304,9 +306,10 @@ dotProtoFor :: (Named a, Message a) => Proxy# a -> DotProto dotProtoFor proxy = DotProto [] [] DotProtoNoPackage- [ DotProtoMessage (Single (nameOf proxy)) (DotProtoMessageField <$> dotProto proxy)+ [ DotProtoMessage+ "" (Single (nameOf proxy)) (DotProtoMessageField <$> dotProto proxy) ]- (DotProtoMeta (Path []))+ (DotProtoMeta (Path $ "mypath" NE.:| [])) showDotProtoFor :: (Named a, Message a) => Proxy# a -> IO () showDotProtoFor proxy = putStrLn . toProtoFileDef $ dotProtoFor proxy
tests/TestCodeGen.hs view
@@ -9,6 +9,7 @@ import ArbitraryGeneratedTestTypes () import Control.Applicative import Control.Monad+import Control.Monad.Except import qualified Data.Aeson import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Lazy.Char8 as LBS8@@ -20,6 +21,7 @@ import qualified Data.Text as T import Prelude hiding (FilePath) import Proto3.Suite.DotProto.Generate+import Proto3.Suite.DotProto (fieldLikeName, prefixedEnumFieldName, typeLikeName) import Proto3.Suite.JSONPB (FromJSONPB (..), Options (..), ToJSONPB (..), eitherDecode, encode, defaultOptions)@@ -41,19 +43,34 @@ camelCaseMessageNames :: TestTree camelCaseMessageNames = testGroup "CamelCasing of message names"- [ testCase "Capitalizes letters after underscores" (typeLikeName "protocol_analysis" @?= Right "ProtocolAnalysis")- , testCase "Preserves casing of interior letters" (typeLikeName "analyze_HTTP" @?= Right "AnalyzeHTTP")- , testCase "Handles non-alphanumeric characters after underscore" (typeLikeName "analyze_http_2" @?= Right "AnalyzeHttp2")- , testCase "Preserves one underscore in double underscore sequence" (typeLikeName "Analyze__HTTP" @?= Right "Analyze_HTTP")- , testCase "Handles names prefixed with underscore" (typeLikeName "_message_name" @?= Right "XMessageName")- , testCase "Preserves trailing underscore" (typeLikeName "message_name_" @?= Right "MessageName_") ]+ [ testCase "Capitalizes letters after underscores"+ $ typeLikeName "protocol_analysis" @?= Right "ProtocolAnalysis" + , testCase "Preserves casing of interior letters"+ $ typeLikeName "analyze_HTTP" @?= Right "AnalyzeHTTP" + , testCase "Handles non-alphanumeric characters after underscore"+ $ typeLikeName "analyze_http_2" @?= Right "AnalyzeHttp2"++ , testCase "Preserves one underscore in double underscore sequence"+ $ typeLikeName "Analyze__HTTP" @?= Right "Analyze_HTTP"++ , testCase "Handles names prefixed with underscore"+ $ typeLikeName "_message_name" @?= Right "XMessageName"++ , testCase "Preserves trailing underscore"+ $ typeLikeName "message_name_" @?= Right "MessageName_"+ ]+ camelCaseMessageFieldNames :: TestTree camelCaseMessageFieldNames = testGroup "camelCasing of field names"- [ testCase "Preserves capitalization patterns" (fieldLikeName "IP" @?= "ip")- , testCase "Preserves underscores" (fieldLikeName "IP_address" @?= "ip_address") ]+ [ testCase "Preserves capitalization patterns"+ $ fieldLikeName "IP" @?= "ip" + , testCase "Preserves underscores"+ $ fieldLikeName "IP_address" @?= "ip_address"+ ]+ don'tAlterEnumFieldNames :: TestTree don'tAlterEnumFieldNames = testGroup "Do not alter enumeration field names"@@ -67,13 +84,12 @@ ] where enumName = "MyEnum"- tc fieldName = testCase fieldName- $ prefixedEnumFieldName enumName fieldName- @?= (enumName <> fieldName)+ tc fieldName = testCase fieldName $+ prefixedEnumFieldName enumName fieldName @?= (enumName <> fieldName) setPythonPath :: IO ()-setPythonPath = Turtle.export "PYTHONPATH" =<< do- maybe pyTmpDir ((pyTmpDir <> ":") <>) <$> Turtle.need "PYTHONPATH"+setPythonPath = Turtle.export "PYTHONPATH" =<<+ maybe pyTmpDir (\p -> pyTmpDir <> ":" <> p) <$> Turtle.need "PYTHONPATH" simpleEncodeDotProto :: TestTree simpleEncodeDotProto =@@ -81,13 +97,13 @@ $ do compileTestDotProtos -- Compile our generated encoder- (@?= ExitSuccess) =<< Turtle.proc "tests/encode.sh" [hsTmpDir] empty+ Turtle.proc "tests/encode.sh" [hsTmpDir] empty >>= (@?= ExitSuccess) -- The python encoder test exits with a special error code to indicate -- all tests were successful setPythonPath let cmd = hsTmpDir <> "/simpleEncodeDotProto | python tests/check_simple_dot_proto.py"- (@?= ExitFailure 12) =<< Turtle.shell cmd empty+ Turtle.shell cmd empty >>= (@?= ExitFailure 12) -- Not using bracket so that we can inspect the output to fix the tests Turtle.rmtree hsTmpDir@@ -99,11 +115,11 @@ $ do compileTestDotProtos -- Compile our generated decoder- (@?= ExitSuccess) =<< Turtle.proc "tests/decode.sh" [hsTmpDir] empty+ Turtle.proc "tests/decode.sh" [hsTmpDir] empty >>= (@?= ExitSuccess) setPythonPath let cmd = "python tests/send_simple_dot_proto.py | " <> hsTmpDir <> "/simpleDecodeDotProto "- (@?= ExitSuccess) =<< Turtle.shell cmd empty+ Turtle.shell cmd empty >>= (@?= ExitSuccess) -- Not using bracket so that we can inspect the output to fix the tests Turtle.rmtree hsTmpDir@@ -113,10 +129,10 @@ -- E.g. dumpAST ["test-files"] "test_proto.proto" dumpAST :: [FilePath] -> FilePath -> IO ()-dumpAST incs fp = do- Right (dp, tc) <- readDotProtoWithContext incs fp- let Right src = renderHsModuleForDotProto mempty dp tc- putStrLn src+dumpAST incs fp = (either (error . show) putStrLn <=< runExceptT) $ do+ (dp, tc) <- readDotProtoWithContext incs fp+ src <- renderHsModuleForDotProto mempty dp tc+ pure src hsTmpDir, pyTmpDir :: IsString a => a hsTmpDir = "test-files/hs-tmp"@@ -126,22 +142,29 @@ compileTestDotProtos = do Turtle.mktree hsTmpDir Turtle.mktree pyTmpDir+ let protoFiles =+ [ "test_proto.proto"+ , "test_proto_import.proto"+ , "test_proto_oneof.proto"+ , "test_proto_oneof_import.proto"+ ]+ forM_ protoFiles $ \protoFile -> do- compileDotProtoFileOrDie [] hsTmpDir ["test-files"] protoFile- (@?= ExitSuccess) =<< Turtle.shell (T.concat [ "protoc --python_out="- , pyTmpDir- , " --proto_path=test-files"- , " test-files/" <> Turtle.format F.fp protoFile- ])- empty+ compileDotProtoFileOrDie+ CompileArgs{ includeDir = ["test-files"]+ , extraInstanceFiles = []+ , outputDir = hsTmpDir+ , inputProto = protoFile+ }++ let cmd = T.concat [ "protoc --python_out="+ , pyTmpDir+ , " --proto_path=test-files"+ , " test-files/" <> Turtle.format F.fp protoFile+ ]+ Turtle.shell cmd empty >>= (@?= ExitSuccess)+ Turtle.touch (pyTmpDir Turtle.</> "__init__.py")- where- protoFiles =- [ "test_proto.proto"- , "test_proto_import.proto"- , "test_proto_oneof.proto"- , "test_proto_oneof_import.proto"- ] -- * Doctests for JSONPB @@ -233,6 +256,17 @@ -- {"properties":{"dummy":{"maximum":2147483647,"format":"int32","minimum":-2147483648,"type":"integer"}},"type":"object"} -- >>> schemaOf @(Enumerated DummyEnum) -- {"type":"string","enum":["DUMMY0","DUMMY1"]}+--+-- Generic HasDefault+--+-- >>> def :: MultipleFields+-- MultipleFields {multipleFieldsMultiFieldDouble = 0.0, multipleFieldsMultiFieldFloat = 0.0, multipleFieldsMultiFieldInt32 = 0, multipleFieldsMultiFieldInt64 = 0, multipleFieldsMultiFieldString = "", multipleFieldsMultiFieldBool = False}+-- >>> def :: WithNesting+-- WithNesting {withNestingNestedMessage = Nothing}+-- >>> def :: WithNestingRepeated+-- WithNestingRepeated {withNestingRepeatedNestedMessages = []}+-- >>> def :: WithEnum+-- WithEnum {withEnumEnumField = Enumerated {enumerated = Right WithEnum_TestEnumENUM1}} -- * Helper quickcheck props
tools/canonicalize-proto-file/Main.hs view
@@ -13,7 +13,9 @@ module Main (main) where +import Control.Monad.Except import Data.List (sort, sortOn)+import qualified Data.List.NonEmpty as NE import Data.RangeSet.List (fromRangeList, toRangeList) import Data.Semigroup (Min(..), Option(..)) import Options.Generic@@ -34,7 +36,7 @@ main :: IO () main = do Args{..} :: Args Unwrapped <- unwrapRecord "Dumps a canonicalized .proto file to stdout"- readDotProtoWithContext includeDir proto >>= \case+ runExceptT (readDotProtoWithContext includeDir proto) >>= \case Left err -> fail (show err) Right (dp, _) -> putStr (toProtoFile defRenderingOptions (canonicalize dp)) @@ -83,18 +85,18 @@ instance CanonicalRank DotProtoDefinition (Int, DotProtoIdentifier) where canonicalRank = \case- DotProtoEnum name _ -> (1, name)- DotProtoMessage name _ -> (2, name)- DotProtoService name _ -> (3, name)+ DotProtoEnum _ name _ -> (1, name)+ DotProtoMessage _ name _ -> (2, name)+ DotProtoService _ name _ -> (3, name) instance Canonicalize DotProtoDefinition where canonicalize = \case- DotProtoMessage name parts ->- DotProtoMessage (canonicalize name) (canonicalize parts)- DotProtoEnum name parts ->- DotProtoEnum (canonicalize name) (canonicalize parts)- DotProtoService name parts ->- DotProtoService (canonicalize name) (canonicalize parts)+ DotProtoMessage _ name parts ->+ DotProtoMessage "" (canonicalize name) (canonicalize parts)+ DotProtoEnum _ name parts ->+ DotProtoEnum "" (canonicalize name) (canonicalize parts)+ DotProtoService _ name parts ->+ DotProtoService "" (canonicalize name) (canonicalize parts) instance Canonicalize [DotProtoMessagePart] where canonicalize parts = canonicalSort (resNumbers ++ resNames ++ other)@@ -157,8 +159,8 @@ , dotProtoFieldType = canonicalize dotProtoFieldType , dotProtoFieldName = canonicalize dotProtoFieldName , dotProtoFieldOptions = canonicalize dotProtoFieldOptions- , dotProtoFieldComment = Nothing -- In future we might add a command-line- -- option to preserve comments.+ , dotProtoFieldComment = "" -- In future we might add a command-line+ -- option to preserve comments. } canonicalize DotProtoEmptyField = DotProtoEmptyField @@ -214,22 +216,26 @@ instance CanonicalRank DotProtoServicePart (Either (Maybe DotProtoOption) DotProtoIdentifier) where canonicalRank = \case- DotProtoServiceRPC name _ _ _ -> Right name+ DotProtoServiceRPCMethod method -> Right (rpcMethodName method) DotProtoServiceOption option -> Left (Just option) DotProtoServiceEmpty -> Left Nothing instance Canonicalize DotProtoServicePart where canonicalize = \case- DotProtoServiceRPC name (reqN, reqS) (rspN, rspS) options ->- DotProtoServiceRPC (canonicalize name)- (canonicalize reqN, reqS)- (canonicalize rspN, rspS)- (canonicalize options)+ DotProtoServiceRPCMethod guts ->+ DotProtoServiceRPCMethod (canonicalize guts) DotProtoServiceOption option -> DotProtoServiceOption (canonicalize option) DotProtoServiceEmpty -> DotProtoServiceEmpty +instance Canonicalize RPCMethod where+ canonicalize (RPCMethod name reqN reqS rspN rspS options) =+ RPCMethod (canonicalize name)+ (canonicalize reqN) reqS+ (canonicalize rspN) rspS+ (canonicalize options)+ instance Canonicalize DotProtoValue where canonicalize = \case Identifier name -> Identifier (canonicalize name)@@ -241,7 +247,7 @@ instance Canonicalize DotProtoIdentifier where canonicalize = \case Single part -> Single part- Dots (Path [part]) -> Single part+ Dots (Path (part NE.:| [])) -> Single part Dots path -> Dots path Qualified x y -> Qualified (canonicalize x) (canonicalize y) Anonymous -> Anonymous
tools/compile-proto-file/Main.hs view
@@ -8,21 +8,36 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeOperators #-} -import Options.Generic+import Data.Semigroup ((<>))+import Options.Applicative import Prelude hiding (FilePath) import Proto3.Suite.DotProto.Generate-import Turtle (FilePath) -data Args w = Args- { out :: w ::: FilePath <?> "Output directory path where generated Haskell modules will be written (directory is created if it does not exist; note that files in the output directory may be overwritten!)"- , includeDir :: w ::: [FilePath] <?> "Path to search for included .proto files (can be repeated, and paths will be searched in order; the current directory is used if this option is not provided)"- , proto :: w ::: FilePath <?> "Path to input .proto file"- , extraInstanceFile :: w ::: [FilePath] <?> "Additional file to provide instances that would otherwise be generated. Can be used multiple times. Types for which instance overrides are given must be fully qualified."- } deriving Generic-instance ParseRecord (Args Wrapped)-deriving instance Show (Args Unwrapped)+parseArgs :: ParserInfo CompileArgs+parseArgs = info parser (fullDesc <> progDesc "Compiles a .proto file to a Haskell module")+ where+ parser = CompileArgs <$> includes <*> extraInstances <*> proto <*> out + includes = many $ strOption $+ long "includeDir"+ <> metavar "DIR"+ <> help "Path to search for included .proto files (can be repeated, and paths will be searched in order; the current directory is used if this option is not provided)"++ extraInstances = many $ strOption $+ long "extraInstanceFile"+ <> metavar "DIR"+ <> help "Additional file to provide instances that would otherwise be generated. Can be used multiple times. Types for which instance overrides are given must be fully qualified."++ proto = strOption $+ long "proto"+ <> metavar "FILE"+ <> help "Path to input .proto file"++ out = strOption $+ long "out"+ <> metavar "FILE"+ <> help "Output directory path where generated Haskell modules will be written (directory is created if it does not exist; note that files in the output directory may be overwritten!)"++ main :: IO ()-main = do- Args{..} :: Args Unwrapped <- unwrapRecord "Compiles a .proto file to a Haskell module"- compileDotProtoFileOrDie extraInstanceFile out includeDir proto+main = execParser parseArgs >>= compileDotProtoFileOrDie