hydra-ext-0.17.0: src/main/haskell/Hydra/Protobuf/Serde.hs
-- Note: this is an automatically generated file. Do not edit.
-- | Serialization functions for converting Protocol Buffers v3 AST to abstract expressions
module Hydra.Protobuf.Serde where
import qualified Hydra.Ast as Ast
import qualified Hydra.Coders as Coders
import qualified Hydra.Core as Core
import qualified Hydra.Error.Checking as Checking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Errors as Errors
import qualified Hydra.Formatting as Formatting
import qualified Hydra.Graph as Graph
import qualified Hydra.Json.Model as Model
import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals
import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Protobuf.Proto3 as Proto3
import qualified Hydra.Query as Query
import qualified Hydra.Relational as Relational
import qualified Hydra.Serialization as Serialization
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variants as Variants
import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci
-- | Convert a definition to an expression
definitionToExpr :: Proto3.Definition -> Ast.Expr
definitionToExpr def =
case def of
Proto3.DefinitionEnum v0 -> enumDefinitionToExpr v0
Proto3.DefinitionMessage v0 -> messageDefinitionToExpr v0
-- | The name of the deprecated option
deprecatedOptionName :: String
deprecatedOptionName = "deprecated"
-- | A special Protobuf option name for descriptions (documentation)
descriptionOptionName :: String
descriptionOptionName = "_description"
-- | Convert an enum definition to an expression
enumDefinitionToExpr :: Proto3.EnumDefinition -> Ast.Expr
enumDefinitionToExpr ed =
let name = Proto3.enumDefinitionName ed
values = Proto3.enumDefinitionValues ed
options = Proto3.enumDefinitionOptions ed
in (optDesc False options (Serialization.spaceSep [
Serialization.cst "enum",
(Serialization.cst (Proto3.unTypeName name)),
(protoBlock (Lists.map enumValueToExpr values))]))
-- | Convert an enum value to an expression
enumValueToExpr :: Proto3.EnumValue -> Ast.Expr
enumValueToExpr ev =
let name = Proto3.enumValueName ev
number = Proto3.enumValueNumber ev
options = Proto3.enumValueOptions ev
in (optDesc False options (semi (Serialization.spaceSep [
Serialization.cst (Proto3.unEnumValueName name),
(Serialization.cst "="),
(Serialization.cst (Literals.showInt32 number))])))
-- | Filter out internal options (those whose names start with underscore)
excludeInternalOptions :: [Proto3.Option] -> [Proto3.Option]
excludeInternalOptions opts =
Lists.filter (\opt -> Logic.not (Equality.equal (Optionals.fromOptional 0 (Strings.maybeCharAt 0 (Proto3.optionName opt))) 95)) opts
-- | Convert a field option to an expression
fieldOptionToExpr :: Proto3.Option -> Ast.Expr
fieldOptionToExpr opt =
let name = Proto3.optionName opt
value = Proto3.optionValue opt
in (Serialization.spaceSep [
Serialization.cst name,
(Serialization.cst "="),
(valueToExpr value)])
-- | Convert field options to an optional bracket-enclosed expression
fieldOptionsToExpr :: [Proto3.Option] -> Maybe Ast.Expr
fieldOptionsToExpr opts0 =
let opts = excludeInternalOptions opts0
in (Logic.ifElse (Lists.null opts) Nothing (Optionals.pure (Serialization.bracketList Serialization.inlineStyle (Lists.map fieldOptionToExpr opts))))
-- | Convert a field to an expression
fieldToExpr :: Proto3.Field -> Ast.Expr
fieldToExpr f =
let name = Proto3.fieldName f
typ = Proto3.fieldType f
num = Proto3.fieldNumber f
options = Proto3.fieldOptions f
in (optDesc False options (case typ of
Proto3.FieldTypeOneof v0 -> Serialization.spaceSep [
Serialization.cst "oneof",
(Serialization.cst (Proto3.unFieldName name)),
(protoBlock (Lists.map fieldToExpr v0))]
Proto3.FieldTypeMap v0 ->
let kt = Proto3.mapTypeKeys v0
vt = Proto3.mapTypeValues v0
in (semi (Serialization.spaceSep (Optionals.cat [
Optionals.pure (fieldTypeToExpr typ),
(Optionals.pure (Serialization.cst (Proto3.unFieldName name))),
(Optionals.pure (Serialization.cst "=")),
(Optionals.pure (Serialization.cst (Literals.showInt32 num))),
(fieldOptionsToExpr options)])))
Proto3.FieldTypeRepeated _ -> semi (Serialization.spaceSep (Optionals.cat [
Optionals.pure (fieldTypeToExpr typ),
(Optionals.pure (Serialization.cst (Proto3.unFieldName name))),
(Optionals.pure (Serialization.cst "=")),
(Optionals.pure (Serialization.cst (Literals.showInt32 num))),
(fieldOptionsToExpr options)]))
Proto3.FieldTypeSimple _ -> semi (Serialization.spaceSep (Optionals.cat [
Optionals.pure (fieldTypeToExpr typ),
(Optionals.pure (Serialization.cst (Proto3.unFieldName name))),
(Optionals.pure (Serialization.cst "=")),
(Optionals.pure (Serialization.cst (Literals.showInt32 num))),
(fieldOptionsToExpr options)]))))
-- | Convert a field type to an expression
fieldTypeToExpr :: Proto3.FieldType -> Ast.Expr
fieldTypeToExpr ftyp =
case ftyp of
Proto3.FieldTypeMap v0 ->
let kt = Proto3.mapTypeKeys v0
vt = Proto3.mapTypeValues v0
in (Serialization.noSep [
Serialization.cst "map",
(Serialization.angleBracesList Serialization.inlineStyle [
simpleTypeToExpr kt,
(simpleTypeToExpr vt)])])
Proto3.FieldTypeRepeated v0 -> Serialization.spaceSep [
Serialization.cst "repeated",
(simpleTypeToExpr v0)]
Proto3.FieldTypeSimple v0 -> simpleTypeToExpr v0
Proto3.FieldTypeOneof _ -> Serialization.cst "oneof"
-- | Convert a file-level option to an expression
fileOptionToExpr :: Proto3.Option -> Ast.Expr
fileOptionToExpr opt =
let name = Proto3.optionName opt
value = Proto3.optionValue opt
in (semi (Serialization.spaceSep [
Serialization.cst "option",
(Serialization.cst name),
(Serialization.cst "="),
(valueToExpr value)]))
-- | Convert file-level options to an optional newline-separated expression
fileOptionsToExpr :: [Proto3.Option] -> Maybe Ast.Expr
fileOptionsToExpr opts0 =
let opts = excludeInternalOptions opts0
in (Logic.ifElse (Lists.null opts) Nothing (Optionals.pure (Serialization.newlineSep (Lists.map fileOptionToExpr opts))))
-- | Convert a file reference to an import expression
importToExpr :: Proto3.FileReference -> Ast.Expr
importToExpr ref =
semi (Serialization.spaceSep [
Serialization.cst "import",
(Serialization.cst (Literals.showString (Proto3.unFileReference ref)))])
-- | Convert a message definition to an expression
messageDefinitionToExpr :: Proto3.MessageDefinition -> Ast.Expr
messageDefinitionToExpr md =
let name = Proto3.messageDefinitionName md
fields = Proto3.messageDefinitionFields md
options = Proto3.messageDefinitionOptions md
in (optDesc False options (Serialization.spaceSep [
Serialization.cst "message",
(Serialization.cst (Proto3.unTypeName name)),
(protoBlock (Lists.map fieldToExpr fields))]))
-- | Prepend an optional description comment to an expression
optDesc :: Bool -> [Proto3.Option] -> Ast.Expr -> Ast.Expr
optDesc doubleNewline opts expr =
let descs = Lists.filter (\opt -> Equality.equal (Proto3.optionName opt) "_description") opts
in (Optionals.cases (Lists.maybeHead descs) expr (\firstDesc ->
let descValue = Proto3.optionValue firstDesc
descStr =
case descValue of
Proto3.ValueBoolean v0 -> Logic.ifElse v0 "true" "false"
Proto3.ValueString v0 -> v0
commentLines =
Lists.map (\line -> Logic.ifElse (Equality.equal line "") "//" (Strings.cat2 "// " line)) (Strings.lines descStr)
comment = Serialization.cst (Strings.intercalate "\n" commentLines)
sep =
Logic.ifElse doubleNewline (Serialization.doubleNewlineSep [
comment,
expr]) (Serialization.newlineSep [
comment,
expr])
in sep))
-- | Wrap expressions in a curly-braced block with double-newline separation
protoBlock :: [Ast.Expr] -> Ast.Expr
protoBlock exprs =
Serialization.brackets Serialization.curlyBraces Serialization.fullBlockStyle (Serialization.doubleNewlineSep exprs)
-- | Convert a proto file to an expression
protoFileToExpr :: Proto3.ProtoFile -> Ast.Expr
protoFileToExpr pf =
let pkg = Proto3.protoFilePackage pf
imports = Proto3.protoFileImports pf
defs = Proto3.protoFileTypes pf
options = Proto3.protoFileOptions pf
headerSec =
Optionals.pure (Serialization.newlineSep [
semi (Serialization.cst "syntax = \"proto3\""),
(semi (Serialization.spaceSep [
Serialization.cst "package",
(Serialization.cst (Proto3.unPackageName pkg))]))])
importsSec =
Logic.ifElse (Lists.null imports) Nothing (Optionals.pure (Serialization.newlineSep (Lists.map importToExpr imports)))
options1 = Lists.filter (\opt -> Logic.not (Equality.equal (Proto3.optionName opt) "_description")) options
optionsSec = fileOptionsToExpr options1
defsSec =
Logic.ifElse (Lists.null defs) Nothing (Optionals.pure (Serialization.doubleNewlineSep (Lists.map definitionToExpr defs)))
in (optDesc True options (Serialization.doubleNewlineSep (Optionals.cat [
headerSec,
importsSec,
optionsSec,
defsSec])))
-- | Convert a scalar type to an expression
scalarTypeToExpr :: Proto3.ScalarType -> Ast.Expr
scalarTypeToExpr sct =
Serialization.cst (case sct of
Proto3.ScalarTypeBool -> "bool"
Proto3.ScalarTypeBytes -> "bytes"
Proto3.ScalarTypeDouble -> "double"
Proto3.ScalarTypeFixed32 -> "fixed32"
Proto3.ScalarTypeFixed64 -> "fixed64"
Proto3.ScalarTypeFloat -> "float"
Proto3.ScalarTypeInt32 -> "int32"
Proto3.ScalarTypeInt64 -> "int64"
Proto3.ScalarTypeSfixed32 -> "sfixed32"
Proto3.ScalarTypeSfixed64 -> "sfixed64"
Proto3.ScalarTypeSint32 -> "sint32"
Proto3.ScalarTypeSint64 -> "sint64"
Proto3.ScalarTypeString -> "string"
Proto3.ScalarTypeUint32 -> "uint32"
Proto3.ScalarTypeUint64 -> "uint64")
-- | Append a semicolon to an expression
semi :: Ast.Expr -> Ast.Expr
semi e =
Serialization.noSep [
e,
(Serialization.cst ";")]
-- | Convert a simple type to an expression
simpleTypeToExpr :: Proto3.SimpleType -> Ast.Expr
simpleTypeToExpr st =
case st of
Proto3.SimpleTypeReference v0 -> Serialization.cst (Proto3.unTypeName v0)
Proto3.SimpleTypeScalar v0 -> scalarTypeToExpr v0
-- | Convert a value to an expression
valueToExpr :: Proto3.Value -> Ast.Expr
valueToExpr v =
Serialization.cst (case v of
Proto3.ValueBoolean v0 -> Logic.ifElse v0 "true" "false"
Proto3.ValueString v0 -> Literals.showString v0)