From 053ab25296258e54e9656a5733841519b4312490 Mon Sep 17 00:00:00 2001 From: ScalaPB Docs Date: Mon, 31 Jan 2022 14:14:53 +0000 Subject: [PATCH] Deploy website - based on 6d6879d33ce14026330011431c5fd2465692cf9c --- 01a85c17.a89172fb.js => 01a85c17.9830584e.js | 0 031793e1.8f04ca57.js => 031793e1.372fcc9e.js | 0 0492aa7e.6b880dc3.js | 1 + 0492aa7e.9127b90f.js | 1 - 0f622c7a.0b2cac4b.js | 1 - 0f622c7a.bd47421b.js | 1 + 1.d720bdf5.js => 1.d1f2961e.js | 2 +- 10204607.1aebdf1e.js | 1 + 10204607.43c74fed.js | 1 - 17896441.4206d928.js => 17896441.4580ba69.js | 2 +- 1b891fa3.ebf3f902.js | 1 - 1b891fa3.f599a486.js | 1 + 1d35a65b.bfc2dd20.js | 1 + 1d35a65b.c4cddcff.js | 1 - 2.5b37da85.js | 2 - 2.f4df6e70.js | 2 + ...s.LICENSE.txt => 2.f4df6e70.js.LICENSE.txt | 0 26672fd6.c8be9bb4.js | 1 + 26672fd6.fb0d6b85.js | 1 - 2868cdab.1222fb38.js => 2868cdab.fe247b46.js | 2 +- 28fe488f.31fdc0dc.js | 1 + 28fe488f.d5b3fa30.js | 1 - 3.5a4cea5d.js | 1 - 3.70d70172.js | 1 + 30a24c52.7f51d313.js => 30a24c52.48f86123.js | 0 30c1f25e.69e9b373.js | 1 + 30c1f25e.cc03965a.js | 1 - 3570154c.42857bb2.js => 3570154c.1ff3f249.js | 2 +- 3784e0de.15fd4185.js | 1 - 3784e0de.f9edd92e.js | 1 + 3a4cb4c8.713c5d5a.js | 1 + 3a4cb4c8.f649c61c.js | 1 - 404.html | 14 ++--- 409a7ded.c0c8198c.js | 1 + 409a7ded.ef9fca60.js | 1 - 44966442.ef8626a8.js | 1 - 44966442.f1ad2ae6.js | 1 + 49.50d7d611.js | 1 + 49.555e99e2.js | 1 - 50.7731d502.js => 50.a4265ab1.js | 0 5ee2bf2d.16191403.js | 1 + 5ee2bf2d.6801c681.js | 1 - 63f1a026.a4a1f87b.js | 1 - 63f1a026.a79c8deb.js | 1 + 6875c492.d2810576.js => 6875c492.c05025fc.js | 0 6a102a11.51224351.js | 1 + 6a102a11.d36bda6a.js | 1 - 7969e6ea.a1c65481.js | 1 + 7969e6ea.d3a0533f.js | 1 - 8e9f0a8a.ca897eff.js => 8e9f0a8a.d92b55c2.js | 2 +- 91ea4504.28e6c1c8.js | 1 - 91ea4504.dd0df415.js | 1 + 935f2afb.5e094e5e.js => 935f2afb.5b2cd0a8.js | 0 9dcf530e.30e5d8a8.js | 1 - 9dcf530e.e5b7c6fc.js | 1 + a6aa9e1f.0848dbf3.js => a6aa9e1f.8f1f5a6b.js | 2 +- a7023ddc.400a3306.js => a7023ddc.5979d515.js | 0 a80da1cf.19728128.js => a80da1cf.34d1a551.js | 0 af172acd.8b232b46.js | 1 + af172acd.f838b0d0.js | 1 - b2b675dd.b282ec91.js => b2b675dd.e28b341a.js | 0 b681c370.0c3c262c.js | 1 + b681c370.13a70afa.js | 1 - bdd709f1.66112bae.js | 1 - bdd709f1.bbd24846.js | 1 + blog/2019/05/28/hola/index.html | 38 ++++++------ blog/2019/05/29/hello-world/index.html | 38 ++++++------ blog/2019/05/30/welcome/index.html | 38 ++++++------ blog/index.html | 50 ++++++++-------- blog/tags/docusaurus/index.html | 50 ++++++++-------- blog/tags/facebook/index.html | 42 ++++++------- blog/tags/hello/index.html | 46 +++++++-------- blog/tags/hola/index.html | 42 ++++++------- blog/tags/index.html | 34 +++++------ c0a0cb68.6772e505.js | 1 + c0a0cb68.b974e41e.js | 1 - c101867e.5628b7ba.js | 1 + c101867e.9ded73fc.js | 1 - c4f5d8e4.40138c2c.js => c4f5d8e4.ba7f0d26.js | 2 +- ccc49370.4e5ff17e.js | 1 + ccc49370.64dea868.js | 1 - d0d9f8e7.65c50e91.js | 1 - d0d9f8e7.8a2fee4e.js | 1 + d610846f.02ab080a.js | 1 + d610846f.83e0654c.js | 1 - dfbf1396.91821922.js => dfbf1396.a0d6fa98.js | 0 docs/common-protos/index.html | 42 ++++++------- docs/contact/index.html | 42 ++++++------- docs/customizations/index.html | 42 ++++++------- docs/dotty/index.html | 42 ++++++------- docs/faq/index.html | 42 ++++++------- docs/generated-code/index.html | 42 ++++++------- docs/generic/index.html | 42 ++++++------- docs/getting-started/index.html | 42 ++++++------- docs/grpc/index.html | 42 ++++++------- docs/index.html | 42 ++++++------- docs/installation/index.html | 42 ++++++------- docs/json/index.html | 52 ++++++++-------- docs/sbt-settings/index.html | 42 ++++++------- docs/scala.js/index.html | 42 ++++++------- docs/scalapbc/index.html | 42 ++++++------- docs/sealed-oneofs/index.html | 42 ++++++------- docs/sparksql/index.html | 59 +++++++++++-------- docs/third-party-protos/index.html | 42 ++++++------- docs/transformations/index.html | 42 ++++++------- docs/upgrading/index.html | 42 ++++++------- docs/user_defined_options/index.html | 42 ++++++------- docs/validation/index.html | 42 ++++++------- docs/writing-plugins/index.html | 42 ++++++------- e16015ca.a4c8d715.js => e16015ca.130c2bd6.js | 0 e901dba7.88a54853.js | 1 + e901dba7.a606b5a1.js | 1 - index.html | 26 ++++---- main.a3b1c0bb.js | 2 - main.b1efec4c.js | 2 + ...ICENSE.txt => main.b1efec4c.js.LICENSE.txt | 0 ...in.9b3622c0.js => runtime~main.996f925a.js | 2 +- styles.e145afce.js => styles.022ff8f0.js | 0 styles.0bbc50d2.css | 1 + styles.189e0da9.css | 1 - 120 files changed, 751 insertions(+), 744 deletions(-) rename 01a85c17.a89172fb.js => 01a85c17.9830584e.js (100%) rename 031793e1.8f04ca57.js => 031793e1.372fcc9e.js (100%) create mode 100644 0492aa7e.6b880dc3.js delete mode 100644 0492aa7e.9127b90f.js delete mode 100644 0f622c7a.0b2cac4b.js create mode 100644 0f622c7a.bd47421b.js rename 1.d720bdf5.js => 1.d1f2961e.js (98%) create mode 100644 10204607.1aebdf1e.js delete mode 100644 10204607.43c74fed.js rename 17896441.4206d928.js => 17896441.4580ba69.js (68%) delete mode 100644 1b891fa3.ebf3f902.js create mode 100644 1b891fa3.f599a486.js create mode 100644 1d35a65b.bfc2dd20.js delete mode 100644 1d35a65b.c4cddcff.js delete mode 100644 2.5b37da85.js create mode 100644 2.f4df6e70.js rename 2.5b37da85.js.LICENSE.txt => 2.f4df6e70.js.LICENSE.txt (100%) create mode 100644 26672fd6.c8be9bb4.js delete mode 100644 26672fd6.fb0d6b85.js rename 2868cdab.1222fb38.js => 2868cdab.fe247b46.js (61%) create mode 100644 28fe488f.31fdc0dc.js delete mode 100644 28fe488f.d5b3fa30.js delete mode 100644 3.5a4cea5d.js create mode 100644 3.70d70172.js rename 30a24c52.7f51d313.js => 30a24c52.48f86123.js (100%) create mode 100644 30c1f25e.69e9b373.js delete mode 100644 30c1f25e.cc03965a.js rename 3570154c.42857bb2.js => 3570154c.1ff3f249.js (54%) delete mode 100644 3784e0de.15fd4185.js create mode 100644 3784e0de.f9edd92e.js create mode 100644 3a4cb4c8.713c5d5a.js delete mode 100644 3a4cb4c8.f649c61c.js create mode 100644 409a7ded.c0c8198c.js delete mode 100644 409a7ded.ef9fca60.js delete mode 100644 44966442.ef8626a8.js create mode 100644 44966442.f1ad2ae6.js create mode 100644 49.50d7d611.js delete mode 100644 49.555e99e2.js rename 50.7731d502.js => 50.a4265ab1.js (100%) create mode 100644 5ee2bf2d.16191403.js delete mode 100644 5ee2bf2d.6801c681.js delete mode 100644 63f1a026.a4a1f87b.js create mode 100644 63f1a026.a79c8deb.js rename 6875c492.d2810576.js => 6875c492.c05025fc.js (100%) create mode 100644 6a102a11.51224351.js delete mode 100644 6a102a11.d36bda6a.js create mode 100644 7969e6ea.a1c65481.js delete mode 100644 7969e6ea.d3a0533f.js rename 8e9f0a8a.ca897eff.js => 8e9f0a8a.d92b55c2.js (63%) delete mode 100644 91ea4504.28e6c1c8.js create mode 100644 91ea4504.dd0df415.js rename 935f2afb.5e094e5e.js => 935f2afb.5b2cd0a8.js (100%) delete mode 100644 9dcf530e.30e5d8a8.js create mode 100644 9dcf530e.e5b7c6fc.js rename a6aa9e1f.0848dbf3.js => a6aa9e1f.8f1f5a6b.js (95%) rename a7023ddc.400a3306.js => a7023ddc.5979d515.js (100%) rename a80da1cf.19728128.js => a80da1cf.34d1a551.js (100%) create mode 100644 af172acd.8b232b46.js delete mode 100644 af172acd.f838b0d0.js rename b2b675dd.b282ec91.js => b2b675dd.e28b341a.js (100%) create mode 100644 b681c370.0c3c262c.js delete mode 100644 b681c370.13a70afa.js delete mode 100644 bdd709f1.66112bae.js create mode 100644 bdd709f1.bbd24846.js create mode 100644 c0a0cb68.6772e505.js delete mode 100644 c0a0cb68.b974e41e.js create mode 100644 c101867e.5628b7ba.js delete mode 100644 c101867e.9ded73fc.js rename c4f5d8e4.40138c2c.js => c4f5d8e4.ba7f0d26.js (98%) create mode 100644 ccc49370.4e5ff17e.js delete mode 100644 ccc49370.64dea868.js delete mode 100644 d0d9f8e7.65c50e91.js create mode 100644 d0d9f8e7.8a2fee4e.js create mode 100644 d610846f.02ab080a.js delete mode 100644 d610846f.83e0654c.js rename dfbf1396.91821922.js => dfbf1396.a0d6fa98.js (100%) rename e16015ca.a4c8d715.js => e16015ca.130c2bd6.js (100%) create mode 100644 e901dba7.88a54853.js delete mode 100644 e901dba7.a606b5a1.js delete mode 100644 main.a3b1c0bb.js create mode 100644 main.b1efec4c.js rename main.a3b1c0bb.js.LICENSE.txt => main.b1efec4c.js.LICENSE.txt (100%) rename runtime~main.9b3622c0.js => runtime~main.996f925a.js (60%) rename styles.e145afce.js => styles.022ff8f0.js (100%) create mode 100644 styles.0bbc50d2.css delete mode 100644 styles.189e0da9.css diff --git a/01a85c17.a89172fb.js b/01a85c17.9830584e.js similarity index 100% rename from 01a85c17.a89172fb.js rename to 01a85c17.9830584e.js diff --git a/031793e1.8f04ca57.js b/031793e1.372fcc9e.js similarity index 100% rename from 031793e1.8f04ca57.js rename to 031793e1.372fcc9e.js diff --git a/0492aa7e.6b880dc3.js b/0492aa7e.6b880dc3.js new file mode 100644 index 000000000..e90bc440f --- /dev/null +++ b/0492aa7e.6b880dc3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{119:function(e,a,t){"use strict";t.d(a,"a",(function(){return b})),t.d(a,"b",(function(){return u}));var n=t(0),r=t.n(n);function s(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function o(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);a&&(n=n.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var a=1;a=0||(r[t]=e[t]);return r}(e,a);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var i=r.a.createContext({}),c=function(e){var a=r.a.useContext(i),t=a;return e&&(t="function"==typeof e?e(a):l(l({},a),e)),t},b=function(e){var a=c(e.components);return r.a.createElement(i.Provider,{value:a},e.children)},d={inlineCode:"code",wrapper:function(e){var a=e.children;return r.a.createElement(r.a.Fragment,{},a)}},m=r.a.forwardRef((function(e,a){var t=e.components,n=e.mdxType,s=e.originalType,o=e.parentName,i=p(e,["components","mdxType","originalType","parentName"]),b=c(t),m=n,u=b["".concat(o,".").concat(m)]||b[m]||d[m]||s;return t?r.a.createElement(u,l(l({ref:a},i),{},{components:t})):r.a.createElement(u,l({ref:a},i))}));function u(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var s=t.length,o=new Array(s);o[0]=m;var l={};for(var p in a)hasOwnProperty.call(a,p)&&(l[p]=a[p]);l.originalType=e,l.mdxType="string"==typeof e?e:n,o[1]=l;for(var i=2;i<none> is not a term",id:"datasets-and-none-is-not-a-term",children:[]},{value:"Example",id:"example",children:[]}],c={toc:i};function b(e){var a=e.components,t=Object(r.a)(e,o);return Object(s.b)("wrapper",Object(n.a)({},c,t,{components:a,mdxType:"MDXLayout"}),Object(s.b)("h2",{id:"introduction"},"Introduction"),Object(s.b)("p",null,"By default, Spark uses reflection to derive schemas and encoders from case\nclasses. This doesn't work well when there are messages that contain types that\nSpark does not understand such as enums, ",Object(s.b)("inlineCode",{parentName:"p"},"ByteString"),"s and ",Object(s.b)("inlineCode",{parentName:"p"},"oneof"),"s. To get around this, sparksql-scalapb provides its own ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder"),"s for protocol buffers."),Object(s.b)("p",null,"However, it turns out there is another obstacle. Spark does not provide any mechanism to compose user-provided encoders with its own reflection-derived Encoders. Therefore, merely providing an ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder")," for protocol buffers is insufficient to derive an encoder for regular case-classes that contain a protobuf as a field. To solve this problem, ScalaPB uses ",Object(s.b)("a",{parentName:"p",href:"https://github.com/typelevel/frameless"},"frameless")," which relies on implicit search to derive encoders. This approach enables combining ScalaPB's encoders with frameless encoders that takes care for all non-protobuf types."),Object(s.b)("h2",{id:"setting-up-your-project"},"Setting up your project"),Object(s.b)("p",null,"We are going to use sbt-assembly to deploy a fat JAR containing ScalaPB, and\nyour compiled protos. Make sure in project/plugins.sbt you have a line\nthat adds sbt-assembly:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")\n')),Object(s.b)("p",null,"To add sparksql-scalapb to your project, add ",Object(s.b)("em",{parentName:"p"},"one")," of the following lines that\nmatches ",Object(s.b)("em",{parentName:"p"},"both the version of ScalaPB and Spark")," you use:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'// Spark 3.2 and ScalaPB 0.11\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql32-scalapb0_11" % "1.0.0-M1"\n\n// Spark 3.1 and ScalaPB 0.11\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql31-scalapb0_11" % "1.0.0-M1"\n\n// Spark 3.0 and ScalaPB 0.11\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql30-scalapb0_11" % "1.0.0-M1"\n\n// Spark 3.2 and ScalaPB 0.10\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql32-scalapb0_10" % "1.0.0-M1"\n\n// Spark 3.1 and ScalaPB 0.10\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql31-scalapb0_10" % "1.0.0-M1"\n\n// Spark 3.0 and ScalaPB 0.10\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql30-scalapb0_10" % "1.0.0-M1"\n\n// Spark 2.x and ScalaPB 0.10\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.10.4"\n\n// Spark 2.x and ScalaPB 0.9\nlibraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.9.3"\n')),Object(s.b)("p",null,"Spark ships with an old version of Google's Protocol Buffers runtime that is not compatible with\nthe current version. Therefore, we need to shade our copy of the Protocol Buffer runtime. Spark 3\nalso ships with an incompatible version of scala-collection-compat. Add the following to your\nbuild.sbt:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'assemblyShadeRules in assembly := Seq(\n ShadeRule.rename("com.google.protobuf.**" -> "shadeproto.@1").inAll,\n ShadeRule.rename("scala.collection.compat.**" -> "shadecompat.@1").inAll\n)\n')),Object(s.b)("p",null,"See ",Object(s.b)("a",{parentName:"p",href:"https://github.com/thesamet/sparksql-scalapb-test/blob/master/build.sbt"},"complete example of build.sbt"),"."),Object(s.b)("h2",{id:"using-sparksql-scalapb"},"Using sparksql-scalapb"),Object(s.b)("p",null,"We assume you have a ",Object(s.b)("inlineCode",{parentName:"p"},"SparkSession")," assigned to the variable ",Object(s.b)("inlineCode",{parentName:"p"},"spark"),". In a standalone Scala program, this can be created with:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'import org.apache.spark.sql.SparkSession\n\nval spark: SparkSession = SparkSession\n .builder()\n .appName("ScalaPB Demo")\n .master("local[2]")\n .getOrCreate()\n// spark: SparkSession = org.apache.spark.sql.SparkSession@25fc57af\n')),Object(s.b)("p",null,Object(s.b)("em",{parentName:"p"},"IMPORTANT"),": Ensure you do not import ",Object(s.b)("inlineCode",{parentName:"p"},"spark.implicits._")," to avoid ambiguity between ScalaPB provided encoders and Spark's default encoders. You may want to import ",Object(s.b)("inlineCode",{parentName:"p"},"StringToColumn")," to convert ",Object(s.b)("inlineCode",{parentName:"p"},'$"col name"')," into a ",Object(s.b)("inlineCode",{parentName:"p"},"Column"),". Add an import ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits")," to add ScalaPB's encoders for protocol buffers into the implicit search scope:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"import org.apache.spark.sql.{Dataset, DataFrame, functions => F}\nimport spark.implicits.StringToColumn\nimport scalapb.spark.ProtoSQL\n\nimport scalapb.spark.Implicits._\n")),Object(s.b)("p",null,"The code snippets below use the ",Object(s.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/blob/master/docs/src/main/protobuf/person.proto"},Object(s.b)("inlineCode",{parentName:"a"},"Person")," message"),"."),Object(s.b)("p",null,"We start by creating some test data:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'import scalapb.docs.person.Person\nimport scalapb.docs.person.Person.{Address, AddressType}\n\nval testData = Seq(\n Person(name="John", age=32, addresses=Vector(\n Address(addressType=AddressType.HOME, street="Market", city="SF"))\n ),\n Person(name="Mike", age=29, addresses=Vector(\n Address(addressType=AddressType.WORK, street="Castro", city="MV"),\n Address(addressType=AddressType.HOME, street="Church", city="MV"))\n ),\n Person(name="Bart", age=27)\n)\n')),Object(s.b)("p",null,"We can create a ",Object(s.b)("inlineCode",{parentName:"p"},"DataFrame")," from the test data:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"val df = ProtoSQL.createDataFrame(spark, testData)\n// df: DataFrame = [name: string, age: int ... 1 more field]\ndf.printSchema()\n// root\n// |-- name: string (nullable = true)\n// |-- age: integer (nullable = true)\n// |-- addresses: array (nullable = false)\n// | |-- element: struct (containsNull = false)\n// | | |-- address_type: string (nullable = true)\n// | | |-- street: string (nullable = true)\n// | | |-- city: string (nullable = true)\n// \ndf.show()\n// +----+---+--------------------+\n// |name|age| addresses|\n// +----+---+--------------------+\n// |John| 32|[{HOME, Market, SF}]|\n// |Mike| 29|[{WORK, Castro, M...|\n// |Bart| 27| []|\n// +----+---+--------------------+\n//\n")),Object(s.b)("p",null,"and then process it as any other Dataframe in Spark:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'df.select($"name", F.size($"addresses").alias("address_count")).show()\n// +----+-------------+\n// |name|address_count|\n// +----+-------------+\n// |John| 1|\n// |Mike| 2|\n// |Bart| 0|\n// +----+-------------+\n// \n\nval nameAndAddress = df.select($"name", $"addresses".getItem(0).alias("firstAddress"))\n// nameAndAddress: DataFrame = [name: string, firstAddress: struct]\n\nnameAndAddress.show()\n// +----+------------------+\n// |name| firstAddress|\n// +----+------------------+\n// |John|{HOME, Market, SF}|\n// |Mike|{WORK, Castro, MV}|\n// |Bart| null|\n// +----+------------------+\n//\n')),Object(s.b)("p",null,"Using the datasets API it is possible to bring the data back to ScalaPB case classes:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"nameAndAddress.as[(String, Option[Address])].collect().foreach(println)\n// (John,Some(Address(HOME,Market,SF,UnknownFieldSet(Map()))))\n// (Mike,Some(Address(WORK,Castro,MV,UnknownFieldSet(Map()))))\n// (Bart,None)\n")),Object(s.b)("p",null,"You can create a Dataset directly using Spark APIs:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"spark.createDataset(testData)\n// res5: Dataset[Person] = [name: string, age: int ... 1 more field]\n")),Object(s.b)("h2",{id:"from-binary-to-protos-and-back"},"From Binary to protos and back"),Object(s.b)("p",null,"In some situations, you may need to deal with datasets that contain serialized protocol buffers. This can be handled by mapping the datasets through ScalaPB's ",Object(s.b)("inlineCode",{parentName:"p"},"parseFrom")," and ",Object(s.b)("inlineCode",{parentName:"p"},"toByteArray")," functions."),Object(s.b)("p",null,"Let's start by preparing a dataset with test binary data by mapping our ",Object(s.b)("inlineCode",{parentName:"p"},"testData"),":"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"val binaryDS: Dataset[Array[Byte]] = spark.createDataset(testData.map(_.toByteArray))\n// binaryDS: Dataset[Array[Byte]] = [value: binary]\n\nbinaryDS.show()\n// +--------------------+\n// | value|\n// +--------------------+\n// |[0A 04 4A 6F 68 6...|\n// |[0A 04 4D 69 6B 6...|\n// |[0A 04 42 61 72 7...|\n// +--------------------+\n//\n")),Object(s.b)("p",null,"To turn this dataset into a ",Object(s.b)("inlineCode",{parentName:"p"},"Dataset[Person]"),", we map it through ",Object(s.b)("inlineCode",{parentName:"p"},"parseFrom"),":"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"val protosDS: Dataset[Person] = binaryDS.map(Person.parseFrom(_))\n// protosDS: Dataset[Person] = [name: string, age: int ... 1 more field]\n")),Object(s.b)("p",null,"to turn a dataset of protos into ",Object(s.b)("inlineCode",{parentName:"p"},"Dataset[Array[Byte]]"),":"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"val protosBinary: Dataset[Array[Byte]] = protosDS.map(_.toByteArray)\n// protosBinary: Dataset[Array[Byte]] = [value: binary]\n")),Object(s.b)("h2",{id:"on-enums"},"On enums"),Object(s.b)("p",null,"In SparkSQL-ScalaPB, enums are represented as strings. Unrecognized enum values are represented as strings containing the numeric value."),Object(s.b)("h2",{id:"dataframes-and-datasets-from-rdds"},"Dataframes and Datasets from RDDs"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},"import org.apache.spark.rdd.RDD\n\nval protoRDD: RDD[Person] = spark.sparkContext.parallelize(testData)\n\nval protoDF: DataFrame = ProtoSQL.protoToDataFrame(spark, protoRDD)\n\nval protoDS: Dataset[Person] = spark.createDataset(protoRDD)\n")),Object(s.b)("h2",{id:"udfs"},"UDFs"),Object(s.b)("p",null,"If you need to write a UDF that returns a message, it would not pick up our encoder and you may get a runtime failure. To work around this, sparksql-scalapb provides ",Object(s.b)("inlineCode",{parentName:"p"},"ProtoSQL.udf")," to create UDFs. For example, if you need to parse a binary column into a proto:"),Object(s.b)("pre",null,Object(s.b)("code",{parentName:"pre",className:"language-scala"},'val binaryDF = protosBinary.toDF("value")\n// binaryDF: DataFrame = [value: binary]\n\nval parsePersons = ProtoSQL.udf { bytes: Array[Byte] => Person.parseFrom(bytes) }\n// parsePersons: org.apache.spark.sql.Column => org.apache.spark.sql.Column = scalapb.spark.Udfs$$Lambda$11321/1255281891@7d1d1ae5\n\nbinaryDF.withColumn("person", parsePersons($"value"))\n// res7: DataFrame = [value: binary, person: struct]\n')),Object(s.b)("h2",{id:"primitive-wrappers"},"Primitive wrappers"),Object(s.b)("p",null,"In ProtoSQL 0.9.x and 0.10.x, primitive wrappers are represented in Spark as structs\nwitha single field named ",Object(s.b)("inlineCode",{parentName:"p"},"value"),". A better representation in Spark would be a\nnullable field of the primitive type. The better representation will be the\ndefault in 0.11.x. To enable this representation today, replace the usages of\n",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL")," with ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL.withPrimitiveWrappers"),".\nInstead of importing ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits._"),", import\n",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL.implicits._")),Object(s.b)("p",null,"See example in ",Object(s.b)("a",{parentName:"p",href:"https://github.com/scalapb/sparksql-scalapb/blob/80f3162b69313d57f95d3dcbfee865809873567a/sparksql-scalapb/src/test/scala/WrappersSpec.scala#L42-L59"},"WrappersSpec"),"."),Object(s.b)("h2",{id:"datasets-and-none-is-not-a-term"},"Datasets and ",Object(s.b)("inlineCode",{parentName:"h2"}," is not a term")),Object(s.b)("p",null,"You will see this error if for some reason Spark's ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder"),"s are being picked up\ninstead of the ones provided by sparksql-scalapb. Please ensure you are not importing ",Object(s.b)("inlineCode",{parentName:"p"},"spark.implicits._"),". See instructions above for imports."),Object(s.b)("h2",{id:"example"},"Example"),Object(s.b)("p",null,"Check out a ",Object(s.b)("a",{parentName:"p",href:"https://github.com/thesamet/sparksql-scalapb-test"},"complete example")," here."))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/0492aa7e.9127b90f.js b/0492aa7e.9127b90f.js deleted file mode 100644 index b49eb1ebd..000000000 --- a/0492aa7e.9127b90f.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{119:function(e,a,t){"use strict";t.d(a,"a",(function(){return b})),t.d(a,"b",(function(){return u}));var n=t(0),r=t.n(n);function s(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function o(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);a&&(n=n.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var a=1;a=0||(r[t]=e[t]);return r}(e,a);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=r.a.createContext({}),i=function(e){var a=r.a.useContext(p),t=a;return e&&(t="function"==typeof e?e(a):l(l({},a),e)),t},b=function(e){var a=i(e.components);return r.a.createElement(p.Provider,{value:a},e.children)},d={inlineCode:"code",wrapper:function(e){var a=e.children;return r.a.createElement(r.a.Fragment,{},a)}},m=r.a.forwardRef((function(e,a){var t=e.components,n=e.mdxType,s=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=i(t),m=n,u=b["".concat(o,".").concat(m)]||b[m]||d[m]||s;return t?r.a.createElement(u,l(l({ref:a},p),{},{components:t})):r.a.createElement(u,l({ref:a},p))}));function u(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var s=t.length,o=new Array(s);o[0]=m;var l={};for(var c in a)hasOwnProperty.call(a,c)&&(l[c]=a[c]);l.originalType=e,l.mdxType="string"==typeof e?e:n,o[1]=l;for(var p=2;p<none> is not a term",id:"datasets-and-none-is-not-a-term",children:[]},{value:"Example",id:"example",children:[]}],p={toc:c};function i(e){var a=e.components,t=Object(r.a)(e,["components"]);return Object(s.b)("wrapper",Object(n.a)({},p,t,{components:a,mdxType:"MDXLayout"}),Object(s.b)("h2",{id:"introduction"},"Introduction"),Object(s.b)("p",null,"By default, Spark uses reflection to derive schemas and encoders from case\nclasses. This doesn't work well when there are messages that contain types that\nSpark does not understand such as enums, ",Object(s.b)("inlineCode",{parentName:"p"},"ByteString"),"s and ",Object(s.b)("inlineCode",{parentName:"p"},"oneof"),"s. To get around this, sparksql-scalapb provides its own ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder"),"s for protocol buffers."),Object(s.b)("p",null,"However, it turns out there is another obstacle. Spark does not provide any mechanism to compose user-provided encoders with its own reflection-derived Encoders. Therefore, merely providing an ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder")," for protocol buffers is insufficient to derive an encoder for regular case-classes that contain a protobuf as a field. To solve this problem, ScalaPB uses ",Object(s.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/typelevel/frameless"}),"frameless")," which relies on implicit search to derive encoders. This approach enables combining ScalaPB's encoders with frameless encoders that takes care for all non-protobuf types."),Object(s.b)("h2",{id:"setting-up-your-project"},"Setting up your project"),Object(s.b)("p",null,"The version of sparksql-scalapb needs to match the Spark and\nScalaPB version:"),Object(s.b)("table",null,Object(s.b)("thead",{parentName:"table"},Object(s.b)("tr",{parentName:"thead"},Object(s.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"Spark"),Object(s.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"ScalaPB"),Object(s.b)("th",Object(n.a)({parentName:"tr"},{align:null}),"SparkSQL-ScalaPB"))),Object(s.b)("tbody",{parentName:"table"},Object(s.b)("tr",{parentName:"tbody"},Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"3.0"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.11.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.11.0")),Object(s.b)("tr",{parentName:"tbody"},Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"3.0"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.10.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.11.0-RC1")),Object(s.b)("tr",{parentName:"tbody"},Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"2.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.10.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.10.4")),Object(s.b)("tr",{parentName:"tbody"},Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"2.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.9.x"),Object(s.b)("td",Object(n.a)({parentName:"tr"},{align:null}),"0.9.3")))),Object(s.b)("p",null,"We are going to use sbt-assembly to deploy a fat JAR containing ScalaPB, and\nyour compiled protos. Make sure in project/plugins.sbt you have a line\nthat adds sbt-assembly:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")\n')),Object(s.b)("p",null,"In ",Object(s.b)("inlineCode",{parentName:"p"},"build.sbt")," add a dependency on ",Object(s.b)("inlineCode",{parentName:"p"},"sparksql-scalapb"),":"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'libraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.11.0"\n')),Object(s.b)("p",null,"Spark ships with an old version of Google's Protocol Buffers runtime that is not compatible with\nthe current version. Therefore, we need to shade our copy of the Protocol Buffer runtime. Spark 3\nalso ships with an incompatible version of scala-collection-compat. Add the following to your\nbuild.sbt:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'assemblyShadeRules in assembly := Seq(\n ShadeRule.rename("com.google.protobuf.**" -> "shadeproto.@1").inAll,\n ShadeRule.rename("scala.collection.compat.**" -> "shadecompat.@1").inAll\n)\n')),Object(s.b)("p",null,"See ",Object(s.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/thesamet/sparksql-scalapb-test/blob/master/build.sbt"}),"complete example of build.sbt"),"."),Object(s.b)("h2",{id:"using-sparksql-scalapb"},"Using sparksql-scalapb"),Object(s.b)("p",null,"We assume you have a ",Object(s.b)("inlineCode",{parentName:"p"},"SparkSession")," assigned to the variable ",Object(s.b)("inlineCode",{parentName:"p"},"spark"),". In a standalone Scala program, this can be created with:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'import org.apache.spark.sql.SparkSession\n\nval spark: SparkSession = SparkSession\n .builder()\n .appName("ScalaPB Demo")\n .master("local[2]")\n .getOrCreate()\n// spark: SparkSession = org.apache.spark.sql.SparkSession@61ef672\n')),Object(s.b)("p",null,Object(s.b)("em",{parentName:"p"},"IMPORTANT"),": Ensure you do not import ",Object(s.b)("inlineCode",{parentName:"p"},"spark.implicits._")," to avoid ambiguity between ScalaPB provided encoders and Spark's default encoders. You may want to import ",Object(s.b)("inlineCode",{parentName:"p"},"StringToColumn")," to convert ",Object(s.b)("inlineCode",{parentName:"p"},'$"col name"')," into a ",Object(s.b)("inlineCode",{parentName:"p"},"Column"),". Add an import ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits")," to add ScalaPB's encoders for protocol buffers into the implicit search scope:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"import org.apache.spark.sql.{Dataset, DataFrame, functions => F}\nimport spark.implicits.StringToColumn\nimport scalapb.spark.ProtoSQL\n\nimport scalapb.spark.Implicits._\n")),Object(s.b)("p",null,"The code snippets below use the ",Object(s.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/ScalaPB/blob/master/docs/src/main/protobuf/person.proto"}),Object(s.b)("inlineCode",{parentName:"a"},"Person")," message"),"."),Object(s.b)("p",null,"We start by creating some test data:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'import scalapb.docs.person.Person\nimport scalapb.docs.person.Person.{Address, AddressType}\n\nval testData = Seq(\n Person(name="John", age=32, addresses=Vector(\n Address(addressType=AddressType.HOME, street="Market", city="SF"))\n ),\n Person(name="Mike", age=29, addresses=Vector(\n Address(addressType=AddressType.WORK, street="Castro", city="MV"),\n Address(addressType=AddressType.HOME, street="Church", city="MV"))\n ),\n Person(name="Bart", age=27)\n)\n')),Object(s.b)("p",null,"We can create a ",Object(s.b)("inlineCode",{parentName:"p"},"DataFrame")," from the test data:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"val df = ProtoSQL.createDataFrame(spark, testData)\n// df: DataFrame = [name: string, age: int ... 1 more field]\ndf.printSchema()\n// root\n// |-- name: string (nullable = true)\n// |-- age: integer (nullable = true)\n// |-- addresses: array (nullable = false)\n// | |-- element: struct (containsNull = false)\n// | | |-- address_type: string (nullable = true)\n// | | |-- street: string (nullable = true)\n// | | |-- city: string (nullable = true)\n// \ndf.show()\n// +----+---+--------------------+\n// |name|age| addresses|\n// +----+---+--------------------+\n// |John| 32|[{HOME, Market, SF}]|\n// |Mike| 29|[{WORK, Castro, M...|\n// |Bart| 27| []|\n// +----+---+--------------------+\n//\n")),Object(s.b)("p",null,"and then process it as any other Dataframe in Spark:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'df.select($"name", F.size($"addresses").alias("address_count")).show()\n// +----+-------------+\n// |name|address_count|\n// +----+-------------+\n// |John| 1|\n// |Mike| 2|\n// |Bart| 0|\n// +----+-------------+\n// \n\nval nameAndAddress = df.select($"name", $"addresses".getItem(0).alias("firstAddress"))\n// nameAndAddress: DataFrame = [name: string, firstAddress: struct]\n\nnameAndAddress.show()\n// +----+------------------+\n// |name| firstAddress|\n// +----+------------------+\n// |John|{HOME, Market, SF}|\n// |Mike|{WORK, Castro, MV}|\n// |Bart| null|\n// +----+------------------+\n//\n')),Object(s.b)("p",null,"Using the datasets API it is possible to bring the data back to ScalaPB case classes:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"nameAndAddress.as[(String, Option[Address])].collect().foreach(println)\n// (John,Some(Address(HOME,Market,SF,UnknownFieldSet(Map()))))\n// (Mike,Some(Address(WORK,Castro,MV,UnknownFieldSet(Map()))))\n// (Bart,None)\n")),Object(s.b)("p",null,"You can create a Dataset directly using Spark APIs:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"spark.createDataset(testData)\n// res5: Dataset[Person] = [name: string, age: int ... 1 more field]\n")),Object(s.b)("h2",{id:"from-binary-to-protos-and-back"},"From Binary to protos and back"),Object(s.b)("p",null,"In some situations, you may need to deal with datasets that contain serialized protocol buffers. This can be handled by mapping the datasets through ScalaPB's ",Object(s.b)("inlineCode",{parentName:"p"},"parseFrom")," and ",Object(s.b)("inlineCode",{parentName:"p"},"toByteArray")," functions."),Object(s.b)("p",null,"Let's start by preparing a dataset with test binary data by mapping our ",Object(s.b)("inlineCode",{parentName:"p"},"testData"),":"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"val binaryDS: Dataset[Array[Byte]] = spark.createDataset(testData.map(_.toByteArray))\n// binaryDS: Dataset[Array[Byte]] = [value: binary]\n\nbinaryDS.show()\n// +--------------------+\n// | value|\n// +--------------------+\n// |[0A 04 4A 6F 68 6...|\n// |[0A 04 4D 69 6B 6...|\n// |[0A 04 42 61 72 7...|\n// +--------------------+\n//\n")),Object(s.b)("p",null,"To turn this dataset into a ",Object(s.b)("inlineCode",{parentName:"p"},"Dataset[Person]"),", we map it through ",Object(s.b)("inlineCode",{parentName:"p"},"parseFrom"),":"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"val protosDS: Dataset[Person] = binaryDS.map(Person.parseFrom(_))\n// protosDS: Dataset[Person] = [name: string, age: int ... 1 more field]\n")),Object(s.b)("p",null,"to turn a dataset of protos into ",Object(s.b)("inlineCode",{parentName:"p"},"Dataset[Array[Byte]]"),":"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"val protosBinary: Dataset[Array[Byte]] = protosDS.map(_.toByteArray)\n// protosBinary: Dataset[Array[Byte]] = [value: binary]\n")),Object(s.b)("h2",{id:"on-enums"},"On enums"),Object(s.b)("p",null,"In SparkSQL-ScalaPB, enums are represented as strings. Unrecognized enum values are represented as strings containing the numeric value."),Object(s.b)("h2",{id:"dataframes-and-datasets-from-rdds"},"Dataframes and Datasets from RDDs"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"import org.apache.spark.rdd.RDD\n\nval protoRDD: RDD[Person] = spark.sparkContext.parallelize(testData)\n\nval protoDF: DataFrame = ProtoSQL.protoToDataFrame(spark, protoRDD)\n\nval protoDS: Dataset[Person] = spark.createDataset(protoRDD)\n")),Object(s.b)("h2",{id:"udfs"},"UDFs"),Object(s.b)("p",null,"If you need to write a UDF that returns a message, it would not pick up our encoder and you may get a runtime failure. To work around this, sparksql-scalapb provides ",Object(s.b)("inlineCode",{parentName:"p"},"ProtoSQL.udf")," to create UDFs. For example, if you need to parse a binary column into a proto:"),Object(s.b)("pre",null,Object(s.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'val binaryDF = protosBinary.toDF("value")\n// binaryDF: DataFrame = [value: binary]\n\nval parsePersons = ProtoSQL.udf { bytes: Array[Byte] => Person.parseFrom(bytes) }\n// parsePersons: org.apache.spark.sql.Column => org.apache.spark.sql.Column = scalapb.spark.Udfs$$Lambda$11273/18226139@4575c0dd\n\nbinaryDF.withColumn("person", parsePersons($"value"))\n// res7: DataFrame = [value: binary, person: struct]\n')),Object(s.b)("h2",{id:"primitive-wrappers"},"Primitive wrappers"),Object(s.b)("p",null,"In ProtoSQL 0.9.x and 0.10.x, primitive wrappers are represented in Spark as structs\nwitha single field named ",Object(s.b)("inlineCode",{parentName:"p"},"value"),". A better representation in Spark would be a\nnullable field of the primitive type. The better representation will be the\ndefault in 0.11.x. To enable this representation today, replace the usages of\n",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL")," with ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL.withPrimitiveWrappers"),".\nInstead of importing ",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits._"),", import\n",Object(s.b)("inlineCode",{parentName:"p"},"scalapb.spark.ProtoSQL.implicits._")),Object(s.b)("p",null,"See example in ",Object(s.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/sparksql-scalapb/blob/80f3162b69313d57f95d3dcbfee865809873567a/sparksql-scalapb/src/test/scala/WrappersSpec.scala#L42-L59"}),"WrappersSpec"),"."),Object(s.b)("h2",{id:"datasets-and-none-is-not-a-term"},"Datasets and ",Object(s.b)("inlineCode",{parentName:"h2"}," is not a term")),Object(s.b)("p",null,"You will see this error if for some reason Spark's ",Object(s.b)("inlineCode",{parentName:"p"},"Encoder"),"s are being picked up\ninstead of the ones provided by sparksql-scalapb. Please ensure you are not importing ",Object(s.b)("inlineCode",{parentName:"p"},"spark.implicits._"),". See instructions above for imports."),Object(s.b)("h2",{id:"example"},"Example"),Object(s.b)("p",null,"Check out a ",Object(s.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/thesamet/sparksql-scalapb-test"}),"complete example")," here."))}i.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/0f622c7a.0b2cac4b.js b/0f622c7a.0b2cac4b.js deleted file mode 100644 index 6c929dc81..000000000 --- a/0f622c7a.0b2cac4b.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return d})),a.d(t,"b",(function(){return m}));var o=a(0),n=a.n(o);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,o)}return a}function c(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var p=n.a.createContext({}),l=function(e){var t=n.a.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},d=function(e){var t=l(e.components);return n.a.createElement(p.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},u=n.a.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,i=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=l(a),u=o,m=d["".concat(i,".").concat(u)]||d[u]||b[u]||r;return a?n.a.createElement(m,c(c({ref:t},p),{},{components:a})):n.a.createElement(m,c({ref:t},p))}));function m(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=u;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:o,i[1]=c;for(var p=2;pOption in proto3?",id:"why-message-fields-are-wrapped-in-an-option-in-proto3",children:[]},{value:"How do I represent Option[T] in proto3 for scalar fields?",id:"how-do-i-represent-optiont-in-proto3-for-scalar-fields",children:[]},{value:"Why a certain customization is not available as a global generator parameter?",id:"why-a-certain-customization-is-not-available-as-a-global-generator-parameter",children:[]},{value:"How do I write my own Scala code generator for protocol buffers?",id:"how-do-i-write-my-own-scala-code-generator-for-protocol-buffers",children:[]},{value:"How do I mark a generated case class private?",id:"how-do-i-mark-a-generated-case-class-private",children:[]},{value:"How do I define custom field scope?",id:"how-do-i-define-custom-field-scope",children:[]},{value:"How do I customize third-party types?",id:"how-do-i-customize-third-party-types",children:[]},{value:"Using Spark, I am getting No encoder found for ... or Unable to find encoder for type",id:"using-spark-i-am-getting-no-encoder-found-for--or-unable-to-find-encoder-for-type",children:[]},{value:"How do I use ScalaPB with Gradle?",id:"how-do-i-use-scalapb-with-gradle",children:[]}],p={toc:s};function l(e){var t=e.components,a=Object(n.a)(e,["components"]);return Object(r.b)("wrapper",Object(o.a)({},p,a,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"how-do-i-use-scalapb-from-the-command-line"},"How do I use ScalaPB from the command line?"),Object(r.b)("p",null,"Check out ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/scalapbc"}),"ScalaPBC"),"."),Object(r.b)("h2",{id:"how-do-i-use-scalapb-with-maven"},"How do I use ScalaPB with Maven?"),Object(r.b)("p",null,"ScalaPB code generator can be invoked in your Maven build through the protobuf-maven-plugin. See ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/thesamet/scalapb-maven-example"}),"example project"),"."),Object(r.b)("p",null,'The relevant parts are marked with "Add protobuf-maven-plugin..."'),Object(r.b)("h2",{id:"how-do-i-get-grpc-java-conversions-flat-packages-etc-with-maven"},"How do I get grpc, java conversions, flat packages, etc with Maven?"),Object(r.b)("p",null,"The example maven project invokes ScalaPBC. To get these ScalaPB features, you need to pass a\ngenerator parameter to ScalaPBC. See the supported generator parameters and how to use them in\n",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/scalapbc"}),"ScalaPBC")," documentation."),Object(r.b)("h2",{id:"i-am-getting-import-was-not-found-or-had-errors"},'I am getting "Import was not found or had errors"'),Object(r.b)("p",null,"If you are using sbt-protoc and importing protos like ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb/scalapb.proto"),",\nor common protocol buffers like ",Object(r.b)("inlineCode",{parentName:"p"},"google/protobuf/wrappers.proto"),":"),Object(r.b)("p",null,"Add the following to your ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),'libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')),Object(r.b)("p",null,"This tells ",Object(r.b)("inlineCode",{parentName:"p"},"sbt-protoc")," to extract protos from this jar (and all its\ndependencies, which includes Google's common protos), and make them available\nin the include path that is passed to protoc."),Object(r.b)("p",null,"If you are not using sbt (for example, spbc), then you need to make those\nfiles available on the file system."),Object(r.b)("h2",{id:"how-do-i-generate-scala-code-for-protos-from-another-jar"},"How do I generate Scala code for protos from another jar?"),Object(r.b)("p",null,"For some proto packages, we may already provide pre-compiled generated code in\n",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/scalapb/common-protos"}),"ScalaPB's Common Protos project"),".\nIf what you are looking for is not there, consider adding it by following the\ninstructions on the project's page."),Object(r.b)("p",null,"To build it yourself using SBT: include the jar as a ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," dependency in your libraryDependencies:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-scala"}),'libraryDependencies += "com.somepackage" %% "that-has-jar" % "1.0" % "protobuf-src" intransitive()\n')),Object(r.b)("p",null,"This will tell sbt-protoc to extract the protos from that jar into\n",Object(r.b)("inlineCode",{parentName:"p"},"target/scala-2.vv/protobuf_external_src")," and add them both to the import\nsearch path and the set of sources to generate code for (",Object(r.b)("inlineCode",{parentName:"p"},"PB.protoSources"),")."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"intransitive")," modifier makes it not unpack the dependencies of this\nlibrary to the same directory since you may not want to generate classes for them\nas well. Many common libraries depend on ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf-java"),", and generated\nclasses for them are already shipped with ScalaPB's ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb-runtime"),". When\nusing ",Object(r.b)("inlineCode",{parentName:"p"},"intransitive()"),", you should ensure all the dependencies are provided,\neither as ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf-src")," or ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," (depending if you want to compile them\nor just import them)."),Object(r.b)("p",null,"You may find other protos under ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf_external_src")," that you do not wish to\ncompile. You can exclude them by adding an ",Object(r.b)("inlineCode",{parentName:"p"},"includeFilter"),":"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{}),'includeFilter in PB.generate := new SimpleFileFilter(\n (f: File) => f.getParent.endsWith("com/thesamet/protos"))\n')),Object(r.b)("p",null,"See ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/multi-with-external-jar"}),"full example here"),"."),Object(r.b)("h2",{id:"why-message-fields-are-wrapped-in-an-option-in-proto3"},"Why message fields are wrapped in an ",Object(r.b)("inlineCode",{parentName:"h2"},"Option")," in proto3?"),Object(r.b)("p",null,"For a proto like this:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-protobuf"}),'synax = "proto3";\n\nmessage A {}\n\nmessage B {\n A a = 1;\n}\n')),Object(r.b)("p",null,"The generated case class for ",Object(r.b)("inlineCode",{parentName:"p"},"B")," will have a field ",Object(r.b)("inlineCode",{parentName:"p"},"a: Option[A]"),". The reason\nis that in the proto3 format, it is valid for an encoded message of type ",Object(r.b)("inlineCode",{parentName:"p"},"B")," to not\ncontain a value for the field ",Object(r.b)("inlineCode",{parentName:"p"},"a"),". Using the ",Object(r.b)("inlineCode",{parentName:"p"},"Option[A]")," type lets us distinguish\nbetween the case where a value for ",Object(r.b)("inlineCode",{parentName:"p"},"A")," was not provided and the case where ",Object(r.b)("inlineCode",{parentName:"p"},"A"),"\nwas explictly set to a certain value (even if that value is the default value\nfor ",Object(r.b)("inlineCode",{parentName:"p"},"A"),"). The case where ",Object(r.b)("inlineCode",{parentName:"p"},"a")," is not set, and the case that ",Object(r.b)("inlineCode",{parentName:"p"},"A")," is set to its\ndefault value have two distinct binary representations (in both proto2 and\nproto3)."),Object(r.b)("p",null,"You can set a certain message type or a field to not be wrapped in an ",Object(r.b)("inlineCode",{parentName:"p"},"Option"),"\nusing the ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/customizations#message-level-custom-type-and-boxing"}),Object(r.b)("inlineCode",{parentName:"a"},"no_box")," option"),"."),Object(r.b)("h2",{id:"how-do-i-represent-optiont-in-proto3-for-scalar-fields"},"How do I represent ",Object(r.b)("inlineCode",{parentName:"h2"},"Option[T]")," in proto3 for scalar fields?"),Object(r.b)("p",null,"Scalar fields are the various numeric types, ",Object(r.b)("inlineCode",{parentName:"p"},"bool"),", ",Object(r.b)("inlineCode",{parentName:"p"},"string"),", ",Object(r.b)("inlineCode",{parentName:"p"},"byte")," and ",Object(r.b)("inlineCode",{parentName:"p"},"enum")," -\neverything except of messages. In the proto2 wire format, there is a distinction between\nnot setting a value (",Object(r.b)("inlineCode",{parentName:"p"},"None"),"), or setting it to its default value (",Object(r.b)("inlineCode",{parentName:"p"},"Some(0)")," or\n",Object(r.b)("inlineCode",{parentName:"p"},'Some("")'),")."),Object(r.b)("p",null,"In proto3, this distinction has been removed in the wire format. Whenever the value\nof a scalar type is zero, it does not get serialized. Therefore, the parser is not\nable to distinguish between ",Object(r.b)("inlineCode",{parentName:"p"},"Some(0)")," or ",Object(r.b)("inlineCode",{parentName:"p"},"None"),". The semantics is that a ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://developers.google.com/protocol-buffers/docs/proto3#default"}),"zero\nhas been received"),"."),Object(r.b)("p",null,"Optional message types are still wrapped in ",Object(r.b)("inlineCode",{parentName:"p"},"Option[]")," since there is a\ndistinction in the wire format between leaving out a message (which is\nrepresent by ",Object(r.b)("inlineCode",{parentName:"p"},"None")," or sending one, even if all its fields are unset (or\nassigned default values). If you wish to have ",Object(r.b)("inlineCode",{parentName:"p"},"Option[]")," around scalar\ntypes in proto3, you can use this fact to your advantage by using ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/customizations#primitive-wrappers"}),"primitive wrappers")),Object(r.b)("h2",{id:"why-a-certain-customization-is-not-available-as-a-global-generator-parameter"},"Why a certain customization is not available as a global generator parameter?"),Object(r.b)("p",null,"It turns out that global generator parameters that affect source code compatibility are something that we would like to avoid, as it is creating issues that are tricky to resolve. For example, if:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"package A provides proto files and generate source code with one value of a generator parameter,"),Object(r.b)("li",{parentName:"ul"},"package B is compiled separately with a different value of this generator parameter, and imports protos from package A, as well as its generated classes.")),Object(r.b)("p",null,"then the code generator for B has no way of knowing that package A has code generated with a different parameter, and that it needs to account for that in the way it references it. This leads to compilation errors in ScalaPB or in user-provided code generators."),Object(r.b)("p",null,"In version 0.8.2, we introduced ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/customizations#package-scoped-options"}),"package-scoped options")," which let you set file-level options for an entire package at once."),Object(r.b)("h2",{id:"how-do-i-write-my-own-scala-code-generator-for-protocol-buffers"},"How do I write my own Scala code generator for protocol buffers?"),Object(r.b)("p",null,"Easy! Check out ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/scalapb/scalapb-plugin-template.g8"}),"giter8 template for writing new code generators"),"."),Object(r.b)("h2",{id:"how-do-i-mark-a-generated-case-class-private"},"How do I mark a generated case class private?"),Object(r.b)("p",null,"Easy! See this example:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\nimport "scalapb/scalapb.proto";\n\nmessage MyPrivateMessage {\n option (scalapb.message).annotations = "private[com.mypkg]";\n option (scalapb.message).companion_annotations = "private[com.mypkg]";\n}\n')),Object(r.b)("h2",{id:"how-do-i-define-custom-field-scope"},"How do I define custom field scope?"),Object(r.b)("p",null,"Easy! See this example:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-protobuf"}),"syntax = \"proto3\";\nimport \"scalapb/scalapb.proto\";\n\nmessage MyMessage {\n string privateField = 1 [(scalapb.field).annotations = 'private val'];\n string protectedField = 2 [(scalapb.field).annotations = 'protected val'];\n string packagePrivateField = 3 [(scalapb.field).annotations = 'private[proto] val'];\n}\n")),Object(r.b)("p",null,"Generated code would be:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-scala"}),'final case class MyMessage(\n private val privateField: String = "",\n protected val protectedField: String = "",\n private[proto] val packagePrivateField: String = ""\n) extends ...\n')),Object(r.b)("h2",{id:"how-do-i-customize-third-party-types"},"How do I customize third-party types?"),Object(r.b)("p",null,"You can use field-transformations to match on third-party types and apply arbitrary field-level options. See ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/transformations#example-customizing-third-party-types"}),"example here"),"."),Object(r.b)("h2",{id:"using-spark-i-am-getting-no-encoder-found-for--or-unable-to-find-encoder-for-type"},"Using Spark, I am getting ",Object(r.b)("inlineCode",{parentName:"h2"},"No encoder found for ...")," or ",Object(r.b)("inlineCode",{parentName:"h2"},"Unable to find encoder for type")),Object(r.b)("p",null,"When using ScalaPB case classes with Spark datasets or dataframes,\nyou need to be using sparksql-scalapb:"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Make sure the version of ScalaPB, sparksql-scalapb and ScalaPB match according to ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"/docs/sparksql#setting-up-your-project"}),"this table"),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"In the scope where the exception occurs, make sure you import ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits._"),". ",Object(r.b)("strong",{parentName:"p"},"Do not import ",Object(r.b)("inlineCode",{parentName:"strong"},"spark.implicits._")),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"If you use an interactive notebook such as Databricks or spark-shell, there is a default import of ",Object(r.b)("inlineCode",{parentName:"p"},"spark.implicits._")," that is executed prior to your own code. There is currently no way to disable this behavior. The workaround is to manually pass the encoder\nexplicitly in the locations where an encoder is not found, for example:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-scala"}),"import scalapb.spark.Implicits.typedEncoderToEncoder\n\ndf.as[MyMessageType](typedEncoderToEncoder[MyMessageType])\n\nspark.createDataset(myList, typedEncoderToEncoder[MyMessageType])\n")))),Object(r.b)("p",null,"This error is very common for newcomers to ScalaPB and Spark. If the guidance above did not resolve your issue and you would like to get support over Gitter, Github or Stackoverflow, please clearly indicate that you have read this FAQ, and provide the protos and code that triggers the exception, including the relevant imports in scope. Ideally, provide a reproducible example. The easiest way to do it is to fork ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/thesamet/sparksql-scalapb-test"}),"this repo"),", adjust so it reproduces the issue you have and provide a link to your fork in your problem report."),Object(r.b)("h2",{id:"how-do-i-use-scalapb-with-gradle"},"How do I use ScalaPB with Gradle?"),Object(r.b)("p",null,"You can use ScalaPB with the official ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/google/protobuf-gradle-plugin"}),"Protobuf Plugin for Gradle"),"."),Object(r.b)("p",null,"In your ",Object(r.b)("inlineCode",{parentName:"p"},"build.gradle")," the ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," section should look like this:"),Object(r.b)("pre",null,Object(r.b)("code",Object(o.a)({parentName:"pre"},{className:"language-gradle"}),'ext {\n scalapbVersion = \'0.11.1\'\n}\n\ndependencies {\n compile "com.thesamet.scalapb:scalapb-runtime_2.12:${scalapbVersion}"\n}\n\nprotobuf {\n protoc {\n artifact = \'com.google.protobuf:protoc:3.15.6\'\n }\n plugins {\n scalapb {\n artifact = (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) ?\n "com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:windows@bat" :\n "com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:unix@sh"\n }\n }\n\n generateProtoTasks {\n all().each { task ->\n task.builtins {\n // if you don\'t want java code to be generated.\n remove java\n }\n task.plugins {\n scalapb {\n // add any ScalaPB generator options here. See: https://scalapb.github.io/scalapbc.html#passing-generator-parameters\n // option \'flat_package\'\n }\n }\n }\n }\n}\n\n// Add geneated Scala code as a source directory\nsourceSets {\n main {\n scala {\n srcDirs "${protobuf.generatedFilesBaseDir}/main/scalapb"\n }\n }\n}\n')),Object(r.b)("p",null,"See ",Object(r.b)("a",Object(o.a)({parentName:"p"},{href:"https://github.com/scalapb/gradle-demo"}),"full example here"),"."))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/0f622c7a.bd47421b.js b/0f622c7a.bd47421b.js new file mode 100644 index 000000000..de023df18 --- /dev/null +++ b/0f622c7a.bd47421b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return d})),a.d(t,"b",(function(){return m}));var o=a(0),n=a.n(o);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,o)}return a}function s(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var c=n.a.createContext({}),l=function(e){var t=n.a.useContext(c),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},d=function(e){var t=l(e.components);return n.a.createElement(c.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},u=n.a.forwardRef((function(e,t){var a=e.components,o=e.mdxType,r=e.originalType,i=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),d=l(a),u=o,m=d["".concat(i,".").concat(u)]||d[u]||b[u]||r;return a?n.a.createElement(m,s(s({ref:t},c),{},{components:a})):n.a.createElement(m,s({ref:t},c))}));function m(e,t){var a=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=a.length,i=new Array(r);i[0]=u;var s={};for(var p in t)hasOwnProperty.call(t,p)&&(s[p]=t[p]);s.originalType=e,s.mdxType="string"==typeof e?e:o,i[1]=s;for(var c=2;cOption in proto3?",id:"why-message-fields-are-wrapped-in-an-option-in-proto3",children:[]},{value:"How do I represent Option[T] in proto3 for scalar fields?",id:"how-do-i-represent-optiont-in-proto3-for-scalar-fields",children:[]},{value:"Why a certain customization is not available as a global generator parameter?",id:"why-a-certain-customization-is-not-available-as-a-global-generator-parameter",children:[]},{value:"How do I write my own Scala code generator for protocol buffers?",id:"how-do-i-write-my-own-scala-code-generator-for-protocol-buffers",children:[]},{value:"How do I mark a generated case class private?",id:"how-do-i-mark-a-generated-case-class-private",children:[]},{value:"How do I define custom field scope?",id:"how-do-i-define-custom-field-scope",children:[]},{value:"How do I customize third-party types?",id:"how-do-i-customize-third-party-types",children:[]},{value:"Using Spark, I am getting No encoder found for ... or Unable to find encoder for type",id:"using-spark-i-am-getting-no-encoder-found-for--or-unable-to-find-encoder-for-type",children:[]},{value:"How do I use ScalaPB with Gradle?",id:"how-do-i-use-scalapb-with-gradle",children:[]}],l={toc:c};function d(e){var t=e.components,a=Object(n.a)(e,i);return Object(r.b)("wrapper",Object(o.a)({},l,a,{components:t,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"how-do-i-use-scalapb-from-the-command-line"},"How do I use ScalaPB from the command line?"),Object(r.b)("p",null,"Check out ",Object(r.b)("a",{parentName:"p",href:"/docs/scalapbc"},"ScalaPBC"),"."),Object(r.b)("h2",{id:"how-do-i-use-scalapb-with-maven"},"How do I use ScalaPB with Maven?"),Object(r.b)("p",null,"ScalaPB code generator can be invoked in your Maven build through the protobuf-maven-plugin. See ",Object(r.b)("a",{parentName:"p",href:"https://github.com/thesamet/scalapb-maven-example"},"example project"),"."),Object(r.b)("p",null,'The relevant parts are marked with "Add protobuf-maven-plugin..."'),Object(r.b)("h2",{id:"how-do-i-get-grpc-java-conversions-flat-packages-etc-with-maven"},"How do I get grpc, java conversions, flat packages, etc with Maven?"),Object(r.b)("p",null,"The example maven project invokes ScalaPBC. To get these ScalaPB features, you need to pass a\ngenerator parameter to ScalaPBC. See the supported generator parameters and how to use them in\n",Object(r.b)("a",{parentName:"p",href:"/docs/scalapbc"},"ScalaPBC")," documentation."),Object(r.b)("h2",{id:"i-am-getting-import-was-not-found-or-had-errors"},'I am getting "Import was not found or had errors"'),Object(r.b)("p",null,"If you are using sbt-protoc and importing protos like ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb/scalapb.proto"),",\nor common protocol buffers like ",Object(r.b)("inlineCode",{parentName:"p"},"google/protobuf/wrappers.proto"),":"),Object(r.b)("p",null,"Add the following to your ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre"},'libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')),Object(r.b)("p",null,"This tells ",Object(r.b)("inlineCode",{parentName:"p"},"sbt-protoc")," to extract protos from this jar (and all its\ndependencies, which includes Google's common protos), and make them available\nin the include path that is passed to protoc."),Object(r.b)("p",null,"If you are not using sbt (for example, spbc), then you need to make those\nfiles available on the file system."),Object(r.b)("h2",{id:"how-do-i-generate-scala-code-for-protos-from-another-jar"},"How do I generate Scala code for protos from another jar?"),Object(r.b)("p",null,"For some proto packages, we may already provide pre-compiled generated code in\n",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/common-protos"},"ScalaPB's Common Protos project"),".\nIf what you are looking for is not there, consider adding it by following the\ninstructions on the project's page."),Object(r.b)("p",null,"To build it yourself using SBT: include the jar as a ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," dependency in your libraryDependencies:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'libraryDependencies += "com.somepackage" %% "that-has-jar" % "1.0" % "protobuf-src" intransitive()\n')),Object(r.b)("p",null,"This will tell sbt-protoc to extract the protos from that jar into\n",Object(r.b)("inlineCode",{parentName:"p"},"target/scala-2.vv/protobuf_external_src")," and add them both to the import\nsearch path and the set of sources to generate code for (",Object(r.b)("inlineCode",{parentName:"p"},"PB.protoSources"),")."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"intransitive")," modifier makes it not unpack the dependencies of this\nlibrary to the same directory since you may not want to generate classes for them\nas well. Many common libraries depend on ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf-java"),", and generated\nclasses for them are already shipped with ScalaPB's ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb-runtime"),". When\nusing ",Object(r.b)("inlineCode",{parentName:"p"},"intransitive()"),", you should ensure all the dependencies are provided,\neither as ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf-src")," or ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," (depending if you want to compile them\nor just import them)."),Object(r.b)("p",null,"You may find other protos under ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf_external_src")," that you do not wish to\ncompile. You can exclude them by adding an ",Object(r.b)("inlineCode",{parentName:"p"},"includeFilter"),":"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre"},'includeFilter in PB.generate := new SimpleFileFilter(\n (f: File) => f.getParent.endsWith("com/thesamet/protos"))\n')),Object(r.b)("p",null,"See ",Object(r.b)("a",{parentName:"p",href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/multi-with-external-jar"},"full example here"),"."),Object(r.b)("h2",{id:"why-message-fields-are-wrapped-in-an-option-in-proto3"},"Why message fields are wrapped in an ",Object(r.b)("inlineCode",{parentName:"h2"},"Option")," in proto3?"),Object(r.b)("p",null,"For a proto like this:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},'synax = "proto3";\n\nmessage A {}\n\nmessage B {\n A a = 1;\n}\n')),Object(r.b)("p",null,"The generated case class for ",Object(r.b)("inlineCode",{parentName:"p"},"B")," will have a field ",Object(r.b)("inlineCode",{parentName:"p"},"a: Option[A]"),". The reason\nis that in the proto3 format, it is valid for an encoded message of type ",Object(r.b)("inlineCode",{parentName:"p"},"B")," to not\ncontain a value for the field ",Object(r.b)("inlineCode",{parentName:"p"},"a"),". Using the ",Object(r.b)("inlineCode",{parentName:"p"},"Option[A]")," type lets us distinguish\nbetween the case where a value for ",Object(r.b)("inlineCode",{parentName:"p"},"A")," was not provided and the case where ",Object(r.b)("inlineCode",{parentName:"p"},"A"),"\nwas explictly set to a certain value (even if that value is the default value\nfor ",Object(r.b)("inlineCode",{parentName:"p"},"A"),"). The case where ",Object(r.b)("inlineCode",{parentName:"p"},"a")," is not set, and the case that ",Object(r.b)("inlineCode",{parentName:"p"},"A")," is set to its\ndefault value have two distinct binary representations (in both proto2 and\nproto3)."),Object(r.b)("p",null,"You can set a certain message type or a field to not be wrapped in an ",Object(r.b)("inlineCode",{parentName:"p"},"Option"),"\nusing the ",Object(r.b)("a",{parentName:"p",href:"/docs/customizations#message-level-custom-type-and-boxing"},Object(r.b)("inlineCode",{parentName:"a"},"no_box")," option"),"."),Object(r.b)("h2",{id:"how-do-i-represent-optiont-in-proto3-for-scalar-fields"},"How do I represent ",Object(r.b)("inlineCode",{parentName:"h2"},"Option[T]")," in proto3 for scalar fields?"),Object(r.b)("p",null,"Scalar fields are the various numeric types, ",Object(r.b)("inlineCode",{parentName:"p"},"bool"),", ",Object(r.b)("inlineCode",{parentName:"p"},"string"),", ",Object(r.b)("inlineCode",{parentName:"p"},"byte")," and ",Object(r.b)("inlineCode",{parentName:"p"},"enum")," -\neverything except of messages. In the proto2 wire format, there is a distinction between\nnot setting a value (",Object(r.b)("inlineCode",{parentName:"p"},"None"),"), or setting it to its default value (",Object(r.b)("inlineCode",{parentName:"p"},"Some(0)")," or\n",Object(r.b)("inlineCode",{parentName:"p"},'Some("")'),")."),Object(r.b)("p",null,"In proto3, this distinction has been removed in the wire format. Whenever the value\nof a scalar type is zero, it does not get serialized. Therefore, the parser is not\nable to distinguish between ",Object(r.b)("inlineCode",{parentName:"p"},"Some(0)")," or ",Object(r.b)("inlineCode",{parentName:"p"},"None"),". The semantics is that a ",Object(r.b)("a",{parentName:"p",href:"https://developers.google.com/protocol-buffers/docs/proto3#default"},"zero\nhas been received"),"."),Object(r.b)("p",null,"Optional message types are still wrapped in ",Object(r.b)("inlineCode",{parentName:"p"},"Option[]")," since there is a\ndistinction in the wire format between leaving out a message (which is\nrepresent by ",Object(r.b)("inlineCode",{parentName:"p"},"None")," or sending one, even if all its fields are unset (or\nassigned default values). If you wish to have ",Object(r.b)("inlineCode",{parentName:"p"},"Option[]")," around scalar\ntypes in proto3, you can use this fact to your advantage by using ",Object(r.b)("a",{parentName:"p",href:"/docs/customizations#primitive-wrappers"},"primitive wrappers")),Object(r.b)("h2",{id:"why-a-certain-customization-is-not-available-as-a-global-generator-parameter"},"Why a certain customization is not available as a global generator parameter?"),Object(r.b)("p",null,"It turns out that global generator parameters that affect source code compatibility are something that we would like to avoid, as it is creating issues that are tricky to resolve. For example, if:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"package A provides proto files and generate source code with one value of a generator parameter,"),Object(r.b)("li",{parentName:"ul"},"package B is compiled separately with a different value of this generator parameter, and imports protos from package A, as well as its generated classes.")),Object(r.b)("p",null,"then the code generator for B has no way of knowing that package A has code generated with a different parameter, and that it needs to account for that in the way it references it. This leads to compilation errors in ScalaPB or in user-provided code generators."),Object(r.b)("p",null,"In version 0.8.2, we introduced ",Object(r.b)("a",{parentName:"p",href:"/docs/customizations#package-scoped-options"},"package-scoped options")," which let you set file-level options for an entire package at once."),Object(r.b)("h2",{id:"how-do-i-write-my-own-scala-code-generator-for-protocol-buffers"},"How do I write my own Scala code generator for protocol buffers?"),Object(r.b)("p",null,"Easy! Check out ",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/scalapb-plugin-template.g8"},"giter8 template for writing new code generators"),"."),Object(r.b)("h2",{id:"how-do-i-mark-a-generated-case-class-private"},"How do I mark a generated case class private?"),Object(r.b)("p",null,"Easy! See this example:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\nimport "scalapb/scalapb.proto";\n\nmessage MyPrivateMessage {\n option (scalapb.message).annotations = "private[com.mypkg]";\n option (scalapb.message).companion_annotations = "private[com.mypkg]";\n}\n')),Object(r.b)("h2",{id:"how-do-i-define-custom-field-scope"},"How do I define custom field scope?"),Object(r.b)("p",null,"Easy! See this example:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},"syntax = \"proto3\";\nimport \"scalapb/scalapb.proto\";\n\nmessage MyMessage {\n string privateField = 1 [(scalapb.field).annotations = 'private val'];\n string protectedField = 2 [(scalapb.field).annotations = 'protected val'];\n string packagePrivateField = 3 [(scalapb.field).annotations = 'private[proto] val'];\n}\n")),Object(r.b)("p",null,"Generated code would be:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'final case class MyMessage(\n private val privateField: String = "",\n protected val protectedField: String = "",\n private[proto] val packagePrivateField: String = ""\n) extends ...\n')),Object(r.b)("h2",{id:"how-do-i-customize-third-party-types"},"How do I customize third-party types?"),Object(r.b)("p",null,"You can use field-transformations to match on third-party types and apply arbitrary field-level options. See ",Object(r.b)("a",{parentName:"p",href:"/docs/transformations#example-customizing-third-party-types"},"example here"),"."),Object(r.b)("h2",{id:"using-spark-i-am-getting-no-encoder-found-for--or-unable-to-find-encoder-for-type"},"Using Spark, I am getting ",Object(r.b)("inlineCode",{parentName:"h2"},"No encoder found for ...")," or ",Object(r.b)("inlineCode",{parentName:"h2"},"Unable to find encoder for type")),Object(r.b)("p",null,"When using ScalaPB case classes with Spark datasets or dataframes,\nyou need to be using sparksql-scalapb:"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Make sure the version of ScalaPB, sparksql-scalapb and ScalaPB match according to ",Object(r.b)("a",{parentName:"p",href:"/docs/sparksql#setting-up-your-project"},"this table"),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"In the scope where the exception occurs, make sure you import ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb.spark.Implicits._"),". ",Object(r.b)("strong",{parentName:"p"},"Do not import ",Object(r.b)("inlineCode",{parentName:"strong"},"spark.implicits._")),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"If you use an interactive notebook such as Databricks or spark-shell, there is a default import of ",Object(r.b)("inlineCode",{parentName:"p"},"spark.implicits._")," that is executed prior to your own code. There is currently no way to disable this behavior. The workaround is to manually pass the encoder\nexplicitly in the locations where an encoder is not found, for example:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-scala"},"import scalapb.spark.Implicits.typedEncoderToEncoder\n\ndf.as[MyMessageType](typedEncoderToEncoder[MyMessageType])\n\nspark.createDataset(myList, typedEncoderToEncoder[MyMessageType])\n")))),Object(r.b)("p",null,"This error is very common for newcomers to ScalaPB and Spark. If the guidance above did not resolve your issue and you would like to get support over Gitter, Github or Stackoverflow, please clearly indicate that you have read this FAQ, and provide the protos and code that triggers the exception, including the relevant imports in scope. Ideally, provide a reproducible example. The easiest way to do it is to fork ",Object(r.b)("a",{parentName:"p",href:"https://github.com/thesamet/sparksql-scalapb-test"},"this repo"),", adjust so it reproduces the issue you have and provide a link to your fork in your problem report."),Object(r.b)("h2",{id:"how-do-i-use-scalapb-with-gradle"},"How do I use ScalaPB with Gradle?"),Object(r.b)("p",null,"You can use ScalaPB with the official ",Object(r.b)("a",{parentName:"p",href:"https://github.com/google/protobuf-gradle-plugin"},"Protobuf Plugin for Gradle"),"."),Object(r.b)("p",null,"In your ",Object(r.b)("inlineCode",{parentName:"p"},"build.gradle")," the ",Object(r.b)("inlineCode",{parentName:"p"},"protobuf")," section should look like this:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-gradle"},'ext {\n scalapbVersion = \'0.11.1\'\n}\n\ndependencies {\n compile "com.thesamet.scalapb:scalapb-runtime_2.12:${scalapbVersion}"\n}\n\nprotobuf {\n protoc {\n artifact = \'com.google.protobuf:protoc:3.15.6\'\n }\n plugins {\n scalapb {\n artifact = (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) ?\n "com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:windows@bat" :\n "com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:unix@sh"\n }\n }\n\n generateProtoTasks {\n all().each { task ->\n task.builtins {\n // if you don\'t want java code to be generated.\n remove java\n }\n task.plugins {\n scalapb {\n // add any ScalaPB generator options here. See: https://scalapb.github.io/scalapbc.html#passing-generator-parameters\n // option \'flat_package\'\n }\n }\n }\n }\n}\n\n// Add geneated Scala code as a source directory\nsourceSets {\n main {\n scala {\n srcDirs "${protobuf.generatedFilesBaseDir}/main/scalapb"\n }\n }\n}\n')),Object(r.b)("p",null,"See ",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/gradle-demo"},"full example here"),"."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/1.d720bdf5.js b/1.d1f2961e.js similarity index 98% rename from 1.d720bdf5.js rename to 1.d1f2961e.js index fe262f3a8..a5bc06ff5 100644 --- a/1.d720bdf5.js +++ b/1.d1f2961e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{120:function(e,t,n){"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t0)&&(d.unobserve(t),d.disconnect(),n())}))}))).observe(t))},to:j||""},l&&{isActive:h,activeClassName:p}))}},123:function(e,t,n){try{e.exports=n(150)}catch(r){e.exports={}}},124:function(e,t,n){"use strict";n.d(t,"b",(function(){return i})),n.d(t,"a",(function(){return u}));var r=n(21),o=n(130);function i(){var e=Object(r.default)().siteConfig,t=(e=void 0===e?{}:e).baseUrl,n=void 0===t?"/":t,i=e.url;return{withBaseUrl:function(e,t){return function(e,t,n,r){var i=void 0===r?{}:r,u=i.forcePrependBaseUrl,s=void 0!==u&&u,c=i.absolute,a=void 0!==c&&c;if(!n)return n;if(n.startsWith("#"))return n;if(Object(o.b)(n))return n;if(s)return t+n;var f=n.startsWith(t)?n:t+n.replace(/^\//,"");return a?e+f:f}(i,n,e,t)}}}function u(e,t){return void 0===t&&(t={}),(0,i().withBaseUrl)(e,t)}},126:function(e,t,n){"use strict";n.r(t);var r=n(11);n.d(t,"MemoryRouter",(function(){return r.d})),n.d(t,"Prompt",(function(){return r.f})),n.d(t,"Redirect",(function(){return r.g})),n.d(t,"Route",(function(){return r.h})),n.d(t,"Router",(function(){return r.i})),n.d(t,"StaticRouter",(function(){return r.j})),n.d(t,"Switch",(function(){return r.k})),n.d(t,"generatePath",(function(){return r.l})),n.d(t,"matchPath",(function(){return r.m})),n.d(t,"useHistory",(function(){return r.n})),n.d(t,"useLocation",(function(){return r.o})),n.d(t,"useParams",(function(){return r.p})),n.d(t,"useRouteMatch",(function(){return r.q})),n.d(t,"withRouter",(function(){return r.r})),n.d(t,"BrowserRouter",(function(){return r.a})),n.d(t,"HashRouter",(function(){return r.b})),n.d(t,"Link",(function(){return r.c})),n.d(t,"NavLink",(function(){return r.e}))},130:function(e,t,n){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return o}))},138:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useThemeConfig=void 0;var o=r(n(21));t.useThemeConfig=function(){return o.default().siteConfig.themeConfig}},139:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isDocsPluginEnabled=void 0;var r=n(123);t.isDocsPluginEnabled=!!r.useAllDocsData},140:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useDocsPreferredVersionContext=t.DocsPreferredVersionContextProvider=void 0;var s=i(n(0)),c=n(138),a=n(139),f=n(123),d=u(n(156));function l(e){var t=e.pluginIds,n=e.versionPersistence,r=e.allDocsData;var o={};return t.forEach((function(e){o[e]=function(e){var t=d.default.read(e,n);return r[e].versions.some((function(e){return e.name===t}))?{preferredVersionName:t}:(d.default.clear(e,n),{preferredVersionName:null})}(e)})),o}function v(){var e=f.useAllDocsData(),t=c.useThemeConfig().docs.versionPersistence,n=s.useMemo((function(){return Object.keys(e)}),[e]),r=s.useState((function(){return function(e){var t={};return e.forEach((function(e){t[e]={preferredVersionName:null}})),t}(n)})),o=r[0],i=r[1];return s.useEffect((function(){i(l({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]),[o,s.useMemo((function(){return{savePreferredVersion:function(e,n){d.default.save(e,t,n),i((function(t){var r;return Object.assign(Object.assign({},t),((r={})[e]={preferredVersionName:n},r))}))}}}),[i])]}var g=s.createContext(null);function p(e){var t=e.children,n=v();return s.default.createElement(g.Provider,{value:n},t)}t.DocsPreferredVersionContextProvider=function(e){var t=e.children;return a.isDocsPluginEnabled?s.default.createElement(p,null,t):s.default.createElement(s.default.Fragment,null,t)},t.useDocsPreferredVersionContext=function(){var e=s.useContext(g);if(!e)throw new Error("Can't find docs preferred context, maybe you forgot to use the DocsPreferredVersionContextProvider ?");return e}},149:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.docVersionSearchTag=t.DEFAULT_SEARCH_TAG=void 0,t.DEFAULT_SEARCH_TAG="default",t.docVersionSearchTag=function(e,t){return"docs-"+e+"-"+t}},150:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useDocVersionSuggestions=t.useActiveDocContext=t.useActiveVersion=t.useLatestVersion=t.useVersions=t.useActivePluginAndVersion=t.useActivePlugin=t.useDocsData=t.useAllDocsData=void 0;var r=n(126),o=n(151),i=n(152);t.useAllDocsData=function(){return o.useAllPluginInstancesData("docusaurus-plugin-content-docs")},t.useDocsData=function(e){return o.usePluginData("docusaurus-plugin-content-docs",e)},t.useActivePlugin=function(e){void 0===e&&(e={});var n=t.useAllDocsData(),o=r.useLocation().pathname;return i.getActivePlugin(n,o,e)},t.useActivePluginAndVersion=function(e){void 0===e&&(e={});var n=t.useActivePlugin(e),o=r.useLocation().pathname;if(n)return{activePlugin:n,activeVersion:i.getActiveVersion(n.pluginData,o)}},t.useVersions=function(e){return t.useDocsData(e).versions},t.useLatestVersion=function(e){var n=t.useDocsData(e);return i.getLatestVersion(n)},t.useActiveVersion=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getActiveVersion(n,o)},t.useActiveDocContext=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getActiveDocContext(n,o)},t.useDocVersionSuggestions=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getDocVersionSuggestions(n,o)}},151:function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return o})),n.d(t,"useAllPluginInstancesData",(function(){return i})),n.d(t,"usePluginData",(function(){return u}));var r=n(21);function o(){var e=Object(r.default)().globalData;if(!e)throw new Error("Docusaurus global data not found");return e}function i(e){var t=o()[e];if(!t)throw new Error("Docusaurus plugin global data not found for pluginName="+e);return t}function u(e,t){void 0===t&&(t="default");var n=i(e)[t];if(!n)throw new Error("Docusaurus plugin global data not found for pluginName="+e+" and pluginId="+t);return n}},152:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getDocVersionSuggestions=t.getActiveDocContext=t.getActiveVersion=t.getLatestVersion=t.getActivePlugin=void 0;var r=n(126);t.getActivePlugin=function(e,t,n){void 0===n&&(n={});var o=Object.entries(e).find((function(e){e[0];var n=e[1];return!!r.matchPath(t,{path:n.path,exact:!1,strict:!1})})),i=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!i&&n.failfast)throw new Error("Can't find active docs plugin for pathname="+t+", while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: "+Object.values(e).map((function(e){return e.path})).join(", "));return i},t.getLatestVersion=function(e){return e.versions.find((function(e){return e.isLast}))},t.getActiveVersion=function(e,n){var o=t.getLatestVersion(e);return[].concat(e.versions.filter((function(e){return e!==o})),[o]).find((function(e){return!!r.matchPath(n,{path:e.path,exact:!1,strict:!1})}))},t.getActiveDocContext=function(e,n){var o,i,u=t.getActiveVersion(e,n),s=null==u?void 0:u.docs.find((function(e){return!!r.matchPath(n,{path:e.path,exact:!0,strict:!1})}));return{activeVersion:u,activeDoc:s,alternateDocVersions:s?(o=s.id,i={},e.versions.forEach((function(e){e.docs.forEach((function(t){t.id===o&&(i[e.name]=t)}))})),i):{}}},t.getDocVersionSuggestions=function(e,n){var r=t.getLatestVersion(e),o=t.getActiveDocContext(e,n),i=o.activeVersion!==r;return{latestDocSuggestion:i?null==o?void 0:o.alternateDocVersions[r.name]:void 0,latestVersionSuggestion:i?r:void 0}}},153:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isSamePath=void 0,t.isSamePath=function(e,t){var n=function(e){return!e||(null==e?void 0:e.endsWith("/"))?e:e+"/"};return n(e)===n(t)}},154:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useTitleFormatter=void 0;var o=r(n(21));t.useTitleFormatter=function(e){var t=o.default().siteConfig,n=void 0===t?{}:t,r=n.title,i=n.titleDelimiter,u=void 0===i?"|":i;return e&&e.trim().length?e.trim()+" "+u+" "+r:r}},155:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useDocsPreferredVersionByPluginId=t.useDocsPreferredVersion=void 0;var r=n(0),o=n(140),i=n(123),u=n(157);t.useDocsPreferredVersion=function(e){void 0===e&&(e=u.DEFAULT_PLUGIN_ID);var t=i.useDocsData(e),n=o.useDocsPreferredVersionContext(),s=n[0],c=n[1],a=s[e].preferredVersionName;return{preferredVersion:a?t.versions.find((function(e){return e.name===a})):null,savePreferredVersionName:r.useCallback((function(t){c.savePreferredVersion(e,t)}),[c])}},t.useDocsPreferredVersionByPluginId=function(){var e=i.useAllDocsData(),t=o.useDocsPreferredVersionContext()[0],n=Object.keys(e),r={};return n.forEach((function(n){r[n]=function(n){var r=e[n],o=t[n].preferredVersionName;return o?r.versions.find((function(e){return e.name===o})):null}(n)})),r}},156:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(e){return"docs-preferred-version-"+e},o={save:function(e,t,n){"none"===t||window.localStorage.setItem(r(e),n)},read:function(e,t){return"none"===t?null:window.localStorage.getItem(r(e))},clear:function(e,t){"none"===t||window.localStorage.removeItem(r(e))}};t.default=o},157:function(e,t,n){"use strict";n.r(t),n.d(t,"DEFAULT_PLUGIN_ID",(function(){return r}));var r="default"}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{120:function(e,t,n){"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;t0)&&(d.unobserve(t),d.disconnect(),n())}))}))).observe(t))},to:j||""},l&&{isActive:h,activeClassName:p}))}},123:function(e,t,n){try{e.exports=n(150)}catch(r){e.exports={}}},124:function(e,t,n){"use strict";n.d(t,"b",(function(){return i})),n.d(t,"a",(function(){return u}));var r=n(20),o=n(130);function i(){var e=Object(r.default)().siteConfig,t=(e=void 0===e?{}:e).baseUrl,n=void 0===t?"/":t,i=e.url;return{withBaseUrl:function(e,t){return function(e,t,n,r){var i=void 0===r?{}:r,u=i.forcePrependBaseUrl,s=void 0!==u&&u,c=i.absolute,a=void 0!==c&&c;if(!n)return n;if(n.startsWith("#"))return n;if(Object(o.b)(n))return n;if(s)return t+n;var f=n.startsWith(t)?n:t+n.replace(/^\//,"");return a?e+f:f}(i,n,e,t)}}}function u(e,t){return void 0===t&&(t={}),(0,i().withBaseUrl)(e,t)}},126:function(e,t,n){"use strict";n.r(t);var r=n(11);n.d(t,"MemoryRouter",(function(){return r.d})),n.d(t,"Prompt",(function(){return r.f})),n.d(t,"Redirect",(function(){return r.g})),n.d(t,"Route",(function(){return r.h})),n.d(t,"Router",(function(){return r.i})),n.d(t,"StaticRouter",(function(){return r.j})),n.d(t,"Switch",(function(){return r.k})),n.d(t,"generatePath",(function(){return r.l})),n.d(t,"matchPath",(function(){return r.m})),n.d(t,"useHistory",(function(){return r.n})),n.d(t,"useLocation",(function(){return r.o})),n.d(t,"useParams",(function(){return r.p})),n.d(t,"useRouteMatch",(function(){return r.q})),n.d(t,"withRouter",(function(){return r.r})),n.d(t,"BrowserRouter",(function(){return r.a})),n.d(t,"HashRouter",(function(){return r.b})),n.d(t,"Link",(function(){return r.c})),n.d(t,"NavLink",(function(){return r.e}))},130:function(e,t,n){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return o}))},138:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useThemeConfig=void 0;var o=r(n(20));t.useThemeConfig=function(){return o.default().siteConfig.themeConfig}},139:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isDocsPluginEnabled=void 0;var r=n(123);t.isDocsPluginEnabled=!!r.useAllDocsData},140:function(e,t,n){"use strict";var r=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n),Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[n]}})}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),i=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)"default"!==n&&Object.hasOwnProperty.call(e,n)&&r(t,e,n);return o(t,e),t},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useDocsPreferredVersionContext=t.DocsPreferredVersionContextProvider=void 0;var s=i(n(0)),c=n(138),a=n(139),f=n(123),d=u(n(156));function l(e){var t=e.pluginIds,n=e.versionPersistence,r=e.allDocsData;var o={};return t.forEach((function(e){o[e]=function(e){var t=d.default.read(e,n);return r[e].versions.some((function(e){return e.name===t}))?{preferredVersionName:t}:(d.default.clear(e,n),{preferredVersionName:null})}(e)})),o}function v(){var e=f.useAllDocsData(),t=c.useThemeConfig().docs.versionPersistence,n=s.useMemo((function(){return Object.keys(e)}),[e]),r=s.useState((function(){return function(e){var t={};return e.forEach((function(e){t[e]={preferredVersionName:null}})),t}(n)})),o=r[0],i=r[1];return s.useEffect((function(){i(l({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]),[o,s.useMemo((function(){return{savePreferredVersion:function(e,n){d.default.save(e,t,n),i((function(t){var r;return Object.assign(Object.assign({},t),((r={})[e]={preferredVersionName:n},r))}))}}}),[i])]}var g=s.createContext(null);function p(e){var t=e.children,n=v();return s.default.createElement(g.Provider,{value:n},t)}t.DocsPreferredVersionContextProvider=function(e){var t=e.children;return a.isDocsPluginEnabled?s.default.createElement(p,null,t):s.default.createElement(s.default.Fragment,null,t)},t.useDocsPreferredVersionContext=function(){var e=s.useContext(g);if(!e)throw new Error("Can't find docs preferred context, maybe you forgot to use the DocsPreferredVersionContextProvider ?");return e}},149:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.docVersionSearchTag=t.DEFAULT_SEARCH_TAG=void 0,t.DEFAULT_SEARCH_TAG="default",t.docVersionSearchTag=function(e,t){return"docs-"+e+"-"+t}},150:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useDocVersionSuggestions=t.useActiveDocContext=t.useActiveVersion=t.useLatestVersion=t.useVersions=t.useActivePluginAndVersion=t.useActivePlugin=t.useDocsData=t.useAllDocsData=void 0;var r=n(126),o=n(151),i=n(152);t.useAllDocsData=function(){return o.useAllPluginInstancesData("docusaurus-plugin-content-docs")},t.useDocsData=function(e){return o.usePluginData("docusaurus-plugin-content-docs",e)},t.useActivePlugin=function(e){void 0===e&&(e={});var n=t.useAllDocsData(),o=r.useLocation().pathname;return i.getActivePlugin(n,o,e)},t.useActivePluginAndVersion=function(e){void 0===e&&(e={});var n=t.useActivePlugin(e),o=r.useLocation().pathname;if(n)return{activePlugin:n,activeVersion:i.getActiveVersion(n.pluginData,o)}},t.useVersions=function(e){return t.useDocsData(e).versions},t.useLatestVersion=function(e){var n=t.useDocsData(e);return i.getLatestVersion(n)},t.useActiveVersion=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getActiveVersion(n,o)},t.useActiveDocContext=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getActiveDocContext(n,o)},t.useDocVersionSuggestions=function(e){var n=t.useDocsData(e),o=r.useLocation().pathname;return i.getDocVersionSuggestions(n,o)}},151:function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return o})),n.d(t,"useAllPluginInstancesData",(function(){return i})),n.d(t,"usePluginData",(function(){return u}));var r=n(20);function o(){var e=Object(r.default)().globalData;if(!e)throw new Error("Docusaurus global data not found");return e}function i(e){var t=o()[e];if(!t)throw new Error("Docusaurus plugin global data not found for pluginName="+e);return t}function u(e,t){void 0===t&&(t="default");var n=i(e)[t];if(!n)throw new Error("Docusaurus plugin global data not found for pluginName="+e+" and pluginId="+t);return n}},152:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getDocVersionSuggestions=t.getActiveDocContext=t.getActiveVersion=t.getLatestVersion=t.getActivePlugin=void 0;var r=n(126);t.getActivePlugin=function(e,t,n){void 0===n&&(n={});var o=Object.entries(e).find((function(e){e[0];var n=e[1];return!!r.matchPath(t,{path:n.path,exact:!1,strict:!1})})),i=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!i&&n.failfast)throw new Error("Can't find active docs plugin for pathname="+t+", while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: "+Object.values(e).map((function(e){return e.path})).join(", "));return i},t.getLatestVersion=function(e){return e.versions.find((function(e){return e.isLast}))},t.getActiveVersion=function(e,n){var o=t.getLatestVersion(e);return[].concat(e.versions.filter((function(e){return e!==o})),[o]).find((function(e){return!!r.matchPath(n,{path:e.path,exact:!1,strict:!1})}))},t.getActiveDocContext=function(e,n){var o,i,u=t.getActiveVersion(e,n),s=null==u?void 0:u.docs.find((function(e){return!!r.matchPath(n,{path:e.path,exact:!0,strict:!1})}));return{activeVersion:u,activeDoc:s,alternateDocVersions:s?(o=s.id,i={},e.versions.forEach((function(e){e.docs.forEach((function(t){t.id===o&&(i[e.name]=t)}))})),i):{}}},t.getDocVersionSuggestions=function(e,n){var r=t.getLatestVersion(e),o=t.getActiveDocContext(e,n),i=o.activeVersion!==r;return{latestDocSuggestion:i?null==o?void 0:o.alternateDocVersions[r.name]:void 0,latestVersionSuggestion:i?r:void 0}}},153:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isSamePath=void 0,t.isSamePath=function(e,t){var n=function(e){return!e||(null==e?void 0:e.endsWith("/"))?e:e+"/"};return n(e)===n(t)}},154:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.useTitleFormatter=void 0;var o=r(n(20));t.useTitleFormatter=function(e){var t=o.default().siteConfig,n=void 0===t?{}:t,r=n.title,i=n.titleDelimiter,u=void 0===i?"|":i;return e&&e.trim().length?e.trim()+" "+u+" "+r:r}},155:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useDocsPreferredVersionByPluginId=t.useDocsPreferredVersion=void 0;var r=n(0),o=n(140),i=n(123),u=n(157);t.useDocsPreferredVersion=function(e){void 0===e&&(e=u.DEFAULT_PLUGIN_ID);var t=i.useDocsData(e),n=o.useDocsPreferredVersionContext(),s=n[0],c=n[1],a=s[e].preferredVersionName;return{preferredVersion:a?t.versions.find((function(e){return e.name===a})):null,savePreferredVersionName:r.useCallback((function(t){c.savePreferredVersion(e,t)}),[c])}},t.useDocsPreferredVersionByPluginId=function(){var e=i.useAllDocsData(),t=o.useDocsPreferredVersionContext()[0],n=Object.keys(e),r={};return n.forEach((function(n){r[n]=function(n){var r=e[n],o=t[n].preferredVersionName;return o?r.versions.find((function(e){return e.name===o})):null}(n)})),r}},156:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(e){return"docs-preferred-version-"+e},o={save:function(e,t,n){"none"===t||window.localStorage.setItem(r(e),n)},read:function(e,t){return"none"===t?null:window.localStorage.getItem(r(e))},clear:function(e,t){"none"===t||window.localStorage.removeItem(r(e))}};t.default=o},157:function(e,t,n){"use strict";n.r(t),n.d(t,"DEFAULT_PLUGIN_ID",(function(){return r}));var r="default"}}]); \ No newline at end of file diff --git a/10204607.1aebdf1e.js b/10204607.1aebdf1e.js new file mode 100644 index 000000000..f4540cf1e --- /dev/null +++ b/10204607.1aebdf1e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return d})),a.d(t,"b",(function(){return u}));var n=a(0),i=a.n(n);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var p=i.a.createContext({}),c=function(e){var t=i.a.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},d=function(e){var t=c(e.components);return i.a.createElement(p.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},m=i.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,r=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(a),m=n,u=d["".concat(r,".").concat(m)]||d[m]||b[m]||o;return a?i.a.createElement(u,l(l({ref:t},p),{},{components:a})):i.a.createElement(u,l({ref:t},p))}));function u(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,r=new Array(o);r[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:n,r[1]=l;for(var p=2;p (Compile / sourceManaged).value / "scalapb",\n scalapb.validate.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf"\n)\n')),Object(o.b)("p",null,"Note that we are adding ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb-validate-core")," as a ",Object(o.b)("inlineCode",{parentName:"p"},"protobuf")," dependency. This makes it possible to import ",Object(o.b)("inlineCode",{parentName:"p"},"validate/validate.proto")," from your own protos."),Object(o.b)("p",null,"If ",Object(o.b)("a",{parentName:"p",href:"/docs/sbt-settings#additional-options-to-the-generator"},"ScalaPB generator parameters")," are passed via ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.gen(options: GeneratorOption*)"),", the same parameters must be passed to ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.validate.gen(options: GeneratorOption*)"),"."),Object(o.b)("h2",{id:"using-the-generated-code"},"Using the generated code"),Object(o.b)("p",null,"Generated code for both ScalaPB and scalapb-validate is generated at compilation time. In ",Object(o.b)("inlineCode",{parentName:"p"},"sbt"),", just type ",Object(o.b)("inlineCode",{parentName:"p"},"compile"),"."),Object(o.b)("p",null,"In addition to the standard ScalaPB generated files, scalapb-validate will generate a validator object for each message based on its protoc-gen-validate rules. For a message named ",Object(o.b)("inlineCode",{parentName:"p"},"Msg")," the validator object will be named ",Object(o.b)("inlineCode",{parentName:"p"},"MsgValidator")," and will extend ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.validate.Validator[Msg]"),". An implicit instance of the validator is added to the companion object of each message, which makes it possible to write ",Object(o.b)("inlineCode",{parentName:"p"},"Validator[Msg]")," to obtain an instance of the validator."),Object(o.b)("h2",{id:"validators"},"Validators"),Object(o.b)("p",null,"The validator object is an object with a ",Object(o.b)("inlineCode",{parentName:"p"},"validate")," method that takes an instance of a message and returns the validation result: The ",Object(o.b)("inlineCode",{parentName:"p"},"Validator[T]")," is defined as follows:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"trait Validator[T] {\n def validate(t: T): Result\n}\n")),Object(o.b)("p",null,"where ",Object(o.b)("inlineCode",{parentName:"p"},"Result")," is a data structure that can be either a ",Object(o.b)("inlineCode",{parentName:"p"},"Success")," or a ",Object(o.b)("inlineCode",{parentName:"p"},"Failure"),":"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"sealed trait Result {\n def isSuccess: Boolean\n def isFailure: Boolean\n}\n\ncase object Success extends Result { ... }\n\ncase class Failure(violations: List[ValidationException]) extends Result { ... }\n")),Object(o.b)("p",null,"Therefore, the validation for the test person casn be run like this:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},'Validator[Person].validate(personInstance) match {\n case Success => println("Success!")\n case Failure(violations) => println(violations)\n}\n')),Object(o.b)("h2",{id:"package-scoped-extension-options"},"Package-scoped extension options"),Object(o.b)("p",null,"ScalaPB-validate further extends ScalaPB's package-scoped options to achieve additional customization:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto2";\n\npackage mypkg;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\n\noption (scalapb.options) = {\n scope: PACKAGE\n [scalapb.validate.file] {\n validate_at_construction: true\n insert_validator_instance: true\n skip: false\n }\n};\n')),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"validate_at_construction")," when true, a check for validity is added to the message class body, so construction of invalid messages results in a validation exception. Default: ",Object(o.b)("inlineCode",{parentName:"li"},"false"),"."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"insert_validator_instance")," when true, implicit instance of a ",Object(o.b)("inlineCode",{parentName:"li"},"Validator")," is added to the companion object of the message. This enables writing ",Object(o.b)("inlineCode",{parentName:"li"},"Validator[MyMsg].validate(instance)"),". Default: ",Object(o.b)("inlineCode",{parentName:"li"},"true"),"."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"skip")," when true, skips gnerating validators for messages defined in this file. This can be set for a third-party package to work around the problem that there are no validators for it. See ",Object(o.b)("a",{parentName:"li",href:"https://github.com/scalapb/scalapb-validate/tree/master/e2e/src/main/protobuf/skip"},"this testcase")," for a usage example.")),Object(o.b)("h2",{id:"rule-based-type-customization"},"Rule-based type customization"),Object(o.b)("p",null,"Starting from version 0.10.10, ScalaPB provides a way to customize its own options by writing rules that are matched against\narbitrary protobuf options. When these rules are matched, additional ScalaPB options are added to the matched entity. For example, you can create a transformation that whenever a field has a PGV-rule like ",Object(o.b)("inlineCode",{parentName:"p"},"int32: { gt: 0 }}"),", then it will be typemapped to a custom class ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt"),"."),Object(o.b)("h3",{id:"installation-1"},"Installation"),Object(o.b)("p",null,"The features described in this section have the following version requirements:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"sbt-protoc >= ",Object(o.b)("inlineCode",{parentName:"li"},"1.0.0")),Object(o.b)("li",{parentName:"ul"},"ScalaPB >= ",Object(o.b)("inlineCode",{parentName:"li"},"0.10.10")),Object(o.b)("li",{parentName:"ul"},"scalapb-validate >= ",Object(o.b)("inlineCode",{parentName:"li"},"0.2.0"))),Object(o.b)("p",null,"While field transformation is a generic ScalaPB mechanism, it is also recommended that you add\nscalapb-validate's preprocessor to ",Object(o.b)("inlineCode",{parentName:"p"},"PB.targets"),". The preprocessor does two things:"),Object(o.b)("ol",null,Object(o.b)("li",{parentName:"ol"},"Provides field transformations for ",Object(o.b)("inlineCode",{parentName:"li"},"Set")," and cats data types."),Object(o.b)("li",{parentName:"ol"},"Expand your PGV-based rules such that they match repeated items, map keys and map values.")),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},'Compile / PB.targets := Seq(\n scalapb.validate.preprocessor() -> (Compile / sourceManaged).value / "scalapb",\n scalapb.gen() -> (Compile / sourceManaged).value / "scalapb",\n scalapb.validate.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf",\n\n // If you are using Cats transformations:\n "com.thesamet.scalapb" %% "scalapb-validate-cats" % scalapb.validate.compiler.BuildInfo.version,\n "org.typelevel" %% "cats-core" % "2.3.0"\n)\n')),Object(o.b)("p",null,"There is an example project ",Object(o.b)("a",{parentName:"p",href:"https://github.com/scalapb/scalapb-validate-demo"},"available on github"),"."),Object(o.b)("h3",{id:"field-transformations"},"Field transformations"),Object(o.b)("p",null,"If you want all positive integers to be typemapped to a Scala class called ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt")," you can\ncreate a proto file with the following content:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto2";\n\npackage mypackage;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\nimport "validate/validate.proto";\n\noption (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {options { [validate.rules] {int32: {gt: 0}} }}\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveInt"\n }\n }\n }\n ]\n};\n')),Object(o.b)("p",null,"The scope of this definition is the entire protobuf file it is found in. Field tranformations can also\nbe used in package-scoped options so they are passed to all files within the package."),Object(o.b)("p",null,"You can learn more about ",Object(o.b)("a",{parentName:"p",href:"/docs/transformations"},"field transformations in this page"),"."),Object(o.b)("p",null,"More examples of field transformations usage:"),Object(o.b)("p",null,"The following rule with match whenever there is a ",Object(o.b)("inlineCode",{parentName:"p"},"gt")," field set, no matter to which value:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'option (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {options { [validate.rules] {int32: {gt: 0}}}}\n match_type: PRESENCE\n set: {\n [scalapb.field] {\n type: "mypkg.GreaterThanAnything"\n }\n }\n }\n ]\n};\n')),Object(o.b)("p",null,"Since the ",Object(o.b)("inlineCode",{parentName:"p"},"when")," clause is ",Object(o.b)("inlineCode",{parentName:"p"},"FieldDescriptorProto"),", it is possible to match on ",Object(o.b)("inlineCode",{parentName:"p"},"type")," and ",Object(o.b)("inlineCode",{parentName:"p"},"label"),". For example,\nthe following will match only when the field is in a ",Object(o.b)("inlineCode",{parentName:"p"},"repeated int32"),":"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'option (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {\n type: TYPE_INT32\n label: LABEL_REPEATED\n options { [validate.rules] {int32: {gt: 0}}}\n }\n match_type: CONTAINS\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveIntInRepeated"\n }\n }\n }\n ]\n};\n')),Object(o.b)("h4",{id:"what-does-the-preprocessor-do"},"What does the preprocessor do?"),Object(o.b)("p",null,"The preprocessor scans for ",Object(o.b)("inlineCode",{parentName:"p"},"field_transformations")," with ",Object(o.b)("inlineCode",{parentName:"p"},"when")," fields that contain ",Object(o.b)("inlineCode",{parentName:"p"},"[validate.rules]")," extensions. Whenever a ",Object(o.b)("inlineCode",{parentName:"p"},"[validate.rules]")," does contain a ",Object(o.b)("inlineCode",{parentName:"p"},"repeated")," or ",Object(o.b)("inlineCode",{parentName:"p"},"map")," validation rules it is assumed to be applied to a singleton type, so we add a copy of the rule for repeated, map-key and map-value context. For example, for this ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt")," rule:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'{\n when: {[validate.rules] {int32: {gt: 0}}}\n set: {\n type: "mypkg.PositiveInt"\n }\n}\n')),Object(o.b)("p",null,"the following field transformations will be automatically added by the preprocessor:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},' {\n when: {options{[validate.rules] {repeated: {int32: {gt: 0}}}}}\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveInt"\n }\n }\n },\n {\n when: {options{[validate.rules] {map: {keys: {int32: {gt: 0}}}}}}\n set: {\n [scalapb.field] {\n key_type: "mypkg.PositiveInt"\n }\n }\n },\n {\n when: {options{[validate.rules] {map: {values: {int32: {gt: 0}}}}}}\n set: {\n [scalapb.field] {\n value_type: "mypkg.PositiveInt"\n }\n }\n }\n')),Object(o.b)("p",null,"This saves you from writing those rules manually so the type transformation is applied in repeated fields or maps. Note that the rewrite mechanism rewrites the ",Object(o.b)("inlineCode",{parentName:"p"},"type")," in the original ",Object(o.b)("inlineCode",{parentName:"p"},"set")," field, into ",Object(o.b)("inlineCode",{parentName:"p"},"key_type")," or ",Object(o.b)("inlineCode",{parentName:"p"},"value_type"),"."),Object(o.b)("h3",{id:"cats-non-empty-collections"},"Cats non-empty collections"),Object(o.b)("p",null,"Using rules like the ones defined above, it is possible to detect when a list or a map are non-empty (via. ",Object(o.b)("inlineCode",{parentName:"p"},"{repeated: { min_items: 1}}")," or ",Object(o.b)("inlineCode",{parentName:"p"},"{map: {min_pairs: 1}}"),", and map them to corresponding non-empty collections. Cats collections require some additional adaptation to ScalaPB since their API is different enough from standard Scala collections. ScalaPB-validate comes with support to automatically map non-empty collections to ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptyMap"),", ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptySet")," and ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptyList"),". To enable, add the following to a proto file. The scope of the settings will be for the entire file. You can turn the setting on for the\nentire package by adding ",Object(o.b)("inlineCode",{parentName:"p"},"scope: PACKAGE"),"."),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'\nsyntax = "proto2";\n\npackage mypackage;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\n\noption (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n [scalapb.validate.file] {\n validate_at_construction : true\n cats_transforms : true\n unique_to_set : true\n }\n};\n')),Object(o.b)("p",null,"As stated above, you will need to have ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb-validate-cats")," listed in\n",Object(o.b)("inlineCode",{parentName:"p"},"libraryDependencies"),". The setting ",Object(o.b)("inlineCode",{parentName:"p"},"unique_to_set")," can be used independently\nof cats to transform a repeated with ",Object(o.b)("inlineCode",{parentName:"p"},"unique: true")," rule to a set."),Object(o.b)("h3",{id:"unboxing-required-fields"},"Unboxing required fields"),Object(o.b)("p",null,"If you use ",Object(o.b)("inlineCode",{parentName:"p"},"validate.message.required")," you can apply a transformation that\nwould set the ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.field.required")," option. As a result, the field will\nnot be boxed in an ",Object(o.b)("inlineCode",{parentName:"p"},"Option")," and parsing will throw an exception if the field\nis missing. To set this transformation add the following to ScalaPB-validate's options:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},"option (scalapb.options) = {\n field_transformations: [\n {\n when: {options: {[validate.rules] {message: {required: true}}}}\n set: {\n [scalapb.field] {\n required: true\n }\n }\n }\n ]\n};\n")),Object(o.b)("h3",{id:"using-with-refined"},"Using with refined"),Object(o.b)("p",null,"As explained in ",Object(o.b)("a",{parentName:"p",href:"/docs/transformations#referencing-rules-values"},'"referencing rule values"'),", it is possible\nto reference field descriptor values in the ",Object(o.b)("inlineCode",{parentName:"p"},"set")," part of field transformation.\nA use case for this is with ",Object(o.b)("a",{parentName:"p",href:"https://github.com/fthomas/refined"},"refined types"),". For example, you can\ndefine the following field transformations:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\n\npackage refined_test;\n\nimport "validate/validate.proto";\nimport "scalapb/validate.proto";\nimport "scalapb/scalapb.proto";\n\noption (scalapb.options) = {\n preprocessors : [ "scalapb-validate-preprocessor" ]\n import : "eu.timepit.refined.api.Refined"\n import : "eu.timepit.refined.numeric._"\n import : "eu.timepit.refined.generic._"\n import : "shapeless.{Witness => W}"\n\n field_transformations : [ {\n when : {options: {[validate.rules] {int32 : {gt : 1}}}} // <-- 1 can be replaced with any number\n set : {type : "Int Refined Greater[$(options.[validate.rules].int32.gt)]"}\n match_type : PRESENCE\n } ]\n};\n\nmessage Test {\n int32 gt_test = 1 [ (validate.rules).int32 = {gt : 5} ]; // transformed to: Int Refined Greater[5]\n}\n')),Object(o.b)("p",null,"For this to work, a typemapper for refined types need to be either put in a package object in the same package where the code is generated, or be manually imported through ",Object(o.b)("inlineCode",{parentName:"p"},"import")," options."),Object(o.b)("p",null,"The typemapper used in scalapb-validate tests is ",Object(o.b)("a",{parentName:"p",href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/main/scala/scalapb/transforms/refined/package.scala"},"here"),"."),Object(o.b)("p",null,"Additional resources:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("a",{parentName:"li",href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/main/protobuf/transforms/refined/refined.proto"},"test proto files (refined.proto)"),": note it uses ",Object(o.b)("inlineCode",{parentName:"li"},"shapeless.Witness")," since ScalaPB-validate is cross-tested for Scala 2.12 and Scala 2.13."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("a",{parentName:"li",href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/test/scala/scalapb/validate/transforms/refined/RefinedSpec.scala"},"end-to-end tests")," demonstrating compile-time validation.")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/10204607.43c74fed.js b/10204607.43c74fed.js deleted file mode 100644 index 6bef0fad6..000000000 --- a/10204607.43c74fed.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return b})),a.d(t,"b",(function(){return u}));var n=a(0),i=a.n(n);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var p=i.a.createContext({}),c=function(e){var t=i.a.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},b=function(e){var t=c(e.components);return i.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},m=i.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,r=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),b=c(a),m=n,u=b["".concat(r,".").concat(m)]||b[m]||d[m]||o;return a?i.a.createElement(u,l(l({ref:t},p),{},{components:a})):i.a.createElement(u,l({ref:t},p))}));function u(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,r=new Array(o);r[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:n,r[1]=l;for(var p=2;p (Compile / sourceManaged).value / "scalapb",\n scalapb.validate.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf"\n)\n')),Object(o.b)("p",null,"Note that we are adding ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb-validate-core")," as a ",Object(o.b)("inlineCode",{parentName:"p"},"protobuf")," dependency. This makes it possible to import ",Object(o.b)("inlineCode",{parentName:"p"},"validate/validate.proto")," from your own protos."),Object(o.b)("p",null,"If ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/sbt-settings#additional-options-to-the-generator"}),"ScalaPB generator parameters")," are passed via ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.gen(options: GeneratorOption*)"),", the same parameters must be passed to ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.validate.gen(options: GeneratorOption*)"),"."),Object(o.b)("h2",{id:"using-the-generated-code"},"Using the generated code"),Object(o.b)("p",null,"Generated code for both ScalaPB and scalapb-validate is generated at compilation time. In ",Object(o.b)("inlineCode",{parentName:"p"},"sbt"),", just type ",Object(o.b)("inlineCode",{parentName:"p"},"compile"),"."),Object(o.b)("p",null,"In addition to the standard ScalaPB generated files, scalapb-validate will generate a validator object for each message based on its protoc-gen-validate rules. For a message named ",Object(o.b)("inlineCode",{parentName:"p"},"Msg")," the validator object will be named ",Object(o.b)("inlineCode",{parentName:"p"},"MsgValidator")," and will extend ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.validate.Validator[Msg]"),". An implicit instance of the validator is added to the companion object of each message, which makes it possible to write ",Object(o.b)("inlineCode",{parentName:"p"},"Validator[Msg]")," to obtain an instance of the validator."),Object(o.b)("h2",{id:"validators"},"Validators"),Object(o.b)("p",null,"The validator object is an object with a ",Object(o.b)("inlineCode",{parentName:"p"},"validate")," method that takes an instance of a message and returns the validation result: The ",Object(o.b)("inlineCode",{parentName:"p"},"Validator[T]")," is defined as follows:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"trait Validator[T] {\n def validate(t: T): Result\n}\n")),Object(o.b)("p",null,"where ",Object(o.b)("inlineCode",{parentName:"p"},"Result")," is a data structure that can be either a ",Object(o.b)("inlineCode",{parentName:"p"},"Success")," or a ",Object(o.b)("inlineCode",{parentName:"p"},"Failure"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"sealed trait Result {\n def isSuccess: Boolean\n def isFailure: Boolean\n}\n\ncase object Success extends Result { ... }\n\ncase class Failure(violations: List[ValidationException]) extends Result { ... }\n")),Object(o.b)("p",null,"Therefore, the validation for the test person casn be run like this:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'Validator[Person].validate(personInstance) match {\n case Success => println("Success!")\n case Failure(violations) => println(violations)\n}\n')),Object(o.b)("h2",{id:"package-scoped-extension-options"},"Package-scoped extension options"),Object(o.b)("p",null,"ScalaPB-validate further extends ScalaPB's package-scoped options to achieve additional customization:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto2";\n\npackage mypkg;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\n\noption (scalapb.options) = {\n scope: PACKAGE\n [scalapb.validate.file] {\n validate_at_construction: true\n insert_validator_instance: true\n skip: false\n }\n};\n')),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"validate_at_construction")," when true, a check for validity is added to the message class body, so construction of invalid messages results in a validation exception. Default: ",Object(o.b)("inlineCode",{parentName:"li"},"false"),"."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"insert_validator_instance")," when true, implicit instance of a ",Object(o.b)("inlineCode",{parentName:"li"},"Validator")," is added to the companion object of the message. This enables writing ",Object(o.b)("inlineCode",{parentName:"li"},"Validator[MyMsg].validate(instance)"),". Default: ",Object(o.b)("inlineCode",{parentName:"li"},"true"),"."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"skip")," when true, skips gnerating validators for messages defined in this file. This can be set for a third-party package to work around the problem that there are no validators for it. See ",Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/scalapb-validate/tree/master/e2e/src/main/protobuf/skip"}),"this testcase")," for a usage example.")),Object(o.b)("h2",{id:"rule-based-type-customization"},"Rule-based type customization"),Object(o.b)("p",null,"Starting from version 0.10.10, ScalaPB provides a way to customize its own options by writing rules that are matched against\narbitrary protobuf options. When these rules are matched, additional ScalaPB options are added to the matched entity. For example, you can create a transformation that whenever a field has a PGV-rule like ",Object(o.b)("inlineCode",{parentName:"p"},"int32: { gt: 0 }}"),", then it will be typemapped to a custom class ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt"),"."),Object(o.b)("h3",{id:"installation-1"},"Installation"),Object(o.b)("p",null,"The features described in this section have the following version requirements:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"sbt-protoc >= ",Object(o.b)("inlineCode",{parentName:"li"},"1.0.0")),Object(o.b)("li",{parentName:"ul"},"ScalaPB >= ",Object(o.b)("inlineCode",{parentName:"li"},"0.10.10")),Object(o.b)("li",{parentName:"ul"},"scalapb-validate >= ",Object(o.b)("inlineCode",{parentName:"li"},"0.2.0"))),Object(o.b)("p",null,"While field transformation is a generic ScalaPB mechanism, it is also recommended that you add\nscalapb-validate's preprocessor to ",Object(o.b)("inlineCode",{parentName:"p"},"PB.targets"),". The preprocessor does two things:"),Object(o.b)("ol",null,Object(o.b)("li",{parentName:"ol"},"Provides field transformations for ",Object(o.b)("inlineCode",{parentName:"li"},"Set")," and cats data types."),Object(o.b)("li",{parentName:"ol"},"Expand your PGV-based rules such that they match repeated items, map keys and map values.")),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'Compile / PB.targets := Seq(\n scalapb.validate.preprocessor() -> (Compile / sourceManaged).value / "scalapb",\n scalapb.gen() -> (Compile / sourceManaged).value / "scalapb",\n scalapb.validate.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-validate-core" % scalapb.validate.compiler.BuildInfo.version % "protobuf",\n\n // If you are using Cats transformations:\n "com.thesamet.scalapb" %% "scalapb-validate-cats" % scalapb.validate.compiler.BuildInfo.version,\n "org.typelevel" %% "cats-core" % "2.3.0"\n)\n')),Object(o.b)("p",null,"There is an example project ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/scalapb-validate-demo"}),"available on github"),"."),Object(o.b)("h3",{id:"field-transformations"},"Field transformations"),Object(o.b)("p",null,"If you want all positive integers to be typemapped to a Scala class called ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt")," you can\ncreate a proto file with the following content:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto2";\n\npackage mypackage;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\nimport "validate/validate.proto";\n\noption (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {options { [validate.rules] {int32: {gt: 0}} }}\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveInt"\n }\n }\n }\n ]\n};\n')),Object(o.b)("p",null,"The scope of this definition is the entire protobuf file it is found in. Field tranformations can also\nbe used in package-scoped options so they are passed to all files within the package."),Object(o.b)("p",null,"You can learn more about ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/transformations"}),"field transformations in this page"),"."),Object(o.b)("p",null,"More examples of field transformations usage:"),Object(o.b)("p",null,"The following rule with match whenever there is a ",Object(o.b)("inlineCode",{parentName:"p"},"gt")," field set, no matter to which value:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'option (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {options { [validate.rules] {int32: {gt: 0}}}}\n match_type: PRESENCE\n set: {\n [scalapb.field] {\n type: "mypkg.GreaterThanAnything"\n }\n }\n }\n ]\n};\n')),Object(o.b)("p",null,"Since the ",Object(o.b)("inlineCode",{parentName:"p"},"when")," clause is ",Object(o.b)("inlineCode",{parentName:"p"},"FieldDescriptorProto"),", it is possible to match on ",Object(o.b)("inlineCode",{parentName:"p"},"type")," and ",Object(o.b)("inlineCode",{parentName:"p"},"label"),". For example,\nthe following will match only when the field is in a ",Object(o.b)("inlineCode",{parentName:"p"},"repeated int32"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'option (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n field_transformations: [\n {\n when: {\n type: TYPE_INT32\n label: LABEL_REPEATED\n options { [validate.rules] {int32: {gt: 0}}}\n }\n match_type: CONTAINS\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveIntInRepeated"\n }\n }\n }\n ]\n};\n')),Object(o.b)("h4",{id:"what-does-the-preprocessor-do"},"What does the preprocessor do?"),Object(o.b)("p",null,"The preprocessor scans for ",Object(o.b)("inlineCode",{parentName:"p"},"field_transformations")," with ",Object(o.b)("inlineCode",{parentName:"p"},"when")," fields that contain ",Object(o.b)("inlineCode",{parentName:"p"},"[validate.rules]")," extensions. Whenever a ",Object(o.b)("inlineCode",{parentName:"p"},"[validate.rules]")," does contain a ",Object(o.b)("inlineCode",{parentName:"p"},"repeated")," or ",Object(o.b)("inlineCode",{parentName:"p"},"map")," validation rules it is assumed to be applied to a singleton type, so we add a copy of the rule for repeated, map-key and map-value context. For example, for this ",Object(o.b)("inlineCode",{parentName:"p"},"PositiveInt")," rule:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'{\n when: {[validate.rules] {int32: {gt: 0}}}\n set: {\n type: "mypkg.PositiveInt"\n }\n}\n')),Object(o.b)("p",null,"the following field transformations will be automatically added by the preprocessor:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{}),' {\n when: {options{[validate.rules] {repeated: {int32: {gt: 0}}}}}\n set: {\n [scalapb.field] {\n type: "mypkg.PositiveInt"\n }\n }\n },\n {\n when: {options{[validate.rules] {map: {keys: {int32: {gt: 0}}}}}}\n set: {\n [scalapb.field] {\n key_type: "mypkg.PositiveInt"\n }\n }\n },\n {\n when: {options{[validate.rules] {map: {values: {int32: {gt: 0}}}}}}\n set: {\n [scalapb.field] {\n value_type: "mypkg.PositiveInt"\n }\n }\n }\n')),Object(o.b)("p",null,"This saves you from writing those rules manually so the type transformation is applied in repeated fields or maps. Note that the rewrite mechanism rewrites the ",Object(o.b)("inlineCode",{parentName:"p"},"type")," in the original ",Object(o.b)("inlineCode",{parentName:"p"},"set")," field, into ",Object(o.b)("inlineCode",{parentName:"p"},"key_type")," or ",Object(o.b)("inlineCode",{parentName:"p"},"value_type"),"."),Object(o.b)("h3",{id:"cats-non-empty-collections"},"Cats non-empty collections"),Object(o.b)("p",null,"Using rules like the ones defined above, it is possible to detect when a list or a map are non-empty (via. ",Object(o.b)("inlineCode",{parentName:"p"},"{repeated: { min_items: 1}}")," or ",Object(o.b)("inlineCode",{parentName:"p"},"{map: {min_pairs: 1}}"),", and map them to corresponding non-empty collections. Cats collections require some additional adaptation to ScalaPB since their API is different enough from standard Scala collections. ScalaPB-validate comes with support to automatically map non-empty collections to ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptyMap"),", ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptySet")," and ",Object(o.b)("inlineCode",{parentName:"p"},"NonEmptyList"),". To enable, add the following to a proto file. The scope of the settings will be for the entire file. You can turn the setting on for the\nentire package by adding ",Object(o.b)("inlineCode",{parentName:"p"},"scope: PACKAGE"),"."),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'\nsyntax = "proto2";\n\npackage mypackage;\n\nimport "scalapb/scalapb.proto";\nimport "scalapb/validate.proto";\n\noption (scalapb.options) = {\n preprocessors: ["scalapb-validate-preprocessor"]\n [scalapb.validate.file] {\n validate_at_construction : true\n cats_transforms : true\n unique_to_set : true\n }\n};\n')),Object(o.b)("p",null,"As stated above, you will need to have ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb-validate-cats")," listed in\n",Object(o.b)("inlineCode",{parentName:"p"},"libraryDependencies"),". The setting ",Object(o.b)("inlineCode",{parentName:"p"},"unique_to_set")," can be used independently\nof cats to transform a repeated with ",Object(o.b)("inlineCode",{parentName:"p"},"unique: true")," rule to a set."),Object(o.b)("h3",{id:"unboxing-required-fields"},"Unboxing required fields"),Object(o.b)("p",null,"If you use ",Object(o.b)("inlineCode",{parentName:"p"},"validate.message.required")," you can apply a transformation that\nwould set the ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.field.required")," option. As a result, the field will\nnot be boxed in an ",Object(o.b)("inlineCode",{parentName:"p"},"Option")," and parsing will throw an exception if the field\nis missing. To set this transformation add the following to ScalaPB-validate's options:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),"option (scalapb.options) = {\n field_transformations: [\n {\n when: {options: {[validate.rules] {message: {required: true}}}}\n set: {\n [scalapb.field] {\n required: true\n }\n }\n }\n ]\n};\n")),Object(o.b)("h3",{id:"using-with-refined"},"Using with refined"),Object(o.b)("p",null,"As explained in ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/transformations#referencing-rules-values"}),'"referencing rule values"'),", it is possible\nto reference field descriptor values in the ",Object(o.b)("inlineCode",{parentName:"p"},"set")," part of field transformation.\nA use case for this is with ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/fthomas/refined"}),"refined types"),". For example, you can\ndefine the following field transformations:"),Object(o.b)("pre",null,Object(o.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\n\npackage refined_test;\n\nimport "validate/validate.proto";\nimport "scalapb/validate.proto";\nimport "scalapb/scalapb.proto";\n\noption (scalapb.options) = {\n preprocessors : [ "scalapb-validate-preprocessor" ]\n import : "eu.timepit.refined.api.Refined"\n import : "eu.timepit.refined.numeric._"\n import : "eu.timepit.refined.generic._"\n import : "shapeless.{Witness => W}"\n\n field_transformations : [ {\n when : {options: {[validate.rules] {int32 : {gt : 1}}}} // <-- 1 can be replaced with any number\n set : {type : "Int Refined Greater[$(options.[validate.rules].int32.gt)]"}\n match_type : PRESENCE\n } ]\n};\n\nmessage Test {\n int32 gt_test = 1 [ (validate.rules).int32 = {gt : 5} ]; // transformed to: Int Refined Greater[5]\n}\n')),Object(o.b)("p",null,"For this to work, a typemapper for refined types need to be either put in a package object in the same package where the code is generated, or be manually imported through ",Object(o.b)("inlineCode",{parentName:"p"},"import")," options."),Object(o.b)("p",null,"The typemapper used in scalapb-validate tests is ",Object(o.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/main/scala/scalapb/transforms/refined/package.scala"}),"here"),"."),Object(o.b)("p",null,"Additional resources:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/main/protobuf/transforms/refined/refined.proto"}),"test proto files (refined.proto)"),": note it uses ",Object(o.b)("inlineCode",{parentName:"li"},"shapeless.Witness")," since ScalaPB-validate is cross-tested for Scala 2.12 and Scala 2.13."),Object(o.b)("li",{parentName:"ul"},Object(o.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/scalapb-validate/blob/0.2.x-preview/e2e/src/test/scala/scalapb/validate/transforms/refined/RefinedSpec.scala"}),"end-to-end tests")," demonstrating compile-time validation.")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/17896441.4206d928.js b/17896441.4580ba69.js similarity index 68% rename from 17896441.4206d928.js rename to 17896441.4580ba69.js index 69e0f60ff..6d3081657 100644 --- a/17896441.4206d928.js +++ b/17896441.4580ba69.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{115:function(e,t,a){"use strict";a.r(t);var n=a(0),l=a.n(n),r=a(23),c=a(121),i=a(21),o=a(124),m=a(122);var s=function(e){var t=e.metadata;return l.a.createElement("nav",{className:"pagination-nav","aria-label":"Blog list page navigation"},l.a.createElement("div",{className:"pagination-nav__item"},t.previous&&l.a.createElement(m.a,{className:"pagination-nav__link",to:t.previous.permalink},l.a.createElement("div",{className:"pagination-nav__sublabel"},"Previous"),l.a.createElement("div",{className:"pagination-nav__label"},"\xab ",t.previous.title))),l.a.createElement("div",{className:"pagination-nav__item pagination-nav__item--next"},t.next&&l.a.createElement(m.a,{className:"pagination-nav__link",to:t.next.permalink},l.a.createElement("div",{className:"pagination-nav__sublabel"},"Next"),l.a.createElement("div",{className:"pagination-nav__label"},t.next.title," \xbb"))))},u=a(123);var d=function(){var e=Object(i.default)().siteConfig.title,t=Object(u.useActivePlugin)({failfast:!0}).pluginId,a=Object(c.useDocsPreferredVersion)(t).savePreferredVersionName,n=Object(u.useActiveVersion)(t),r=Object(u.useDocVersionSuggestions)(t),o=r.latestDocSuggestion,s=r.latestVersionSuggestion;if(!s)return l.a.createElement(l.a.Fragment,null);var d,v=null!=o?o:(d=s).docs.find((function(e){return e.id===d.mainDocId}));return l.a.createElement("div",{className:"alert alert--warning margin-bottom--md",role:"alert"},"current"===n.name?l.a.createElement("div",null,"This is unreleased documentation for ",e," ",l.a.createElement("strong",null,n.label)," version."):l.a.createElement("div",null,"This is documentation for ",e," ",l.a.createElement("strong",null,n.label),", which is no longer actively maintained."),l.a.createElement("div",{className:"margin-top--md"},"For up-to-date documentation, see the"," ",l.a.createElement("strong",null,l.a.createElement(m.a,{to:v.path,onClick:function(){return a(s.name)}},"latest version"))," ","(",s.label,")."))},v=a(136),E=a(131),g=a(120),f=a(75),p=a.n(f);t.default=function(e){var t,a=Object(i.default)().siteConfig.url,n=e.content,m=n.metadata,f=n.frontMatter,b=f.image,N=f.keywords,h=f.hide_title,_=f.hide_table_of_contents,O=m.description,j=m.title,w=m.permalink,k=m.editUrl,y=m.lastUpdatedAt,C=m.lastUpdatedBy,x=Object(u.useActivePlugin)({failfast:!0}).pluginId,L=Object(u.useVersions)(x),I=Object(u.useActiveVersion)(x),A=L.length>1,S=Object(c.useTitleFormatter)(j),V=Object(o.a)(b,{absolute:!0});return l.a.createElement(l.a.Fragment,null,l.a.createElement(r.a,null,l.a.createElement("title",null,S),l.a.createElement("meta",{property:"og:title",content:S}),O&&l.a.createElement("meta",{name:"description",content:O}),O&&l.a.createElement("meta",{property:"og:description",content:O}),N&&N.length&&l.a.createElement("meta",{name:"keywords",content:N.join(",")}),b&&l.a.createElement("meta",{property:"og:image",content:V}),b&&l.a.createElement("meta",{name:"twitter:image",content:V}),b&&l.a.createElement("meta",{name:"twitter:image:alt",content:"Image for "+j}),w&&l.a.createElement("meta",{property:"og:url",content:a+w}),w&&l.a.createElement("link",{rel:"canonical",href:a+w})),l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:Object(g.a)("col",(t={},t[p.a.docItemCol]=!_,t))},l.a.createElement(d,null),l.a.createElement("div",{className:p.a.docItemContainer},l.a.createElement("article",null,A&&l.a.createElement("div",null,l.a.createElement("span",{className:"badge badge--secondary"},"Version: ",I.label)),!h&&l.a.createElement("header",null,l.a.createElement("h1",{className:p.a.docTitle},j)),l.a.createElement("div",{className:"markdown"},l.a.createElement(n,null))),(k||y||C)&&l.a.createElement("div",{className:"margin-vert--xl"},l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:"col"},k&&l.a.createElement("a",{href:k,target:"_blank",rel:"noreferrer noopener"},l.a.createElement(E.a,null),"Edit this page")),(y||C)&&l.a.createElement("div",{className:"col text--right"},l.a.createElement("em",null,l.a.createElement("small",null,"Last updated"," ",y&&l.a.createElement(l.a.Fragment,null,"on"," ",l.a.createElement("time",{dateTime:new Date(1e3*y).toISOString(),className:p.a.docLastUpdatedAt},new Date(1e3*y).toLocaleDateString()),C&&" "),C&&l.a.createElement(l.a.Fragment,null,"by ",l.a.createElement("strong",null,C)),!1))))),l.a.createElement("div",{className:"margin-vert--lg"},l.a.createElement(s,{metadata:m})))),!_&&n.toc&&l.a.createElement("div",{className:"col col--3"},l.a.createElement(v.a,{toc:n.toc}))))}},131:function(e,t,a){"use strict";var n=a(3),l=a(7),r=a(0),c=a.n(r),i=a(120),o=a(57),m=a.n(o);t.a=function(e){var t=e.className,a=Object(l.a)(e,["className"]);return c.a.createElement("svg",Object(n.a)({fill:"currentColor",height:"1.2em",width:"1.2em",preserveAspectRatio:"xMidYMid meet",role:"img",viewBox:"0 0 40 40",className:Object(i.a)(m.a.iconEdit,t)},a),c.a.createElement("g",null,c.a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}},136:function(e,t,a){"use strict";var n=a(0),l=a.n(n),r=a(120);var c=function(e,t,a){var l=Object(n.useState)(void 0),r=l[0],c=l[1];Object(n.useEffect)((function(){function n(){var n=function(){var e=Array.from(document.getElementsByClassName("anchor")),t=e.find((function(e){return e.getBoundingClientRect().top>=a}));if(t){if(t.getBoundingClientRect().top>=a){var n=e[e.indexOf(t)-1];return null!=n?n:t}return t}return e[e.length-1]}();if(n)for(var l=0,i=!1,o=document.getElementsByClassName(e);l1,S=Object(c.useTitleFormatter)(j),V=Object(o.a)(b,{absolute:!0});return l.a.createElement(l.a.Fragment,null,l.a.createElement(r.a,null,l.a.createElement("title",null,S),l.a.createElement("meta",{property:"og:title",content:S}),O&&l.a.createElement("meta",{name:"description",content:O}),O&&l.a.createElement("meta",{property:"og:description",content:O}),N&&N.length&&l.a.createElement("meta",{name:"keywords",content:N.join(",")}),b&&l.a.createElement("meta",{property:"og:image",content:V}),b&&l.a.createElement("meta",{name:"twitter:image",content:V}),b&&l.a.createElement("meta",{name:"twitter:image:alt",content:"Image for "+j}),w&&l.a.createElement("meta",{property:"og:url",content:a+w}),w&&l.a.createElement("link",{rel:"canonical",href:a+w})),l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:Object(g.a)("col",(t={},t[p.a.docItemCol]=!_,t))},l.a.createElement(d,null),l.a.createElement("div",{className:p.a.docItemContainer},l.a.createElement("article",null,A&&l.a.createElement("div",null,l.a.createElement("span",{className:"badge badge--secondary"},"Version: ",I.label)),!h&&l.a.createElement("header",null,l.a.createElement("h1",{className:p.a.docTitle},j)),l.a.createElement("div",{className:"markdown"},l.a.createElement(n,null))),(k||y||C)&&l.a.createElement("div",{className:"margin-vert--xl"},l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:"col"},k&&l.a.createElement("a",{href:k,target:"_blank",rel:"noreferrer noopener"},l.a.createElement(E.a,null),"Edit this page")),(y||C)&&l.a.createElement("div",{className:"col text--right"},l.a.createElement("em",null,l.a.createElement("small",null,"Last updated"," ",y&&l.a.createElement(l.a.Fragment,null,"on"," ",l.a.createElement("time",{dateTime:new Date(1e3*y).toISOString(),className:p.a.docLastUpdatedAt},new Date(1e3*y).toLocaleDateString()),C&&" "),C&&l.a.createElement(l.a.Fragment,null,"by ",l.a.createElement("strong",null,C)),!1))))),l.a.createElement("div",{className:"margin-vert--lg"},l.a.createElement(s,{metadata:m})))),!_&&n.toc&&l.a.createElement("div",{className:"col col--3"},l.a.createElement(v.a,{toc:n.toc}))))}},131:function(e,t,a){"use strict";var n=a(3),l=a(7),r=a(0),c=a.n(r),i=a(120),o=a(57),m=a.n(o),s=["className"];t.a=function(e){var t=e.className,a=Object(l.a)(e,s);return c.a.createElement("svg",Object(n.a)({fill:"currentColor",height:"1.2em",width:"1.2em",preserveAspectRatio:"xMidYMid meet",role:"img",viewBox:"0 0 40 40",className:Object(i.a)(m.a.iconEdit,t)},a),c.a.createElement("g",null,c.a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}},136:function(e,t,a){"use strict";var n=a(0),l=a.n(n),r=a(120);var c=function(e,t,a){var l=Object(n.useState)(void 0),r=l[0],c=l[1];Object(n.useEffect)((function(){function n(){var n=function(){var e=Array.from(document.getElementsByClassName("anchor")),t=e.find((function(e){return e.getBoundingClientRect().top>=a}));if(t){if(t.getBoundingClientRect().top>=a){var n=e[e.indexOf(t)-1];return null!=n?n:t}return t}return e[e.length-1]}();if(n)for(var l=0,i=!1,o=document.getElementsByClassName(e);l=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=r.a.createContext({}),s=function(e){var n=r.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},b=function(e){var n=s(e.components);return r.a.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},d=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),b=s(t),d=a,m=b["".concat(c,".").concat(d)]||b[d]||u[d]||o;return t?r.a.createElement(m,l(l({ref:n},p),{},{components:t})):r.a.createElement(m,l({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,c=new Array(o);c[0]=d;var l={};for(var i in n)hasOwnProperty.call(n,i)&&(l[i]=n[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var p=2;p (Compile / sourceManaged).value / "scalapb"\n)\n\n// (optional) If you need scalapb/scalapb.proto or anything from\n// google/protobuf/*.proto\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n)\n')),Object(o.b)("p",null,"ScalaPB will look for protocol buffer (",Object(o.b)("inlineCode",{parentName:"p"},".proto"),") files under ",Object(o.b)("inlineCode",{parentName:"p"},"src/main/protobuf"),", which can be customized. Running the ",Object(o.b)("inlineCode",{parentName:"p"},"compile")," command in sbt will generate Scala\nsources for your protos and compile them."),Object(o.b)("p",null,"For additional configuration options, see\n",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/sbt-settings"}),"ScalaPB SBT Settings"),"."),Object(o.b)("h2",{id:"running-standalone-using-scalapbc"},"Running Standalone Using scalapbc"),Object(o.b)("p",null,"If you would like to compile protocol buffers into Scala outside SBT, you can\nuse scalapbc (ScalaPB compiler)."),Object(o.b)("p",null,"See ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/scalapbc"}),"ScalaPBC"),"."),Object(o.b)("h2",{id:"running-from-maven"},"Running from Maven"),Object(o.b)("p",null,"Using ScalaPBC, you can get maven to generate the code for you.\nCheck out the ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://github.com/thesamet/scalapb-maven-example"}),"ScalaPB Maven example"),"."),Object(o.b)("h2",{id:"next"},"Next:"),Object(o.b)("p",null,"Read about the ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/generated-code"}),"Generated Code"),"."))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/1b891fa3.f599a486.js b/1b891fa3.f599a486.js new file mode 100644 index 000000000..7332180f6 --- /dev/null +++ b/1b891fa3.f599a486.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return u})),t.d(n,"b",(function(){return m}));var a=t(0),r=t.n(a);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function l(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function c(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=r.a.createContext({}),s=function(e){var n=r.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},u=function(e){var n=s(e.components);return r.a.createElement(p.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},d=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),u=s(t),d=a,m=u["".concat(l,".").concat(d)]||u[d]||b[d]||o;return t?r.a.createElement(m,c(c({ref:n},p),{},{components:t})):r.a.createElement(m,c({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,l=new Array(o);l[0]=d;var c={};for(var i in n)hasOwnProperty.call(n,i)&&(c[i]=n[i]);c.originalType=e,c.mdxType="string"==typeof e?e:a,l[1]=c;for(var p=2;p (Compile / sourceManaged).value / "scalapb"\n)\n\n// (optional) If you need scalapb/scalapb.proto or anything from\n// google/protobuf/*.proto\nlibraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n)\n')),Object(o.b)("p",null,"ScalaPB will look for protocol buffer (",Object(o.b)("inlineCode",{parentName:"p"},".proto"),") files under ",Object(o.b)("inlineCode",{parentName:"p"},"src/main/protobuf"),", which can be customized. Running the ",Object(o.b)("inlineCode",{parentName:"p"},"compile")," command in sbt will generate Scala\nsources for your protos and compile them."),Object(o.b)("p",null,"For additional configuration options, see\n",Object(o.b)("a",{parentName:"p",href:"/docs/sbt-settings"},"ScalaPB SBT Settings"),"."),Object(o.b)("h2",{id:"running-standalone-using-scalapbc"},"Running Standalone Using scalapbc"),Object(o.b)("p",null,"If you would like to compile protocol buffers into Scala outside SBT, you can\nuse scalapbc (ScalaPB compiler)."),Object(o.b)("p",null,"See ",Object(o.b)("a",{parentName:"p",href:"/docs/scalapbc"},"ScalaPBC"),"."),Object(o.b)("h2",{id:"running-from-maven"},"Running from Maven"),Object(o.b)("p",null,"Using ScalaPBC, you can get maven to generate the code for you.\nCheck out the ",Object(o.b)("a",{parentName:"p",href:"https://github.com/thesamet/scalapb-maven-example"},"ScalaPB Maven example"),"."),Object(o.b)("h2",{id:"next"},"Next:"),Object(o.b)("p",null,"Read about the ",Object(o.b)("a",{parentName:"p",href:"/docs/generated-code"},"Generated Code"),"."))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/1d35a65b.bfc2dd20.js b/1d35a65b.bfc2dd20.js new file mode 100644 index 000000000..7b5e63652 --- /dev/null +++ b/1d35a65b.bfc2dd20.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return b})),a.d(t,"b",(function(){return d}));var n=a(0),o=a.n(n);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var r=o.a.createContext({}),c=function(e){var t=o.a.useContext(r),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},b=function(e){var t=c(e.components);return o.a.createElement(r.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},u=o.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,r=p(e,["components","mdxType","originalType","parentName"]),b=c(a),u=n,d=b["".concat(s,".").concat(u)]||b[u]||m[u]||i;return a?o.a.createElement(d,l(l({ref:t},r),{},{components:a})):o.a.createElement(d,l({ref:t},r))}));function d(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,s=new Array(i);s[0]=u;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:n,s[1]=l;for(var r=2;r "path/to/package.proto")\n)\n')),Object(i.b)("p",null,"The path above is relative to the root directory of the published JAR (so ",Object(i.b)("inlineCode",{parentName:"p"},"src/main/protobuf")," is not needed). Users add your library to their projects like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},'libraryDependencies ++= Seq(\n "com.example" %% "your-library" % "0.1.0",\n "com.example" %% "your-library" % "0.1.0" % "protobuf"\n)\n')),Object(i.b)("p",null,"The first dependency provides the precompiled class files. The second dependency makes it possible\nfor users to import the protos in the jar file. ",Object(i.b)("inlineCode",{parentName:"p"},"sbt-protoc")," will look for the\n",Object(i.b)("inlineCode",{parentName:"p"},"ScalaPB-Options-Proto")," attribute in the jar's manifest and automatically add the package scoped options file\nto the protoc command line."),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",{parentName:"div",className:"admonition-heading"},Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",{parentName:"h5",className:"admonition-icon"},Object(i.b)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},Object(i.b)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),Object(i.b)("div",{parentName:"div",className:"admonition-content"},Object(i.b)("p",{parentName:"div"},"Since the package-scoped options file is used as a source file in multiple\nprojects, it should not define any types (messages, enums, services).\nThis ensures that the package-scoped proto file does not generate any code on its own so we don't\nend up with duplicate class files."))),Object(i.b)("h3",{id:"disabling-package-scoped-options-processing"},"Disabling package-scoped options processing"),Object(i.b)("p",null,"As a consumer of third-party dependencies that come with options proto, you\ncan disable the behavior of automatically adding the options proto to protoc\nby setting"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"Compile / PB.manifestProcessing := false\n")),Object(i.b)("p",null,"in sbt. In that case, it is your responsibility to either manually ",Object(i.b)("inlineCode",{parentName:"p"},"import")," the option protos in one\nof your own project source files so it gets applied, or ensure that the\ngenerator settigs used in your project are consistent with the ones used to\ngenerate the dependency. Differences in settings can lead to generated code\nthat does not compile."),Object(i.b)("h2",{id:"auxiliary-options"},"Auxiliary options"),Object(i.b)("p",null,"In some situations, you may want to set some options in a proto file, but without\nmodifying the original proto file or adding anything ScalaPB-specific to it. To accomplish\nthat, you can define auxiliary options under package-scoped options."),Object(i.b)("p",null,"For example, if you are given this proto file:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\npackage a.b.c;\nmessage Foo {\n string hello = 1;\n}\n')),Object(i.b)("p",null,"You can add a file ",Object(i.b)("inlineCode",{parentName:"p"},"package.proto")," with the following content:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\npackage a.b.c;\nimport "scalapb/scalapb.proto";\noption (scalapb.options) = {\n scope: PACKAGE\n aux_message_options: [\n {\n target: "a.b.c.Foo"\n options: {\n extends: "com.myexample.SomeTrait"\n }\n }\n ]\n aux_field_options: [\n {\n target: "a.b.c.Foo.hello"\n options: {\n scala_name: "goodbye"\n }\n }\n ]\n};\n')),Object(i.b)("p",null,"The list ",Object(i.b)("inlineCode",{parentName:"p"},"aux_message_options")," contains options targeted at different messages define under the same proto package of the package-scoped options. The ",Object(i.b)("inlineCode",{parentName:"p"},"target")," name needs to be fully-qualified message name in the protobuf namespace. Similar to ",Object(i.b)("inlineCode",{parentName:"p"},"aux_message_options"),", we also have ",Object(i.b)("inlineCode",{parentName:"p"},"aux_enum_options"),", ",Object(i.b)("inlineCode",{parentName:"p"},"aux_enum_value_options")," and ",Object(i.b)("inlineCode",{parentName:"p"},"aux_field_options"),". See ",Object(i.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/tree/master/e2e/src/main/protobuf/scoped"},"example usage here"),"."),Object(i.b)("h2",{id:"primitive-wrappers"},"Primitive wrappers"),Object(i.b)("p",null,"In proto 3, unlike proto 2, primitives are not wrapped in an option by default.\nThe standard technique to obtain an optional primitive is to wrap it inside a\nmessage (since messages are provided inside an ",Object(i.b)("inlineCode",{parentName:"p"},"Option"),"). Google provides\nstandard wrappers to the primitive types in\n",Object(i.b)("a",{parentName:"p",href:"https://github.com/google/protobuf/blob/master/src/google/protobuf/wrappers.proto"},"wrappers.proto"),"."),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"primitive_wrappers")," is enabled by default for ScalaPB>=0.6.0. Whenever one\nof the standard wrappers is used, it will be mapped to ",Object(i.b)("inlineCode",{parentName:"p"},"Option[X]")," where ",Object(i.b)("inlineCode",{parentName:"p"},"X"),"\nis a primitive type. For example:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\n\nimport "google/protobuf/wrappers.proto";\n\nmessage MyMessage {\n google.protobuf.Int32Value my_int32 = 5;\n}\n')),Object(i.b)("p",null,"would generate"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"case class MyMessage(myInt32: Option[Int]) extends ...\n")),Object(i.b)("p",null,"To disable primitive wrappers in a file:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'import "scalapb/scalapb.proto";\noption (scalapb.options) = {\n no_primitive_wrappers: true\n};\n')),Object(i.b)("p",null,"In versions of ScalaPB prior to 0.6.0, primitive wrappers had to be turned on\nmanually in each file:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'import "scalapb/scalapb.proto";\noption (scalapb.options) = {\n primitive_wrappers: true\n};\n')),Object(i.b)("h2",{id:"custom-base-traits-for-messages"},"Custom base traits for messages"),Object(i.b)("p",null,"Note: this option is available in ScalaPB 0.6.1 and later."),Object(i.b)("p",null,"ScalaPBs allows you to specify custom base traits to a generated case\nclass. This is useful when you have a few messages that share common fields\nand you would like to be able to access those fields through a single trait."),Object(i.b)("p",null,"Example:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'import "scalapb/scalapb.proto";\n\nmessage CustomerWithPhone {\n option (scalapb.message).extends = "com.thesamet.pb.BaseCustomer";\n\n optional string customer_id = 1;\n optional string name = 2;\n optional string phone = 3;\n}\n')),Object(i.b)("p",null,"In your code, define the base trait ",Object(i.b)("inlineCode",{parentName:"p"},"DomainEvent")," and include any subset of the fields:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"package com.thesamet.pb\n\ntrait BaseCustomer {\n def customerId: Option[String]\n def name: Option[String]\n}\n")),Object(i.b)("p",null,"You can specify any number of base traits for a message."),Object(i.b)("p",null,"It is also possible to make the generated companion classes extend a class\nor trait, by using the ",Object(i.b)("inlineCode",{parentName:"p"},"companion_extends")," option. For example:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message MyMessage {\n option (scalapb.message).extends = "MySuperClass";\n option (scalapb.message).companion_extends = "MySuperCompanionClass";\n int32 n = 1;\n}\n')),Object(i.b)("p",null,"Will generate a case class that extends ",Object(i.b)("inlineCode",{parentName:"p"},"MySuperClass"),", and the companion\nobject will extend ",Object(i.b)("inlineCode",{parentName:"p"},"MySuperCompanionClass"),"."),Object(i.b)("h2",{id:"custom-base-traits-for-sealed-oneofs"},"Custom base traits for sealed oneofs"),Object(i.b)("p",null,"Note: this option is available in ScalaPB 0.9.0 and later."),Object(i.b)("p",null,"Use the following option to define one or more base traits for a generated SealedOneof:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message MyEither {\n option (scalapb.message).sealed_oneof_extends = "MyBaseTrait";\n\n oneof sealed_value {\n Left left = 1;\n Right right = 2;\n }\n}\n')),Object(i.b)("h2",{id:"custom-base-traits-for-enums"},"Custom base traits for enums"),Object(i.b)("p",null,"In a similar fashion to custom base traits for messages, it is possible to\ndefine custom base traits for enum types, for the companion objects of enum\ntypes and even for specific values."),Object(i.b)("p",null,"For example:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto2";\n\npackage enum_example;\n\nimport "scalapb/scalapb.proto";\n\nenum MyEnum {\n option (scalapb.enum_options).extends = "example.EnumOptions.EnumBase";\n option (scalapb.enum_options).companion_extends = "example.EnumOptions.EnumCompanionBase";\n Unknown = 0;\n V1 = 1 [(scalapb.enum_value).extends = "example.EnumOptions.ValueMixin"];\n V2 = 2;\n}\n')),Object(i.b)("p",null,"The generated code will look something like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"sealed trait MyEnum extends GeneratedEnum\n with example.EnumOptions.EnumBase {\n /* ... */\n}\n\nobject MyEnum extends GeneratedEnumCompanion[MyEnum]\n with example.EnumOptions.EnumCompanionBase {\n case object Unknown extends MyEnum { /* ... */ }\n\n case object V1 extends MyEnum\n with example.EnumOptions.ValueMixin { /* ... */ }\n\n case object V2 extends MyEnum { /* ... */ }\n\n /* ... */\n}\n")),Object(i.b)("h2",{id:"custom-types"},"Custom types"),Object(i.b)("p",null,"You can customize the Scala type of any field. One use-case for this is when\nyou would like to use type-safe wrappers around primitive values to enforce unit\ncorrectness. For example, instead of using a raw integer for time fields, you can\nwrap them in a ",Object(i.b)("inlineCode",{parentName:"p"},"Seconds")," class."),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'import "scalapb/scalapb.proto";\n\nmessage Connection {\n optional int32 timeout = 1 [(scalapb.field).type = "mydomain.Seconds"];\n}\n')),Object(i.b)("p",null,"We would like to write code like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"val c = Connection().update(_.timeout := Seconds(5))\n")),Object(i.b)("p",null,"How will ScalaPB know how to convert from the original type (",Object(i.b)("inlineCode",{parentName:"p"},"Integer"),") to the\ncustom type ",Object(i.b)("inlineCode",{parentName:"p"},"Seconds"),"? For each custom type you need to define an implicit\n",Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper")," that will tell ScalaPB how to convert between the custom type and\nthe base Scala type. A good place to define this implicit is in the companion\nclass for your custom type, since the Scala compiler will look for a\ntypemapper there by default. If your typemapper is defined elsewhere, you\nwill need to import it manually by using the ",Object(i.b)("inlineCode",{parentName:"p"},"import")," file-level option."),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"package mydomain\n\ncase class Seconds(v: Int) extends AnyVal\n\nobject Seconds {\n implicit val typeMapper = TypeMapper(Seconds.apply)(_.v)\n}\n")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper")," takes two function parameters. The first converts from the original type to\nthe custom type. The second function converts from the custom type to the\noriginal type."),Object(i.b)("p",null,"In addition to primitive values, you can customize enums and messages as well."),Object(i.b)("p",null,"For more examples, see:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/custom_types.proto"},Object(i.b)("inlineCode",{parentName:"a"},"custom_types.proto"))),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala/com/thesamet/pb/PersonId.scala"},Object(i.b)("inlineCode",{parentName:"a"},"PersonId.scala"))),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/test/scala/CustomTypesSpec.scala"},Object(i.b)("inlineCode",{parentName:"a"},"CustomTypesSpec.scala")))),Object(i.b)("p",null,"If you have a TypeMapper that maps a generated type into a type you don't own\n(such as ",Object(i.b)("inlineCode",{parentName:"p"},"String"),", or a third-party class) then you don't have access to the\ncompanion object to define the typemapper in. Instead, you can place the\ntypemapper in one of the parent package objects of the generated code. For\nexample, if you want to map an enum to a string, and the message containing it\ngoes into the ",Object(i.b)("inlineCode",{parentName:"p"},"a.b.c")," package, you can define the type mapper like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"// src/main/scala/a/b/c/package.scala:\npackage a.b\n\npackage object c {\n implicit val segmentType =\n TypeMapper[SegmentType, String](_.name)(SegmentType.fromName(_).get)\n}\n")),Object(i.b)("h2",{id:"message-level-custom-type-and-boxing"},"Message-level custom type and boxing"),Object(i.b)("p",null,"In the previous section you saw how to customize the type generated for a\nspecific field. ScalaPB also lets you specify a custom type at the message\nlevel. When ",Object(i.b)("inlineCode",{parentName:"p"},"type")," is set at the message level, that type is used for all the\nfields that use that message. This eliminates the need to specify ",Object(i.b)("inlineCode",{parentName:"p"},"type")," on each field\nof this type."),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'// duration.proto\nsyntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\n\nmessage Duration {\n option (scalapb.message).type = "mytypes.MyDurationClass";\n int32 seconds = 1;\n}\n')),Object(i.b)("p",null,"In a Scala file define an implicit mapper:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},"import scalapb.TypeMapper\nimport mytypes.duration.Duration\n\ncase class MyDurationClass(seconds: Int)\n\nobject MyDurationClass {\n implicit val tm = TypeMapper[Duration, MyDurationClass] {\n d: Duration => MyDurationClass(d.seconds) } {\n m: MyDurationClass => Duration(m.seconds)\n }\n}\n")),Object(i.b)("p",null,"Now, each time you reference ",Object(i.b)("inlineCode",{parentName:"p"},"Duration")," in a proto file, the generated field in Scala code\nwill be of type ",Object(i.b)("inlineCode",{parentName:"p"},"MyDuration"),":"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\nimport "duration.proto";\n\nmessage Usage {\n Duration dd = 1; // will become dd: Option[MyDuration]\n repeated Duration ds = 2; // will become ds: Seq[MyDuration]\n\n // You can eliminate the boxing of an optional field in an Option by using\n // no_box\n Duration dd_nobox = 3 [(scalapb.field).no_box = true]; // will become ddNoBox: MyDuration\n}\n')),Object(i.b)("p",null,"If you do not want any instance of your message to be boxed (regardless if it\nhas a custom type), you can set ",Object(i.b)("inlineCode",{parentName:"p"},"no_box")," at the message-level:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'// duration_nobox.proto\nsyntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\n\nmessage Duration {\n option (scalapb.message).type = "mytypes.MyDurationType";\n option (scalapb.message).no_box = true; // do not wrap in Option\n int32 seconds = 1;\n}\n')),Object(i.b)("p",null,"Then when this message is used, it will not be wrapped in an ",Object(i.b)("inlineCode",{parentName:"p"},"Option"),". If\n",Object(i.b)("inlineCode",{parentName:"p"},"no_box")," is specified at the field level, it overrides the value specified at\nthe message level."),Object(i.b)("h2",{id:"custom-types-on-maps"},"Custom types on maps"),Object(i.b)("p",null,"Since version 0.6.0 it is possible to customize the key and value types of\nmaps. Like the custom types described above you will need to have a ",Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper"),"\nfor the custom type."),Object(i.b)("p",null,"Example:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message CustomMaps {\n // Will generate Map[String, com.thesamet.pb.Years]\n map string_to_year = 1 [\n (scalapb.field).value_type = "com.thesamet.pb.Years"];\n\n // Will generate Map[PersonId, Int]\n map person_to_int = 2 [\n (scalapb.field).key_type = "com.thesamet.pb.PersonId"];\n\n // Will generate Map[PersonId, com.thesamet.pb.Years]\n map person_to_year = 3 [\n (scalapb.field).key_type = "com.thesamet.pb.PersonId",\n (scalapb.field).value_type = "com.thesamet.pb.Years"];\n}\n')),Object(i.b)("p",null,"Example: see ",Object(i.b)("inlineCode",{parentName:"p"},"CustomMaps")," in ",Object(i.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/maps.proto"},"maps.proto")),Object(i.b)("p",null,"You can also customize the collection type used for a map. See the next\nsection for details."),Object(i.b)("h2",{id:"custom-collection-types"},"Custom collection types"),Object(i.b)("p",null,"By default, ScalaPB compiles repeated fields into a ",Object(i.b)("inlineCode",{parentName:"p"},"Seq[T]"),". When a message\nis parsed from bytes, the default implementation instantiates a ",Object(i.b)("inlineCode",{parentName:"p"},"Vector[T]"),",\nwhich is a subtype of ",Object(i.b)("inlineCode",{parentName:"p"},"Seq[T]"),". You can instruct ScalaPB to use a different\ncollection type for one field by specifying the ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," option. You\ncan also specify a ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," for the entire proto file by specifying a\n",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," at the file-level."),Object(i.b)("p",null,"If both are defined then the field-level setting wins."),Object(i.b)("p",null,"Similar to ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type"),", we have ",Object(i.b)("inlineCode",{parentName:"p"},"map_type")," for map types. By default,\nScalaPB generates ",Object(i.b)("inlineCode",{parentName:"p"},"scala.collection.immutable.Map")," for maps, and you can\ncustomize it at the field level, or file-level by specifying a ",Object(i.b)("inlineCode",{parentName:"p"},"map_type"),"\noption."),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"map_type")," was introduced in ScalaPB 0.8.5."),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'import "scalapb/scalapb.proto";\n\noption (scalapb.options) = {\n collection_type: "Set"\n};\n\nmessage CollTest {\n // Will generate Set[Int] due to file-level option.\n repeated int32 rep1 = 1;\n\n // Will generate an Array[String]\n repeated string rep2 = 2 [\n (scalapb.field).collection_type="Array"];\n\n // Will generate Seq[collection.immutable.Seq]\n repeated bool rep3 = 3 [\n (scalapb.field).collection_type="collection.immutable.Seq"];\n\n map my_map = 4 [\n (scalapb.field).map_type="collection.mutable.Map"];\n}\n')),Object(i.b)("p",null,"Note on mutable collection: ScalaPB assumes that all data is immutable. For example, the result\nof ",Object(i.b)("inlineCode",{parentName:"p"},"serializedSize")," is cached in a private field. When choosing mutable collections, you must be\ncareful not to mutate any collection after it has been passed to any message, or you might get some\nsurprising results!"),Object(i.b)("p",null,"Note: using ",Object(i.b)("inlineCode",{parentName:"p"},"Array")," is not supported along with Java conversions."),Object(i.b)("p",null,"Note: Most Scala collections can be used with this feature. If you are trying\nto implement your own collection type, it may be useful to check ",Object(i.b)("inlineCode",{parentName:"p"},"MyVector"),"\nand ",Object(i.b)("inlineCode",{parentName:"p"},"MyMap"),", the simplest custom collection that is compatible with ScalaPB:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala-pre-2.13/com/thesamet/pb/MyVector.scala"},"MyVector.scala")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala-pre-2.13/com/thesamet/pb/MyMap.scala"},"MyMap.scala")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/collection_types.proto"},"collection_types.proto"))),Object(i.b)("h2",{id:"custom-names"},"Custom names"),Object(i.b)("p",null,"Sometimes it may be useful to manually specify the name of a field in the\ngenerated code. For example, if you have a field named ",Object(i.b)("inlineCode",{parentName:"p"},"hash_code"),", then the\ncamel-case version of it would be ",Object(i.b)("inlineCode",{parentName:"p"},"hashCode"),". Since that name would conflict with\nthe ",Object(i.b)("a",{parentName:"p",href:"https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()"},Object(i.b)("inlineCode",{parentName:"a"},"hashCode()")," method"),"\nwe inherit from Java, ScalaPB issues an error. You can tell ScalaPB to use an\nalternative name by using the ",Object(i.b)("inlineCode",{parentName:"p"},"scala_name")," option:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'optional string hash_code = 1 [(scalapb.field).scala_name = "myHashCode"];\n')),Object(i.b)("p",null,"It is also possible to customize the Scala name of an enum value:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'enum MyEnum {\n DEFAULT = 0;\n FOO = 1 [(scalapb.enum_value).scala_name = "Bar"];\n}\n')),Object(i.b)("p",null,"The same customization can be applied to ",Object(i.b)("inlineCode",{parentName:"p"},"oneof")," fields:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'oneof notify {\n option (scalapb.oneof).scala_name = "myNotify";\n\n string foo = 1;\n int32 bar = 2;\n}\n')),Object(i.b)("h2",{id:"adding-annotations"},"Adding annotations"),Object(i.b)("p",null,"Since ScalaPB 0.6.3, you can add annotations to the generated case classes like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message BarMessage {\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation";\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation1";\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation2";\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.7.0, you can add annotations to the companion object of a\nmessage and to individual fields:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message BarMessage {\n option (scalapb.message).companion_annotations = "@mypackage.AnotherAnnotation2";\n\n optional string x = 1 [\n (scalapb.field).annotations = \'@deprecated("Will be gone", "1.0")\'\n ];\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.10.9, you can also add annotations to the auto generated unknownFields field:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message BarMessage {\n option (scalapb.message).unknown_field_annotations = "@annotation1";\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.11.4, you can also add annotations to the enum values and the ",Object(i.b)("inlineCode",{parentName:"p"},"Unrecognized")," case class:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'enum BarEnum {\n option (scalapb.enum_options) = "@annotation"\n}\n\nenum BarEnum {\n // every value will have the annotation added.\n option (scalapb.enum_options).base_annotations = "@annotation1";\n // only known values (case objects) will have the annotation added.\n option (scalapb.enum_options).recognized_annotations = "@annotation2";\n // only the unrecognized case class will have the annotation added.\n option (scalapb.enum_options).unrecognized_annotations = "@annotation3";\n // only this value (case object) will have the annotation added.\n BarValue = 1 [(scalapb.enum_value).annotations = "@annotation4"];\n}\n')))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/1d35a65b.c4cddcff.js b/1d35a65b.c4cddcff.js deleted file mode 100644 index 8644f4208..000000000 --- a/1d35a65b.c4cddcff.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return b})),a.d(t,"b",(function(){return d}));var n=a(0),o=a.n(n);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function s(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var c=o.a.createContext({}),r=function(e){var t=o.a.useContext(c),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},b=function(e){var t=r(e.components);return o.a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},u=o.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,i=e.originalType,s=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),b=r(a),u=n,d=b["".concat(s,".").concat(u)]||b[u]||m[u]||i;return a?o.a.createElement(d,l(l({ref:t},c),{},{components:a})):o.a.createElement(d,l({ref:t},c))}));function d(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=a.length,s=new Array(i);s[0]=u;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:n,s[1]=l;for(var c=2;c "path/to/package.proto")\n)\n')),Object(i.b)("p",null,"The path above is relative to the root directory of the published JAR (so ",Object(i.b)("inlineCode",{parentName:"p"},"src/main/protobuf")," is not needed). Users add your library to their projects like this:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'libraryDependencies ++= Seq(\n "com.example" %% "your-library" % "0.1.0",\n "com.example" %% "your-library" % "0.1.0" % "protobuf"\n)\n')),Object(i.b)("p",null,"The first dependency provides the precompiled class files. The second dependency makes it possible\nfor users to import the protos in the jar file. ",Object(i.b)("inlineCode",{parentName:"p"},"sbt-protoc")," will look for the\n",Object(i.b)("inlineCode",{parentName:"p"},"ScalaPB-Options-Proto")," attribute in the jar's manifest and automatically add the package scoped options file\nto the protoc command line."),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(n.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(n.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(n.a)({parentName:"svg"},{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})))),"note")),Object(i.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"Since the package-scoped options file is used as a source file in multiple\nprojects, it should not define any types (messages, enums, services).\nThis ensures that the package-scoped proto file does not generate any code on its own so we don't\nend up with duplicate class files."))),Object(i.b)("h3",{id:"disabling-package-scoped-options-processing"},"Disabling package-scoped options processing"),Object(i.b)("p",null,"As a consumer of third-party dependencies that come with options proto, you\ncan disable the behavior of automatically adding the options proto to protoc\nby setting"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"Compile / PB.manifestProcessing := false\n")),Object(i.b)("p",null,"in sbt. In that case, it is your responsibility to either manually ",Object(i.b)("inlineCode",{parentName:"p"},"import")," the option protos in one\nof your own project source files so it gets applied, or ensure that the\ngenerator settigs used in your project are consistent with the ones used to\ngenerate the dependency. Differences in settings can lead to generated code\nthat does not compile."),Object(i.b)("h2",{id:"auxiliary-options"},"Auxiliary options"),Object(i.b)("p",null,"In some situations, you may want to set some options in a proto file, but without\nmodifying the original proto file or adding anything ScalaPB-specific to it. To accomplish\nthat, you can define auxiliary options under package-scoped options."),Object(i.b)("p",null,"For example, if you are given this proto file:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\npackage a.b.c;\nmessage Foo {\n string hello = 1;\n}\n')),Object(i.b)("p",null,"You can add a file ",Object(i.b)("inlineCode",{parentName:"p"},"package.proto")," with the following content:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\npackage a.b.c;\nimport "scalapb/scalapb.proto";\noption (scalapb.options) = {\n scope: PACKAGE\n aux_message_options: [\n {\n target: "a.b.c.Foo"\n options: {\n extends: "com.myexample.SomeTrait"\n }\n }\n ]\n aux_field_options: [\n {\n target: "a.b.c.Foo.hello"\n options: {\n scala_name: "goodbye"\n }\n }\n ]\n};\n')),Object(i.b)("p",null,"The list ",Object(i.b)("inlineCode",{parentName:"p"},"aux_message_options")," contains options targeted at different messages define under the same proto package of the package-scoped options. The ",Object(i.b)("inlineCode",{parentName:"p"},"target")," name needs to be fully-qualified message name in the protobuf namespace. Similar to ",Object(i.b)("inlineCode",{parentName:"p"},"aux_message_options"),", we also have ",Object(i.b)("inlineCode",{parentName:"p"},"aux_enum_options"),", ",Object(i.b)("inlineCode",{parentName:"p"},"aux_enum_value_options")," and ",Object(i.b)("inlineCode",{parentName:"p"},"aux_field_options"),". See ",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/ScalaPB/tree/master/e2e/src/main/protobuf/scoped"}),"example usage here"),"."),Object(i.b)("h2",{id:"primitive-wrappers"},"Primitive wrappers"),Object(i.b)("p",null,"In proto 3, unlike proto 2, primitives are not wrapped in an option by default.\nThe standard technique to obtain an optional primitive is to wrap it inside a\nmessage (since messages are provided inside an ",Object(i.b)("inlineCode",{parentName:"p"},"Option"),"). Google provides\nstandard wrappers to the primitive types in\n",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/google/protobuf/blob/master/src/google/protobuf/wrappers.proto"}),"wrappers.proto"),"."),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"primitive_wrappers")," is enabled by default for ScalaPB>=0.6.0. Whenever one\nof the standard wrappers is used, it will be mapped to ",Object(i.b)("inlineCode",{parentName:"p"},"Option[X]")," where ",Object(i.b)("inlineCode",{parentName:"p"},"X"),"\nis a primitive type. For example:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\n\nimport "google/protobuf/wrappers.proto";\n\nmessage MyMessage {\n google.protobuf.Int32Value my_int32 = 5;\n}\n')),Object(i.b)("p",null,"would generate"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"case class MyMessage(myInt32: Option[Int]) extends ...\n")),Object(i.b)("p",null,"To disable primitive wrappers in a file:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "scalapb/scalapb.proto";\noption (scalapb.options) = {\n no_primitive_wrappers: true\n};\n')),Object(i.b)("p",null,"In versions of ScalaPB prior to 0.6.0, primitive wrappers had to be turned on\nmanually in each file:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "scalapb/scalapb.proto";\noption (scalapb.options) = {\n primitive_wrappers: true\n};\n')),Object(i.b)("h2",{id:"custom-base-traits-for-messages"},"Custom base traits for messages"),Object(i.b)("p",null,"Note: this option is available in ScalaPB 0.6.1 and later."),Object(i.b)("p",null,"ScalaPBs allows you to specify custom base traits to a generated case\nclass. This is useful when you have a few messages that share common fields\nand you would like to be able to access those fields through a single trait."),Object(i.b)("p",null,"Example:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "scalapb/scalapb.proto";\n\nmessage CustomerWithPhone {\n option (scalapb.message).extends = "com.thesamet.pb.BaseCustomer";\n\n optional string customer_id = 1;\n optional string name = 2;\n optional string phone = 3;\n}\n')),Object(i.b)("p",null,"In your code, define the base trait ",Object(i.b)("inlineCode",{parentName:"p"},"DomainEvent")," and include any subset of the fields:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"package com.thesamet.pb\n\ntrait BaseCustomer {\n def customerId: Option[String]\n def name: Option[String]\n}\n")),Object(i.b)("p",null,"You can specify any number of base traits for a message."),Object(i.b)("p",null,"It is also possible to make the generated companion classes extend a class\nor trait, by using the ",Object(i.b)("inlineCode",{parentName:"p"},"companion_extends")," option. For example:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message MyMessage {\n option (scalapb.message).extends = "MySuperClass";\n option (scalapb.message).companion_extends = "MySuperCompanionClass";\n int32 n = 1;\n}\n')),Object(i.b)("p",null,"Will generate a case class that extends ",Object(i.b)("inlineCode",{parentName:"p"},"MySuperClass"),", and the companion\nobject will extend ",Object(i.b)("inlineCode",{parentName:"p"},"MySuperCompanionClass"),"."),Object(i.b)("h2",{id:"custom-base-traits-for-sealed-oneofs"},"Custom base traits for sealed oneofs"),Object(i.b)("p",null,"Note: this option is available in ScalaPB 0.9.0 and later."),Object(i.b)("p",null,"Use the following option to define one or more base traits for a generated SealedOneof:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message MyEither {\n option (scalapb.message).sealed_oneof_extends = "MyBaseTrait";\n\n oneof sealed_value {\n Left left = 1;\n Right right = 2;\n }\n}\n')),Object(i.b)("h2",{id:"custom-base-traits-for-enums"},"Custom base traits for enums"),Object(i.b)("p",null,"In a similar fashion to custom base traits for messages, it is possible to\ndefine custom base traits for enum types, for the companion objects of enum\ntypes and even for specific values."),Object(i.b)("p",null,"For example:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto2";\n\npackage enum_example;\n\nimport "scalapb/scalapb.proto";\n\nenum MyEnum {\n option (scalapb.enum_options).extends = "example.EnumOptions.EnumBase";\n option (scalapb.enum_options).companion_extends = "example.EnumOptions.EnumCompanionBase";\n Unknown = 0;\n V1 = 1 [(scalapb.enum_value).extends = "example.EnumOptions.ValueMixin"];\n V2 = 2;\n}\n')),Object(i.b)("p",null,"The generated code will look something like this:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"sealed trait MyEnum extends GeneratedEnum\n with example.EnumOptions.EnumBase {\n /* ... */\n}\n\nobject MyEnum extends GeneratedEnumCompanion[MyEnum]\n with example.EnumOptions.EnumCompanionBase {\n case object Unknown extends MyEnum { /* ... */ }\n\n case object V1 extends MyEnum\n with example.EnumOptions.ValueMixin { /* ... */ }\n\n case object V2 extends MyEnum { /* ... */ }\n\n /* ... */\n}\n")),Object(i.b)("h2",{id:"custom-types"},"Custom types"),Object(i.b)("p",null,"You can customize the Scala type of any field. One use-case for this is when\nyou would like to use type-safe wrappers around primitive values to enforce unit\ncorrectness. For example, instead of using a raw integer for time fields, you can\nwrap them in a ",Object(i.b)("inlineCode",{parentName:"p"},"Seconds")," class."),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "scalapb/scalapb.proto";\n\nmessage Connection {\n optional int32 timeout = 1 [(scalapb.field).type = "mydomain.Seconds"];\n}\n')),Object(i.b)("p",null,"We would like to write code like this:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"val c = Connection().update(_.timeout := Seconds(5))\n")),Object(i.b)("p",null,"How will ScalaPB know how to convert from the original type (",Object(i.b)("inlineCode",{parentName:"p"},"Integer"),") to the\ncustom type ",Object(i.b)("inlineCode",{parentName:"p"},"Seconds"),"? For each custom type you need to define an implicit\n",Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper")," that will tell ScalaPB how to convert between the custom type and\nthe base Scala type. A good place to define this implicit is in the companion\nclass for your custom type, since the Scala compiler will look for a\ntypemapper there by default. If your typemapper is defined elsewhere, you\nwill need to import it manually by using the ",Object(i.b)("inlineCode",{parentName:"p"},"import")," file-level option."),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"package mydomain\n\ncase class Seconds(v: Int) extends AnyVal\n\nobject Seconds {\n implicit val typeMapper = TypeMapper(Seconds.apply)(_.v)\n}\n")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper")," takes two function parameters. The first converts from the original type to\nthe custom type. The second function converts from the custom type to the\noriginal type."),Object(i.b)("p",null,"In addition to primitive values, you can customize enums and messages as well."),Object(i.b)("p",null,"For more examples, see:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/custom_types.proto"}),Object(i.b)("inlineCode",{parentName:"a"},"custom_types.proto"))),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala/com/thesamet/pb/PersonId.scala"}),Object(i.b)("inlineCode",{parentName:"a"},"PersonId.scala"))),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/test/scala/CustomTypesSpec.scala"}),Object(i.b)("inlineCode",{parentName:"a"},"CustomTypesSpec.scala")))),Object(i.b)("p",null,"If you have a TypeMapper that maps a generated type into a type you don't own\n(such as ",Object(i.b)("inlineCode",{parentName:"p"},"String"),", or a third-party class) then you don't have access to the\ncompanion object to define the typemapper in. Instead, you can place the\ntypemapper in one of the parent package objects of the generated code. For\nexample, if you want to map an enum to a string, and the message containing it\ngoes into the ",Object(i.b)("inlineCode",{parentName:"p"},"a.b.c")," package, you can define the type mapper like this:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"// src/main/scala/a/b/c/package.scala:\npackage a.b\n\npackage object c {\n implicit val segmentType =\n TypeMapper[SegmentType, String](_.name)(SegmentType.fromName(_).get)\n}\n")),Object(i.b)("h2",{id:"message-level-custom-type-and-boxing"},"Message-level custom type and boxing"),Object(i.b)("p",null,"In the previous section you saw how to customize the type generated for a\nspecific field. ScalaPB also lets you specify a custom type at the message\nlevel. When ",Object(i.b)("inlineCode",{parentName:"p"},"type")," is set at the message level, that type is used for all the\nfields that use that message. This eliminates the need to specify ",Object(i.b)("inlineCode",{parentName:"p"},"type")," on each field\nof this type."),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'// duration.proto\nsyntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\n\nmessage Duration {\n option (scalapb.message).type = "mytypes.MyDurationClass";\n int32 seconds = 1;\n}\n')),Object(i.b)("p",null,"In a Scala file define an implicit mapper:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"import scalapb.TypeMapper\nimport mytypes.duration.Duration\n\ncase class MyDurationClass(seconds: Int)\n\nobject MyDurationClass {\n implicit val tm = TypeMapper[Duration, MyDurationClass] {\n d: Duration => MyDurationClass(d.seconds) } {\n m: MyDurationClass => Duration(m.seconds)\n }\n}\n")),Object(i.b)("p",null,"Now, each time you reference ",Object(i.b)("inlineCode",{parentName:"p"},"Duration")," in a proto file, the generated field in Scala code\nwill be of type ",Object(i.b)("inlineCode",{parentName:"p"},"MyDuration"),":"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\nimport "duration.proto";\n\nmessage Usage {\n Duration dd = 1; // will become dd: Option[MyDuration]\n repeated Duration ds = 2; // will become ds: Seq[MyDuration]\n\n // You can eliminate the boxing of an optional field in an Option by using\n // no_box\n Duration dd_nobox = 3 [(scalapb.field).no_box = true]; // will become ddNoBox: MyDuration\n}\n')),Object(i.b)("p",null,"If you do not want any instance of your message to be boxed (regardless if it\nhas a custom type), you can set ",Object(i.b)("inlineCode",{parentName:"p"},"no_box")," at the message-level:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'// duration_nobox.proto\nsyntax = "proto3";\n\npackage mytypes;\n\nimport "scalapb/scalapb.proto";\n\nmessage Duration {\n option (scalapb.message).type = "mytypes.MyDurationType";\n option (scalapb.message).no_box = true; // do not wrap in Option\n int32 seconds = 1;\n}\n')),Object(i.b)("p",null,"Then when this message is used, it will not be wrapped in an ",Object(i.b)("inlineCode",{parentName:"p"},"Option"),". If\n",Object(i.b)("inlineCode",{parentName:"p"},"no_box")," is specified at the field level, it overrides the value specified at\nthe message level."),Object(i.b)("h2",{id:"custom-types-on-maps"},"Custom types on maps"),Object(i.b)("p",null,"Since version 0.6.0 it is possible to customize the key and value types of\nmaps. Like the custom types described above you will need to have a ",Object(i.b)("inlineCode",{parentName:"p"},"TypeMapper"),"\nfor the custom type."),Object(i.b)("p",null,"Example:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message CustomMaps {\n // Will generate Map[String, com.thesamet.pb.Years]\n map string_to_year = 1 [\n (scalapb.field).value_type = "com.thesamet.pb.Years"];\n\n // Will generate Map[PersonId, Int]\n map person_to_int = 2 [\n (scalapb.field).key_type = "com.thesamet.pb.PersonId"];\n\n // Will generate Map[PersonId, com.thesamet.pb.Years]\n map person_to_year = 3 [\n (scalapb.field).key_type = "com.thesamet.pb.PersonId",\n (scalapb.field).value_type = "com.thesamet.pb.Years"];\n}\n')),Object(i.b)("p",null,"Example: see ",Object(i.b)("inlineCode",{parentName:"p"},"CustomMaps")," in ",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/maps.proto"}),"maps.proto")),Object(i.b)("p",null,"You can also customize the collection type used for a map. See the next\nsection for details."),Object(i.b)("h2",{id:"custom-collection-types"},"Custom collection types"),Object(i.b)("p",null,"By default, ScalaPB compiles repeated fields into a ",Object(i.b)("inlineCode",{parentName:"p"},"Seq[T]"),". When a message\nis parsed from bytes, the default implementation instantiates a ",Object(i.b)("inlineCode",{parentName:"p"},"Vector[T]"),",\nwhich is a subtype of ",Object(i.b)("inlineCode",{parentName:"p"},"Seq[T]"),". You can instruct ScalaPB to use a different\ncollection type for one field by specifying the ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," option. You\ncan also specify a ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," for the entire proto file by specifying a\n",Object(i.b)("inlineCode",{parentName:"p"},"collection_type")," at the file-level."),Object(i.b)("p",null,"If both are defined then the field-level setting wins."),Object(i.b)("p",null,"Similar to ",Object(i.b)("inlineCode",{parentName:"p"},"collection_type"),", we have ",Object(i.b)("inlineCode",{parentName:"p"},"map_type")," for map types. By default,\nScalaPB generates ",Object(i.b)("inlineCode",{parentName:"p"},"scala.collection.immutable.Map")," for maps, and you can\ncustomize it at the field level, or file-level by specifying a ",Object(i.b)("inlineCode",{parentName:"p"},"map_type"),"\noption."),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"map_type")," was introduced in ScalaPB 0.8.5."),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "scalapb/scalapb.proto";\n\noption (scalapb.options) = {\n collection_type: "Set"\n};\n\nmessage CollTest {\n // Will generate Set[Int] due to file-level option.\n repeated int32 rep1 = 1;\n\n // Will generate an Array[String]\n repeated string rep2 = 2 [\n (scalapb.field).collection_type="Array"];\n\n // Will generate Seq[collection.immutable.Seq]\n repeated bool rep3 = 3 [\n (scalapb.field).collection_type="collection.immutable.Seq"];\n\n map my_map = 4 [\n (scalapb.field).map_type="collection.mutable.Map"];\n}\n')),Object(i.b)("p",null,"Note on mutable collection: ScalaPB assumes that all data is immutable. For example, the result\nof ",Object(i.b)("inlineCode",{parentName:"p"},"serializedSize")," is cached in a private field. When choosing mutable collections, you must be\ncareful not to mutate any collection after it has been passed to any message, or you might get some\nsurprising results!"),Object(i.b)("p",null,"Note: using ",Object(i.b)("inlineCode",{parentName:"p"},"Array")," is not supported along with Java conversions."),Object(i.b)("p",null,"Note: Most Scala collections can be used with this feature. If you are trying\nto implement your own collection type, it may be useful to check ",Object(i.b)("inlineCode",{parentName:"p"},"MyVector"),"\nand ",Object(i.b)("inlineCode",{parentName:"p"},"MyMap"),", the simplest custom collection that is compatible with ScalaPB:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala-pre-2.13/com/thesamet/pb/MyVector.scala"}),"MyVector.scala")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/scala-pre-2.13/com/thesamet/pb/MyMap.scala"}),"MyMap.scala")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",Object(n.a)({parentName:"li"},{href:"https://github.com/scalapb/ScalaPB/blob/master/e2e/src/main/protobuf/collection_types.proto"}),"collection_types.proto"))),Object(i.b)("h2",{id:"custom-names"},"Custom names"),Object(i.b)("p",null,"Sometimes it may be useful to manually specify the name of a field in the\ngenerated code. For example, if you have a field named ",Object(i.b)("inlineCode",{parentName:"p"},"hash_code"),", then the\ncamel-case version of it would be ",Object(i.b)("inlineCode",{parentName:"p"},"hashCode"),". Since that name would conflict with\nthe ",Object(i.b)("a",Object(n.a)({parentName:"p"},{href:"https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()"}),Object(i.b)("inlineCode",{parentName:"a"},"hashCode()")," method"),"\nwe inherit from Java, ScalaPB issues an error. You can tell ScalaPB to use an\nalternative name by using the ",Object(i.b)("inlineCode",{parentName:"p"},"scala_name")," option:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'optional string hash_code = 1 [(scalapb.field).scala_name = "myHashCode"];\n')),Object(i.b)("p",null,"It is also possible to customize the Scala name of an enum value:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'enum MyEnum {\n DEFAULT = 0;\n FOO = 1 [(scalapb.enum_value).scala_name = "Bar"];\n}\n')),Object(i.b)("p",null,"The same customization can be applied to ",Object(i.b)("inlineCode",{parentName:"p"},"oneof")," fields:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'oneof notify {\n option (scalapb.oneof).scala_name = "myNotify";\n\n string foo = 1;\n int32 bar = 2;\n}\n')),Object(i.b)("h2",{id:"adding-annotations"},"Adding annotations"),Object(i.b)("p",null,"Since ScalaPB 0.6.3, you can add annotations to the generated case classes like this:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message BarMessage {\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation";\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation1";\n option (scalapb.message).annotations = "@mypackage.CustomAnnotation2";\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.7.0, you can add annotations to the companion object of a\nmessage and to individual fields:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message BarMessage {\n option (scalapb.message).companion_annotations = "@mypackage.AnotherAnnotation2";\n\n optional string x = 1 [\n (scalapb.field).annotations = \'@deprecated("Will be gone", "1.0")\'\n ];\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.10.9, you can also add annotations to the auto generated unknownFields field:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'message BarMessage {\n option (scalapb.message).unknown_field_annotations = "@annotation1";\n}\n')),Object(i.b)("p",null,"In ScalaPB 0.11.4, you can also add annotations to the enum values and the ",Object(i.b)("inlineCode",{parentName:"p"},"Unrecognized")," case class:"),Object(i.b)("pre",null,Object(i.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'enum BarEnum {\n option (scalapb.enum_options) = "@annotation"\n}\n\nenum BarEnum {\n // every value will have the annotation added.\n option (scalapb.enum_options).base_annotations = "@annotation1";\n // only known values (case objects) will have the annotation added.\n option (scalapb.enum_options).recognized_annotations = "@annotation2";\n // only the unrecognized case class will have the annotation added.\n option (scalapb.enum_options).unrecognized_annotations = "@annotation3";\n // only this value (case object) will have the annotation added.\n BarValue = 1 [(scalapb.enum_value).annotations = "@annotation4"];\n}\n')))}r.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/2.5b37da85.js b/2.5b37da85.js deleted file mode 100644 index 93c74294e..000000000 --- a/2.5b37da85.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see 2.5b37da85.js.LICENSE.txt */ -(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{125:function(e,t,a){"use strict";var n=a(0),r=a.n(n),c=a(120),o=a(62),l=a.n(o);var i=function(){return r.a.createElement("nav",{"aria-label":"Skip navigation links"},r.a.createElement("button",{type:"button",tabIndex:0,className:l.a.skipToContent,onKeyDown:function(e){if(13===e.keyCode){document.activeElement.blur();var t=document.querySelector("main:first-of-type");t&&t.scrollIntoView()}}},"Skip to main content"))},s=a(121),u=a(141),d=a(63),m=a.n(d);var f=function(){var e,t=Object(u.a)(),a=t.isAnnouncementBarClosed,n=t.closeAnnouncementBar,o=Object(s.useThemeConfig)().announcementBar;if(!o)return null;var l=o.content,i=o.backgroundColor,d=o.textColor,f=o.isCloseable;return!l||f&&a?null:r.a.createElement("div",{className:m.a.announcementBar,style:{backgroundColor:i,color:d},role:"banner"},r.a.createElement("div",{className:Object(c.a)(m.a.announcementBarContent,(e={},e[m.a.announcementBarCloseable]=f,e)),dangerouslySetInnerHTML:{__html:l}}),f?r.a.createElement("button",{type:"button",className:m.a.announcementBarClose,onClick:n,"aria-label":"Close"},r.a.createElement("span",{"aria-hidden":"true"},"\xd7")):null)},h=a(3),v=function(){return null},b=a(158),p=a.n(b),g=a(21),k=a(64),E=a.n(k),O=function(e){var t=e.icon,a=e.style;return r.a.createElement("span",{className:Object(c.a)(E.a.toggle,E.a.dark),style:a},t)},j=function(e){var t=e.icon,a=e.style;return r.a.createElement("span",{className:Object(c.a)(E.a.toggle,E.a.light),style:a},t)},y=function(e){var t=Object(s.useThemeConfig)().colorMode.switchConfig,a=t.darkIcon,n=t.darkIconStyle,c=t.lightIcon,o=t.lightIconStyle,l=Object(g.default)().isClient;return r.a.createElement(p.a,Object(h.a)({disabled:!l,icons:{checked:r.a.createElement(O,{icon:a,style:n}),unchecked:r.a.createElement(j,{icon:c,style:o})}},e))},_=a(129),C=a(126),w=a(144),N=function(e){var t=Object(C.useLocation)(),a=Object(n.useState)(!e),r=a[0],c=a[1],o=Object(n.useRef)(!1),l=Object(n.useState)(0),i=l[0],s=l[1],u=Object(n.useState)(0),d=u[0],m=u[1],f=Object(n.useCallback)((function(e){null!==e&&m(e.getBoundingClientRect().height)}),[]);return Object(w.a)((function(t){var a=t.scrollY;if(e&&!(a=i?c(!1):a+r0&&r.a.createElement("div",{className:"row footer__links"},o.map((function(e,t){return r.a.createElement("div",{key:t,className:"col footer__col"},null!=e.title?r.a.createElement("h4",{className:"footer__title"},e.title):null,null!=e.items&&Array.isArray(e.items)&&e.items.length>0?r.a.createElement("ul",{className:"footer__items"},e.items.map((function(e,t){return e.html?r.a.createElement("li",{key:t,className:"footer__item",dangerouslySetInnerHTML:{__html:e.html}}):r.a.createElement("li",{key:e.href||e.to,className:"footer__item"},r.a.createElement(Y,e))}))):null)}))),(i||a)&&r.a.createElement("div",{className:"footer__bottom text--center"},i&&i.src&&r.a.createElement("div",{className:"margin-bottom--sm"},i.href?r.a.createElement("a",{href:i.href,target:"_blank",rel:"noopener noreferrer",className:G.a.footerLogoLink},r.a.createElement(K,{alt:i.alt,url:u})):r.a.createElement(K,{alt:i.alt,url:u})),a?r.a.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:a}}):null))):null},z=a(8),J="light",q="dark",Q=function(e){return e===q?q:J},Z=function(){return z.a.canUseDOM?Q(document.documentElement.getAttribute("data-theme")):J},$=function(e){try{localStorage.setItem("theme",Q(e))}catch(t){console.error(t)}},ee=function(){var e=Object(s.useThemeConfig)().colorMode,t=e.disableSwitch,a=e.respectPrefersColorScheme,r=Object(n.useState)(Z),c=r[0],o=r[1],l=Object(n.useCallback)((function(){o(J),$(J)}),[]),i=Object(n.useCallback)((function(){o(q),$(q)}),[]);return Object(n.useEffect)((function(){document.documentElement.setAttribute("data-theme",Q(c))}),[c]),Object(n.useEffect)((function(){if(!t)try{var e=localStorage.getItem("theme");null!==e&&o(Q(e))}catch(a){console.error(a)}}),[o]),Object(n.useEffect)((function(){t&&!a||window.matchMedia("(prefers-color-scheme: dark)").addListener((function(e){var t=e.matches;o(t?q:J)}))}),[]),{isDarkTheme:c===q,setLightTheme:l,setDarkTheme:i}},te=a(143);var ae=function(e){var t=ee(),a=t.isDarkTheme,n=t.setLightTheme,c=t.setDarkTheme;return r.a.createElement(te.a.Provider,{value:{isDarkTheme:a,setLightTheme:n,setDarkTheme:c}},e.children)},ne="docusaurus.tab.",re=function(){var e=Object(n.useState)({}),t=e[0],a=e[1],r=Object(n.useCallback)((function(e,t){try{localStorage.setItem("docusaurus.tab."+e,t)}catch(a){console.error(a)}}),[]);return Object(n.useEffect)((function(){try{for(var e={},t=0;t996?r.desktop:r.mobile}var a=Object(n.useState)(t),c=a[0],o=a[1];return Object(n.useEffect)((function(){if(e)return window.addEventListener("resize",a),function(){return window.removeEventListener("resize",a)};function a(){o(t())}}),[]),c}},147:function(e,t,a){"use strict";var n=a(3),r=a(7),c=a(0),o=a.n(c);t.a=function(e){var t=e.width,a=void 0===t?30:t,c=e.height,l=void 0===c?30:c,i=e.className,s=Object(r.a)(e,["width","height","className"]);return o.a.createElement("svg",Object(n.a)({"aria-label":"Menu",className:i,width:a,height:l,viewBox:"0 0 30 30",role:"img",focusable:"false"},s),o.a.createElement("title",null,"Menu"),o.a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}},148:function(e,t,a){"use strict";var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(122),i=a(120),s=a(21),u=a(129),d=a(65),m=a.n(d),f=function(e){var t=Object(s.default)().isClient,a=Object(u.a)().isDarkTheme,c=e.sources,l=e.className,d=e.alt,f=void 0===d?"":d,h=Object(r.a)(e,["sources","className","alt"]),v=t?a?["dark"]:["light"]:["light","dark"];return o.a.createElement(o.a.Fragment,null,v.map((function(e){return o.a.createElement("img",Object(n.a)({key:e,src:c[e],alt:f,className:Object(i.a)(m.a.themedImage,m.a["themedImage--"+e],l)},h))})))},h=a(124),v=a(121),b=a(130);t.a=function(e){var t=Object(s.default)().isClient,a=Object(v.useThemeConfig)().navbar,c=a.title,i=a.logo,u=void 0===i?{src:""}:i,d=e.imageClassName,m=e.titleClassName,p=Object(r.a)(e,["imageClassName","titleClassName"]),g=Object(h.a)(u.href||"/"),k=u.target?{target:u.target}:Object(b.a)(g)?{}:{rel:"noopener noreferrer",target:"_blank"},E={light:Object(h.a)(u.src),dark:Object(h.a)(u.srcDark||u.src)};return o.a.createElement(l.a,Object(n.a)({to:g},p,k),u.src&&o.a.createElement(f,{key:t,className:d,sources:E,alt:u.alt||c||"Logo"}),null!=c&&o.a.createElement("strong",{className:m},c))}},158:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;tthis.startX&&(this.setState({checked:!0}),this.startX=t,this.activated=ta?this.previouslyChecked!==this.state.checked&&(this.setState({checked:!1}),this.previouslyChecked=this.state.checked,t.click()):this.startX-4=0||Object.prototype.hasOwnProperty.call(e,n)&&(a[n]=e[n]);return a}(t,["className","icons"])),c=(0,l.default)("react-toggle",{"react-toggle--checked":this.state.checked,"react-toggle--focus":this.state.hasFocus,"react-toggle--disabled":this.props.disabled},a);return o.default.createElement("div",{className:c,onClick:this.handleClick,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEnd},o.default.createElement("div",{className:"react-toggle-track"},o.default.createElement("div",{className:"react-toggle-track-check"},this.getIcon("checked")),o.default.createElement("div",{className:"react-toggle-track-x"},this.getIcon("unchecked"))),o.default.createElement("div",{className:"react-toggle-thumb"}),o.default.createElement("input",n({},r,{ref:function(t){e.input=t},onFocus:this.handleFocus,onBlur:this.handleBlur,className:"react-toggle-screenreader-only",type:"checkbox"})))}}]),t}(c.PureComponent);t.default=f,f.displayName="Toggle",f.defaultProps={icons:{checked:o.default.createElement(s.default,null),unchecked:o.default.createElement(u.default,null)}},f.propTypes={checked:i.default.bool,disabled:i.default.bool,defaultChecked:i.default.bool,onChange:i.default.func,onFocus:i.default.func,onBlur:i.default.func,className:i.default.string,name:i.default.string,value:i.default.string,id:i.default.string,"aria-labelledby":i.default.string,"aria-label":i.default.string,icons:i.default.oneOfType([i.default.bool,i.default.shape({checked:i.default.node,unchecked:i.default.node})])}},159:function(e,t,a){var n;!function(){"use strict";var a={}.hasOwnProperty;function r(){for(var e=[],t=0;t0){var a=t[0];return{x:a.clientX,y:a.clientY}}var n=e.pageX;if(void 0!==n)return{x:n,y:e.pageY}}return{x:0,y:0}}},163:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return u}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(121);function u(e){var t,a=e.label,c=e.to,u=e.docsPluginId,d=Object(r.a)(e,["label","to","docsPluginId"]),m=Object(i.useActiveVersion)(u),f=Object(s.useDocsPreferredVersion)(u).preferredVersion,h=Object(i.useLatestVersion)(u),v=null!==(t=null!=m?m:f)&&void 0!==t?t:h,b=null!=a?a:v.label,p=null!=c?c:function(e){return e.docs.find((function(t){return t.id===e.mainDocId}))}(v).path;return o.a.createElement(l.a,Object(n.a)({},d,{label:b,to:p}))}},164:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return d}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(121),u=function(e){return e.docs.find((function(t){return t.id===e.mainDocId}))};function d(e){var t,a,c=e.mobile,d=e.docsPluginId,m=e.dropdownActiveClassDisabled,f=e.dropdownItemsBefore,h=e.dropdownItemsAfter,v=Object(r.a)(e,["mobile","docsPluginId","dropdownActiveClassDisabled","dropdownItemsBefore","dropdownItemsAfter"]),b=Object(i.useActiveDocContext)(d),p=Object(i.useVersions)(d),g=Object(i.useLatestVersion)(d),k=Object(s.useDocsPreferredVersion)(d),E=k.preferredVersion,O=k.savePreferredVersionName;var j=null!==(t=null!==(a=b.activeVersion)&&void 0!==a?a:E)&&void 0!==t?t:g,y=c?"Versions":j.label,_=c?void 0:u(j).path;return o.a.createElement(l.a,Object(n.a)({},v,{mobile:c,label:y,to:_,items:function(){var e=p.map((function(e){var t=(null==b?void 0:b.alternateDocVersions[e.name])||u(e);return{isNavLink:!0,label:e.label,to:t.path,isActive:function(){return e===(null==b?void 0:b.activeVersion)},onClick:function(){O(e.name)}}})),t=[].concat(f,e,h);if(!(t.length<=1))return t}(),isActive:m?function(){return!1}:void 0}))}},165:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return d}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(120),u=a(121);function d(e){var t,a,c=e.docId,d=e.activeSidebarClassName,m=e.label,f=e.docsPluginId,h=Object(r.a)(e,["docId","activeSidebarClassName","label","docsPluginId"]),v=Object(i.useActiveDocContext)(f),b=v.activeVersion,p=v.activeDoc,g=Object(u.useDocsPreferredVersion)(f).preferredVersion,k=Object(i.useLatestVersion)(f),E=null!==(t=null!=b?b:g)&&void 0!==t?t:k,O=E.docs.find((function(e){return e.id===c}));if(!O)throw new Error("DocNavbarItem: couldn't find any doc with id="+c+" in version "+E.name+".\nAvailable docIds=\n- "+E.docs.join("\n- "));return o.a.createElement(l.a,Object(n.a)({exact:!0},h,{className:Object(s.a)(h.className,(a={},a[d]=p&&p.sidebar===O.sidebar,a)),label:null!=m?m:O.id,to:O.path}))}}}]); \ No newline at end of file diff --git a/2.f4df6e70.js b/2.f4df6e70.js new file mode 100644 index 000000000..f7953a437 --- /dev/null +++ b/2.f4df6e70.js @@ -0,0 +1,2 @@ +/*! For license information please see 2.f4df6e70.js.LICENSE.txt */ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{125:function(e,t,a){"use strict";var n=a(0),r=a.n(n),c=a(120),o=a(62),l=a.n(o);var i=function(){return r.a.createElement("nav",{"aria-label":"Skip navigation links"},r.a.createElement("button",{type:"button",tabIndex:0,className:l.a.skipToContent,onKeyDown:function(e){if(13===e.keyCode){document.activeElement.blur();var t=document.querySelector("main:first-of-type");t&&t.scrollIntoView()}}},"Skip to main content"))},s=a(121),u=a(141),d=a(63),m=a.n(d);var f=function(){var e,t=Object(u.a)(),a=t.isAnnouncementBarClosed,n=t.closeAnnouncementBar,o=Object(s.useThemeConfig)().announcementBar;if(!o)return null;var l=o.content,i=o.backgroundColor,d=o.textColor,f=o.isCloseable;return!l||f&&a?null:r.a.createElement("div",{className:m.a.announcementBar,style:{backgroundColor:i,color:d},role:"banner"},r.a.createElement("div",{className:Object(c.a)(m.a.announcementBarContent,(e={},e[m.a.announcementBarCloseable]=f,e)),dangerouslySetInnerHTML:{__html:l}}),f?r.a.createElement("button",{type:"button",className:m.a.announcementBarClose,onClick:n,"aria-label":"Close"},r.a.createElement("span",{"aria-hidden":"true"},"\xd7")):null)},h=a(3),v=function(){return null},b=a(158),p=a.n(b),g=a(20),k=a(64),E=a.n(k),O=function(e){var t=e.icon,a=e.style;return r.a.createElement("span",{className:Object(c.a)(E.a.toggle,E.a.dark),style:a},t)},j=function(e){var t=e.icon,a=e.style;return r.a.createElement("span",{className:Object(c.a)(E.a.toggle,E.a.light),style:a},t)},y=function(e){var t=Object(s.useThemeConfig)().colorMode.switchConfig,a=t.darkIcon,n=t.darkIconStyle,c=t.lightIcon,o=t.lightIconStyle,l=Object(g.default)().isClient;return r.a.createElement(p.a,Object(h.a)({disabled:!l,icons:{checked:r.a.createElement(O,{icon:a,style:n}),unchecked:r.a.createElement(j,{icon:c,style:o})}},e))},_=a(129),C=a(126),w=a(144),N=function(e){var t=Object(C.useLocation)(),a=Object(n.useState)(!e),r=a[0],c=a[1],o=Object(n.useRef)(!1),l=Object(n.useState)(0),i=l[0],s=l[1],u=Object(n.useState)(0),d=u[0],m=u[1],f=Object(n.useCallback)((function(e){null!==e&&m(e.getBoundingClientRect().height)}),[]);return Object(w.a)((function(t){var a=t.scrollY;if(e&&!(a=i?c(!1):a+r0&&r.a.createElement("div",{className:"row footer__links"},o.map((function(e,t){return r.a.createElement("div",{key:t,className:"col footer__col"},null!=e.title?r.a.createElement("h4",{className:"footer__title"},e.title):null,null!=e.items&&Array.isArray(e.items)&&e.items.length>0?r.a.createElement("ul",{className:"footer__items"},e.items.map((function(e,t){return e.html?r.a.createElement("li",{key:t,className:"footer__item",dangerouslySetInnerHTML:{__html:e.html}}):r.a.createElement("li",{key:e.href||e.to,className:"footer__item"},r.a.createElement(z,e))}))):null)}))),(i||a)&&r.a.createElement("div",{className:"footer__bottom text--center"},i&&i.src&&r.a.createElement("div",{className:"margin-bottom--sm"},i.href?r.a.createElement("a",{href:i.href,target:"_blank",rel:"noopener noreferrer",className:K.a.footerLogoLink},r.a.createElement(J,{alt:i.alt,url:u})):r.a.createElement(J,{alt:i.alt,url:u})),a?r.a.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:a}}):null))):null},Q=a(8),Z="light",$="dark",ee=function(e){return e===$?$:Z},te=function(){return Q.a.canUseDOM?ee(document.documentElement.getAttribute("data-theme")):Z},ae=function(e){try{localStorage.setItem("theme",ee(e))}catch(t){console.error(t)}},ne=function(){var e=Object(s.useThemeConfig)().colorMode,t=e.disableSwitch,a=e.respectPrefersColorScheme,r=Object(n.useState)(te),c=r[0],o=r[1],l=Object(n.useCallback)((function(){o(Z),ae(Z)}),[]),i=Object(n.useCallback)((function(){o($),ae($)}),[]);return Object(n.useEffect)((function(){document.documentElement.setAttribute("data-theme",ee(c))}),[c]),Object(n.useEffect)((function(){if(!t)try{var e=localStorage.getItem("theme");null!==e&&o(ee(e))}catch(a){console.error(a)}}),[o]),Object(n.useEffect)((function(){t&&!a||window.matchMedia("(prefers-color-scheme: dark)").addListener((function(e){var t=e.matches;o(t?$:Z)}))}),[]),{isDarkTheme:c===$,setLightTheme:l,setDarkTheme:i}},re=a(143);var ce=function(e){var t=ne(),a=t.isDarkTheme,n=t.setLightTheme,c=t.setDarkTheme;return r.a.createElement(re.a.Provider,{value:{isDarkTheme:a,setLightTheme:n,setDarkTheme:c}},e.children)},oe="docusaurus.tab.",le=function(){var e=Object(n.useState)({}),t=e[0],a=e[1],r=Object(n.useCallback)((function(e,t){try{localStorage.setItem("docusaurus.tab."+e,t)}catch(a){console.error(a)}}),[]);return Object(n.useEffect)((function(){try{for(var e={},t=0;t996?r.desktop:r.mobile}var a=Object(n.useState)(t),c=a[0],o=a[1];return Object(n.useEffect)((function(){if(e)return window.addEventListener("resize",a),function(){return window.removeEventListener("resize",a)};function a(){o(t())}}),[]),c}},147:function(e,t,a){"use strict";var n=a(3),r=a(7),c=a(0),o=a.n(c),l=["width","height","className"];t.a=function(e){var t=e.width,a=void 0===t?30:t,c=e.height,i=void 0===c?30:c,s=e.className,u=Object(r.a)(e,l);return o.a.createElement("svg",Object(n.a)({"aria-label":"Menu",className:s,width:a,height:i,viewBox:"0 0 30 30",role:"img",focusable:"false"},u),o.a.createElement("title",null,"Menu"),o.a.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}},148:function(e,t,a){"use strict";var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(122),i=a(120),s=a(20),u=a(129),d=a(65),m=a.n(d),f=["sources","className","alt"],h=function(e){var t=Object(s.default)().isClient,a=Object(u.a)().isDarkTheme,c=e.sources,l=e.className,d=e.alt,h=void 0===d?"":d,v=Object(r.a)(e,f),b=t?a?["dark"]:["light"]:["light","dark"];return o.a.createElement(o.a.Fragment,null,b.map((function(e){return o.a.createElement("img",Object(n.a)({key:e,src:c[e],alt:h,className:Object(i.a)(m.a.themedImage,m.a["themedImage--"+e],l)},v))})))},v=a(124),b=a(121),p=a(130),g=["imageClassName","titleClassName"];t.a=function(e){var t=Object(s.default)().isClient,a=Object(b.useThemeConfig)().navbar,c=a.title,i=a.logo,u=void 0===i?{src:""}:i,d=e.imageClassName,m=e.titleClassName,f=Object(r.a)(e,g),k=Object(v.a)(u.href||"/"),E=u.target?{target:u.target}:Object(p.a)(k)?{}:{rel:"noopener noreferrer",target:"_blank"},O={light:Object(v.a)(u.src),dark:Object(v.a)(u.srcDark||u.src)};return o.a.createElement(l.a,Object(n.a)({to:k},f,E),u.src&&o.a.createElement(h,{key:t,className:d,sources:O,alt:u.alt||c||"Logo"}),null!=c&&o.a.createElement("strong",{className:m},c))}},158:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;tthis.startX&&(this.setState({checked:!0}),this.startX=t,this.activated=ta?this.previouslyChecked!==this.state.checked&&(this.setState({checked:!1}),this.previouslyChecked=this.state.checked,t.click()):this.startX-4=0||Object.prototype.hasOwnProperty.call(e,n)&&(a[n]=e[n]);return a}(t,["className","icons"])),c=(0,l.default)("react-toggle",{"react-toggle--checked":this.state.checked,"react-toggle--focus":this.state.hasFocus,"react-toggle--disabled":this.props.disabled},a);return o.default.createElement("div",{className:c,onClick:this.handleClick,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEnd},o.default.createElement("div",{className:"react-toggle-track"},o.default.createElement("div",{className:"react-toggle-track-check"},this.getIcon("checked")),o.default.createElement("div",{className:"react-toggle-track-x"},this.getIcon("unchecked"))),o.default.createElement("div",{className:"react-toggle-thumb"}),o.default.createElement("input",n({},r,{ref:function(t){e.input=t},onFocus:this.handleFocus,onBlur:this.handleBlur,className:"react-toggle-screenreader-only",type:"checkbox"})))}}]),t}(c.PureComponent);t.default=f,f.displayName="Toggle",f.defaultProps={icons:{checked:o.default.createElement(s.default,null),unchecked:o.default.createElement(u.default,null)}},f.propTypes={checked:i.default.bool,disabled:i.default.bool,defaultChecked:i.default.bool,onChange:i.default.func,onFocus:i.default.func,onBlur:i.default.func,className:i.default.string,name:i.default.string,value:i.default.string,id:i.default.string,"aria-labelledby":i.default.string,"aria-label":i.default.string,icons:i.default.oneOfType([i.default.bool,i.default.shape({checked:i.default.node,unchecked:i.default.node})])}},159:function(e,t,a){var n;!function(){"use strict";var a={}.hasOwnProperty;function r(){for(var e=[],t=0;t0){var a=t[0];return{x:a.clientX,y:a.clientY}}var n=e.pageX;if(void 0!==n)return{x:n,y:e.pageY}}return{x:0,y:0}}},163:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return d}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(121),u=["label","to","docsPluginId"];function d(e){var t,a=e.label,c=e.to,d=e.docsPluginId,m=Object(r.a)(e,u),f=Object(i.useActiveVersion)(d),h=Object(s.useDocsPreferredVersion)(d).preferredVersion,v=Object(i.useLatestVersion)(d),b=null!==(t=null!=f?f:h)&&void 0!==t?t:v,p=null!=a?a:b.label,g=null!=c?c:function(e){return e.docs.find((function(t){return t.id===e.mainDocId}))}(b).path;return o.a.createElement(l.a,Object(n.a)({},m,{label:p,to:g}))}},164:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return m}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(121),u=["mobile","docsPluginId","dropdownActiveClassDisabled","dropdownItemsBefore","dropdownItemsAfter"],d=function(e){return e.docs.find((function(t){return t.id===e.mainDocId}))};function m(e){var t,a,c=e.mobile,m=e.docsPluginId,f=e.dropdownActiveClassDisabled,h=e.dropdownItemsBefore,v=e.dropdownItemsAfter,b=Object(r.a)(e,u),p=Object(i.useActiveDocContext)(m),g=Object(i.useVersions)(m),k=Object(i.useLatestVersion)(m),E=Object(s.useDocsPreferredVersion)(m),O=E.preferredVersion,j=E.savePreferredVersionName;var y=null!==(t=null!==(a=p.activeVersion)&&void 0!==a?a:O)&&void 0!==t?t:k,_=c?"Versions":y.label,C=c?void 0:d(y).path;return o.a.createElement(l.a,Object(n.a)({},b,{mobile:c,label:_,to:C,items:function(){var e=g.map((function(e){var t=(null==p?void 0:p.alternateDocVersions[e.name])||d(e);return{isNavLink:!0,label:e.label,to:t.path,isActive:function(){return e===(null==p?void 0:p.activeVersion)},onClick:function(){j(e.name)}}})),t=[].concat(h,e,v);if(!(t.length<=1))return t}(),isActive:f?function(){return!1}:void 0}))}},165:function(e,t,a){"use strict";a.r(t),a.d(t,"default",(function(){return m}));var n=a(3),r=a(7),c=a(0),o=a.n(c),l=a(127),i=a(123),s=a(120),u=a(121),d=["docId","activeSidebarClassName","label","docsPluginId"];function m(e){var t,a,c=e.docId,m=e.activeSidebarClassName,f=e.label,h=e.docsPluginId,v=Object(r.a)(e,d),b=Object(i.useActiveDocContext)(h),p=b.activeVersion,g=b.activeDoc,k=Object(u.useDocsPreferredVersion)(h).preferredVersion,E=Object(i.useLatestVersion)(h),O=null!==(t=null!=p?p:k)&&void 0!==t?t:E,j=O.docs.find((function(e){return e.id===c}));if(!j)throw new Error("DocNavbarItem: couldn't find any doc with id="+c+" in version "+O.name+".\nAvailable docIds=\n- "+O.docs.join("\n- "));return o.a.createElement(l.a,Object(n.a)({exact:!0},v,{className:Object(s.a)(v.className,(a={},a[m]=g&&g.sidebar===j.sidebar,a)),label:null!=f?f:j.id,to:j.path}))}}}]); \ No newline at end of file diff --git a/2.5b37da85.js.LICENSE.txt b/2.f4df6e70.js.LICENSE.txt similarity index 100% rename from 2.5b37da85.js.LICENSE.txt rename to 2.f4df6e70.js.LICENSE.txt diff --git a/26672fd6.c8be9bb4.js b/26672fd6.c8be9bb4.js new file mode 100644 index 000000000..706673ffb --- /dev/null +++ b/26672fd6.c8be9bb4.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{119:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return u}));var a=n(0),o=n.n(a);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=o.a.createContext({}),c=function(e){var t=o.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},d=function(e){var t=c(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},b=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=c(n),b=a,u=d["".concat(s,".").concat(b)]||d[b]||m[b]||r;return n?o.a.createElement(u,l(l({ref:t},p),{},{components:n})):o.a.createElement(u,l({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,s=new Array(r);s[0]=b;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,s[1]=l;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=o.a.createContext({}),c=function(e){var t=o.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},d=function(e){var t=c(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},m=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=c(n),m=a,u=d["".concat(s,".").concat(m)]||d[m]||b[m]||r;return n?o.a.createElement(u,l(l({ref:t},p),{},{components:n})):o.a.createElement(u,l({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,s=new Array(r);s[0]=m;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,s[1]=l;for(var p=2;p=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},i),{},{components:r})):o.a.createElement(m,c({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},i),{},{components:r})):o.a.createElement(m,c({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var c=r.a.createContext({}),p=function(e){var n=r.a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},b=function(e){var n=p(e.components);return r.a.createElement(c.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),b=p(t),m=a,u=b["".concat(s,".").concat(m)]||b[m]||d[m]||o;return t?r.a.createElement(u,i(i({ref:n},c),{},{components:t})):r.a.createElement(u,i({ref:n},c))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,s=new Array(o);s[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var c=2;c,\n// UnknownFieldSet(Map())\n// )\n// ),\n// UnknownFieldSet(Map())\n// )\n\nval typeRegistry = TypeRegistry().addMessage[MyMessage]\n// typeRegistry: TypeRegistry = TypeRegistry(\n// Map(\n// "type.googleapis.com/com.thesamet.docs.MyMessage" -> com.thesamet.docs.json.MyMessage$@5e5e65ca\n// ),\n// Set()\n// )\n\nval printer = new Printer().withTypeRegistry(typeRegistry)\n// printer: Printer = scalapb.json4s.Printer@4c01170\n\nprinter.print(c)\n// res0: String = "{\\"myAny\\":{\\"@type\\":\\"type.googleapis.com/com.thesamet.docs.MyMessage\\",\\"x\\":17}}"\n')),Object(o.b)("p",null,"Conversely, you can start from a JSON and parse it back to a ",Object(o.b)("inlineCode",{parentName:"p"},"MyContainer")," that contains an ",Object(o.b)("inlineCode",{parentName:"p"},"Any")," field:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},'val parser = new Parser().withTypeRegistry(typeRegistry)\n// parser: Parser = scalapb.json4s.Parser@1941d4f0\n\nparser.fromJsonString[MyContainer]("""\n {\n "myAny": {\n "@type": "type.googleapis.com/com.thesamet.docs.MyMessage",\n "x": 17\n }\n }""")\n// res1: MyContainer = MyContainer(\n// Some(\n// Any(\n// "type.googleapis.com/com.thesamet.docs.MyMessage",\n// ,\n// UnknownFieldSet(Map())\n// )\n// ),\n// UnknownFieldSet(Map())\n// )\n')))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/28fe488f.d5b3fa30.js b/28fe488f.d5b3fa30.js deleted file mode 100644 index 9368b6eeb..000000000 --- a/28fe488f.d5b3fa30.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return u}));var a=t(0),r=t.n(a);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var c=r.a.createContext({}),p=function(e){var n=r.a.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},b=function(e){var n=p(e.components);return r.a.createElement(c.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),b=p(t),m=a,u=b["".concat(s,".").concat(m)]||b[m]||d[m]||o;return t?r.a.createElement(u,i(i({ref:n},c),{},{components:t})):r.a.createElement(u,i({ref:n},c))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var o=t.length,s=new Array(o);s[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var c=2;c,\n// UnknownFieldSet(Map())\n// )\n// ),\n// UnknownFieldSet(Map())\n// )\n\nval typeRegistry = TypeRegistry().addMessage[MyMessage]\n// typeRegistry: TypeRegistry = TypeRegistry(\n// Map(\n// "type.googleapis.com/com.thesamet.docs.MyMessage" -> com.thesamet.docs.json.MyMessage$@14d1bf9\n// ),\n// Set()\n// )\n\nval printer = new Printer().withTypeRegistry(typeRegistry)\n// printer: Printer = scalapb.json4s.Printer@5cd80bfc\n\nprinter.print(c)\n// res0: String = "{\\"myAny\\":{\\"@type\\":\\"type.googleapis.com/com.thesamet.docs.MyMessage\\",\\"x\\":17}}"\n')),Object(o.b)("p",null,"Conversely, you can start from a JSON and parse it back to a ",Object(o.b)("inlineCode",{parentName:"p"},"MyContainer")," that contains an ",Object(o.b)("inlineCode",{parentName:"p"},"Any")," field:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),'val parser = new Parser().withTypeRegistry(typeRegistry)\n// parser: Parser = scalapb.json4s.Parser@167c665e\n\nparser.fromJsonString[MyContainer]("""\n {\n "myAny": {\n "@type": "type.googleapis.com/com.thesamet.docs.MyMessage",\n "x": 17\n }\n }""")\n// res1: MyContainer = MyContainer(\n// Some(\n// Any(\n// "type.googleapis.com/com.thesamet.docs.MyMessage",\n// ,\n// UnknownFieldSet(Map())\n// )\n// ),\n// UnknownFieldSet(Map())\n// )\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/3.5a4cea5d.js b/3.5a4cea5d.js deleted file mode 100644 index 39956e535..000000000 --- a/3.5a4cea5d.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return m})),a.d(t,"b",(function(){return d}));var n=a(0),r=a.n(n);function o(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function l(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function c(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var i=r.a.createContext({}),u=function(e){var t=r.a.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},m=function(e){var t=u(e.components);return r.a.createElement(i.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},y=r.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,l=e.parentName,i=s(e,["components","mdxType","originalType","parentName"]),m=u(a),y=n,d=m["".concat(l,".").concat(y)]||m[y]||p[y]||o;return a?r.a.createElement(d,c(c({ref:t},i),{},{components:a})):r.a.createElement(d,c({ref:t},i))}));function d(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,l=new Array(o);l[0]=y;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i{const a=document.createElement("textarea"),n=document.activeElement;a.value=e,a.setAttribute("readonly",""),a.style.contain="strict",a.style.position="absolute",a.style.left="-9999px",a.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),t.append(a),a.select(),a.selectionStart=0,a.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch(c){}return a.remove(),o&&(r.removeAllRanges(),r.addRange(o)),n&&n.focus(),l};e.exports=n,e.exports.default=n},133:function(e,t){function a(e){let t,a=[];for(let n of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(n))a.push(parseInt(n,10));else if(t=n.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,n,r,o]=t;if(n&&o){n=parseInt(n),o=parseInt(o);const e=n0||b)&&r.a.createElement("footer",{className:"row margin-vert--lg"},O.length>0&&r.a.createElement("div",{className:"col"},r.a.createElement("strong",null,"Tags:"),O.map((function(e){var t=e.label,a=e.permalink;return r.a.createElement(s.a,{key:a,className:"margin-horiz--sm",to:a},t)}))),b&&r.a.createElement("div",{className:"col text--right"},r.a.createElement(s.a,{to:f.permalink,"aria-label":"Read more about "+x},r.a.createElement("strong",null,"Read More"))))))}},135:function(e,t,a){"use strict";var n=a(3),r=a(0),o=a.n(r),l=a(122),c=a(120),s={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","at-rule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},i={Prism:a(22).a,theme:s};function u(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function m(){return(m=Object.assign||function(e){for(var t=1;t0&&e[a-1]===t?e:e.concat(t)},g=function(e,t){var a=e.plain,n=Object.create(null),r=e.styles.reduce((function(e,a){var n=a.languages,r=a.style;return n&&!n.includes(t)||a.types.forEach((function(t){var a=m({},e[t],r);e[t]=a})),e}),n);return r.root=a,r.plain=m({},a,{backgroundColor:null}),r};function h(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&-1===t.indexOf(n)&&(a[n]=e[n]);return a}var f=function(e){function t(){for(var t=this,a=[],n=arguments.length;n--;)a[n]=arguments[n];e.apply(this,a),u(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var a=e.theme?g(e.theme,e.language):void 0;return t.themeDict=a})),u(this,"getLineProps",(function(e){var a=e.key,n=e.className,r=e.style,o=m({},h(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(o.style=l.plain),void 0!==r&&(o.style=void 0!==o.style?m({},o.style,r):r),void 0!==a&&(o.key=a),n&&(o.className+=" "+n),o})),u(this,"getStyleForToken",(function(e){var a=e.types,n=e.empty,r=a.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===r&&"plain"===a[0])return n?{display:"inline-block"}:void 0;if(1===r&&!n)return o[a[0]];var l=n?{display:"inline-block"}:{},c=a.map((function(e){return o[e]}));return Object.assign.apply(Object,[l].concat(c))}})),u(this,"getTokenProps",(function(e){var a=e.key,n=e.className,r=e.style,o=e.token,l=m({},h(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==r&&(l.style=void 0!==l.style?m({},l.style,r):r),void 0!==a&&(l.key=a),n&&(l.className+=" "+n),l}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,a=e.language,n=e.code,r=e.children,o=this.getThemeDict(this.props),l=t.languages[a];return r({tokens:function(e){for(var t=[[]],a=[e],n=[0],r=[e.length],o=0,l=0,c=[],s=[c];l>-1;){for(;(o=n[l]++)0?u:["plain"],i=m):(u=d(u,m.type),m.alias&&(u=d(u,m.alias)),i=m.content),"string"==typeof i){var g=i.split(p),h=g.length;c.push({types:u,content:g[0]});for(var f=1;f0}))}l&&_.test(l)&&(k=l.match(_)[1]);var D=a&&a.replace(/language-/,"");!D&&s.defaultLanguage&&(D=s.defaultLanguage);var S=O.replace(/\n$/,"");if(0===b.length&&void 0!==D){for(var L,I="",B=function(e){switch(e){case"js":case"javascript":case"ts":case"typescript":return C(["js","jsBlock"]);case"jsx":case"tsx":return C(["js","jsBlock","jsx"]);case"html":return C(["js","jsBlock","html"]);case"python":case"py":return C(["python"]);default:return C()}}(D),A=O.replace(/\n$/,"").split("\n"),R=0;R=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var i=r.a.createContext({}),u=function(e){var t=r.a.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):c(c({},t),e)),a},m=function(e){var t=u(e.components);return r.a.createElement(i.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},y=r.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,o=e.originalType,l=e.parentName,i=s(e,["components","mdxType","originalType","parentName"]),m=u(a),y=n,d=m["".concat(l,".").concat(y)]||m[y]||p[y]||o;return a?r.a.createElement(d,c(c({ref:t},i),{},{components:a})):r.a.createElement(d,c({ref:t},i))}));function d(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var o=a.length,l=new Array(o);l[0]=y;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i{const a=document.createElement("textarea"),n=document.activeElement;a.value=e,a.setAttribute("readonly",""),a.style.contain="strict",a.style.position="absolute",a.style.left="-9999px",a.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),t.append(a),a.select(),a.selectionStart=0,a.selectionEnd=e.length;let l=!1;try{l=document.execCommand("copy")}catch(c){}return a.remove(),o&&(r.removeAllRanges(),r.addRange(o)),n&&n.focus(),l};e.exports=n,e.exports.default=n},133:function(e,t){function a(e){let t,a=[];for(let n of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(n))a.push(parseInt(n,10));else if(t=n.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,n,r,o]=t;if(n&&o){n=parseInt(n),o=parseInt(o);const e=n0||b)&&r.a.createElement("footer",{className:"row margin-vert--lg"},O.length>0&&r.a.createElement("div",{className:"col"},r.a.createElement("strong",null,"Tags:"),O.map((function(e){var t=e.label,a=e.permalink;return r.a.createElement(s.a,{key:a,className:"margin-horiz--sm",to:a},t)}))),b&&r.a.createElement("div",{className:"col text--right"},r.a.createElement(s.a,{to:f.permalink,"aria-label":"Read more about "+x},r.a.createElement("strong",null,"Read More"))))))}},135:function(e,t,a){"use strict";var n=a(3),r=a(0),o=a.n(r),l=a(122),c=a(120),s={plain:{backgroundColor:"#2a2734",color:"#9a86fd"},styles:[{types:["comment","prolog","doctype","cdata","punctuation"],style:{color:"#6c6783"}},{types:["namespace"],style:{opacity:.7}},{types:["tag","operator","number"],style:{color:"#e09142"}},{types:["property","function"],style:{color:"#9a86fd"}},{types:["tag-id","selector","atrule-id"],style:{color:"#eeebff"}},{types:["attr-name"],style:{color:"#c4b9fe"}},{types:["boolean","string","entity","url","attr-value","keyword","control","directive","unit","statement","regex","at-rule","placeholder","variable"],style:{color:"#ffcc99"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"#c4b9fe"}}]},i={Prism:a(21).a,theme:s};function u(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function m(){return m=Object.assign||function(e){for(var t=1;t0&&e[a-1]===t?e:e.concat(t)},g=function(e,t){var a=e.plain,n=Object.create(null),r=e.styles.reduce((function(e,a){var n=a.languages,r=a.style;return n&&!n.includes(t)||a.types.forEach((function(t){var a=m({},e[t],r);e[t]=a})),e}),n);return r.root=a,r.plain=m({},a,{backgroundColor:null}),r};function h(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&-1===t.indexOf(n)&&(a[n]=e[n]);return a}var f=function(e){function t(){for(var t=this,a=[],n=arguments.length;n--;)a[n]=arguments[n];e.apply(this,a),u(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var a=e.theme?g(e.theme,e.language):void 0;return t.themeDict=a})),u(this,"getLineProps",(function(e){var a=e.key,n=e.className,r=e.style,o=m({},h(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),l=t.getThemeDict(t.props);return void 0!==l&&(o.style=l.plain),void 0!==r&&(o.style=void 0!==o.style?m({},o.style,r):r),void 0!==a&&(o.key=a),n&&(o.className+=" "+n),o})),u(this,"getStyleForToken",(function(e){var a=e.types,n=e.empty,r=a.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===r&&"plain"===a[0])return n?{display:"inline-block"}:void 0;if(1===r&&!n)return o[a[0]];var l=n?{display:"inline-block"}:{},c=a.map((function(e){return o[e]}));return Object.assign.apply(Object,[l].concat(c))}})),u(this,"getTokenProps",(function(e){var a=e.key,n=e.className,r=e.style,o=e.token,l=m({},h(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==r&&(l.style=void 0!==l.style?m({},l.style,r):r),void 0!==a&&(l.key=a),n&&(l.className+=" "+n),l}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,a=e.language,n=e.code,r=e.children,o=this.getThemeDict(this.props),l=t.languages[a];return r({tokens:function(e){for(var t=[[]],a=[e],n=[0],r=[e.length],o=0,l=0,c=[],s=[c];l>-1;){for(;(o=n[l]++)0?u:["plain"],i=m):(u=d(u,m.type),m.alias&&(u=d(u,m.alias)),i=m.content),"string"==typeof i){var g=i.split(p),h=g.length;c.push({types:u,content:g[0]});for(var f=1;f0}))}l&&D.test(l)&&(v=l.match(D)[1]);var T=a&&a.replace(/language-/,"");!T&&s.defaultLanguage&&(T=s.defaultLanguage);var S=O.replace(/\n$/,"");if(0===f.length&&void 0!==T){for(var L,I="",B=function(e){switch(e){case"js":case"javascript":case"ts":case"typescript":return _(["js","jsBlock"]);case"jsx":case"tsx":return _(["js","jsBlock","jsx"]);case"html":return _(["js","jsBlock","html"]);case"python":case"py":return _(["python"]);default:return _()}}(T),A=O.replace(/\n$/,"").split("\n"),R=0;R=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=o.a.createContext({}),l=function(e){var t=o.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},b=function(e){var t=l(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},u=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=l(n),u=a,m=b["".concat(i,".").concat(u)]||b[u]||d[u]||r;return n?o.a.createElement(m,s(s({ref:t},p),{},{components:n})):o.a.createElement(m,s({ref:t},p))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var p=2;p\n // Implicits gives you extension methods that provide ScalaPB\n // names and types for protobuf entities.\n val implicits =\n DescriptorImplicits.fromCodeGenRequest(params, request)\n\n // Process each top-level message in each file.\n // This can be customized if you want to traverse\n // the input in a different way.\n CodeGenResponse.succeed(\n for {\n file <- request.filesToGenerate\n message <- file.getMessageTypes().asScala\n } yield new MessagePrinter(message, implicits).result\n )\n case Left(error) =>\n CodeGenResponse.fail(error)\n }\n}\n')),Object(r.b)("p",null,"The object extends the ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenApp")," trait. This trait provides our application a ",Object(r.b)("inlineCode",{parentName:"p"},"main")," method so it can be used as a standalone protoc plugin. That trait extends another trait named ",Object(r.b)("inlineCode",{parentName:"p"},"ProtocCodeGenerator")," which facilitates the integration with ",Object(r.b)("inlineCode",{parentName:"p"},"sbt-protoc"),". ",Object(r.b)("inlineCode",{parentName:"p"},"ProtocCodeGenerator")," provides for us the method ",Object(r.b)("inlineCode",{parentName:"p"},"suggestedDependencies")," that let us specify which libraries we want to append to the ",Object(r.b)("inlineCode",{parentName:"p"},"libraryDependencies")," of our users. Normally, we want to add our ",Object(r.b)("inlineCode",{parentName:"p"},"core")," library. If you don't need to change the user's library dependencies you can remove this method as the default implementations return an empty list of artifacts."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"registerExtensions")," method is called when parsing the request and used to install protobuf extensions inside an ",Object(r.b)("inlineCode",{parentName:"p"},"ExtensionRegistry"),". This is useful if you are planning to add ",Object(r.b)("a",{parentName:"p",href:"/docs/user_defined_options"},"custom protobuf options"),'. See the section "Adding custom options" below to learn how to add custom options to your generator.'),Object(r.b)("p",null,"The main action happens at the ",Object(r.b)("inlineCode",{parentName:"p"},"process")," method that takes a ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenRequest")," and returns a ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenResponse"),". These classes are simple wrappers around the Java based protobufs ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorRequest")," and ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorResponse")," and are provided by a helper project called ",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/protoc-bridge/tree/master/protoc-gen/src/main/scala/protocgen"},"protocgen"),". This is the place you would normally start to customize from. The template starts by parsing the parameters given in the request, then it creates a ",Object(r.b)("inlineCode",{parentName:"p"},"DescriptorImplicits")," object that provides us with ScalaPB-specific information about the protobuf entities such as the names of generated Scala types."),Object(r.b)("p",null,"It is important to pass ScalaPB's parameters to DescriptorImplicits rather than the default since parameters such as ",Object(r.b)("inlineCode",{parentName:"p"},"flat_package")," change the package name and thus the generated code may not compile due to trying to use a symbol that doesn't exist."),Object(r.b)("p",null,"The code instantiates a ",Object(r.b)("inlineCode",{parentName:"p"},"MessagePrinter")," for each message. We use a class rather than a method here so we only import the implicits in a single place:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'class MessagePrinter(message: Descriptor, implicits: DescriptorImplicits) {\n import implicits._\n\n private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNums")\n\n def scalaFileName =\n MessageObject.fullName.replace(\'.\', \'/\') + ".scala"\n\n def result: CodeGeneratorResponse.File = {\n val b = CodeGeneratorResponse.File.newBuilder()\n b.setName(scalaFileName)\n b.setContent(content)\n b.build()\n }\n\n def printObject(fp: FunctionalPrinter): FunctionalPrinter =\n fp\n .add(s"object ${MessageObject.name} {")\n .indented(\n _.print(message.getFields().asScala){ (fp, fd) => printField(fp, fd) }\n .add("")\n .print(message.getNestedTypes().asScala) {\n (fp, m) => new MessagePrinter(m, implicits).printObject(fp)\n }\n )\n .add("}")\n\n def printField(fp: FunctionalPrinter, fd: FieldDescriptor): FunctionalPrinter =\n fp.add(s"val ${fd.getName} = ${fd.getNumber}")\n\n def content: String = {\n val fp = new FunctionalPrinter()\n .add(\n s"package ${message.getFile.scalaPackage.fullName}",\n "",\n ).call(printObject)\n fp.result\n }\n}\n')),Object(r.b)("h2",{id:"changing-the-generated-code"},"Changing the generated code"),Object(r.b)("p",null,"Let's make a simple change for the generated code. For example, try changing the suffix of the generated classes from ",Object(r.b)("inlineCode",{parentName:"p"},"FieldNums")," to ",Object(r.b)("inlineCode",{parentName:"p"},"FieldNumbers"),":"),Object(r.b)("p",null,"Before:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNums")\n')),Object(r.b)("p",null,"After:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNumbers")\n')),Object(r.b)("p",null," Then run ",Object(r.b)("inlineCode",{parentName:"p"},"e2eJVM2_12/test"),". The code in ",Object(r.b)("inlineCode",{parentName:"p"},"e2e")," will be regenerated, and you\u2019ll see a compilation error, since the tests still use the old names. You can open the generated code under ",Object(r.b)("inlineCode",{parentName:"p"},"target/scala_2.12")," directory to see the modified generated code. To finish this exercise on a positive note, make the tests in ",Object(r.b)("inlineCode",{parentName:"p"},"e2e/src/test/scala")," pass by updating the reference to the new class name.\nPublishing the code generator"),Object(r.b)("h2",{id:"adding-custom-options"},"Adding custom options"),Object(r.b)("p",null,"This section describes how you can let your users customize the generated code\nvia options. To add custom options, follow this process:"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Create a proto file with the custom options you want to add under\n",Object(r.b)("inlineCode",{parentName:"p"},"core/src/main/protobuf"),". Name it something like ",Object(r.b)("inlineCode",{parentName:"p"},"myplugin.proto"),":"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto2";\n\npackage myorg.myplugin;\n\nimport "google/protobuf/descriptor.proto";\n\nextend google.protobuf.MessageOptions {\n optional MyMessageOptions myopts = 60001;\n}\n\nmessage MyMessageOptions {\n optional bool my_option = 1;\n}\n')),Object(r.b)("div",{parentName:"li",className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",{parentName:"div",className:"admonition-heading"},Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",{parentName:"h5",className:"admonition-icon"},Object(r.b)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},Object(r.b)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"The number 60001 above is just an example!")),Object(r.b)("div",{parentName:"div",className:"admonition-content"},Object(r.b)("p",{parentName:"div"},"It's important that different extensions do not use the same numbers so they do not overwrite\neach other's data. If you publish your plugin externally, ",Object(r.b)("a",{parentName:"p",href:"https://github.com/protocolbuffers/protobuf/blob/master/docs/options.md"},"request for an\nextension number here"),".")))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Make your ",Object(r.b)("inlineCode",{parentName:"p"},"core")," project generate both Java and Scala sources for the\ncustom options proto by adding the following settings to the ",Object(r.b)("inlineCode",{parentName:"p"},"core"),"\nproject in ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-scala"},'Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value / "scalapb",\n scalapb.gen(javaConversions = true) ->\n (Compile / sourceManaged).value / "scalapb",\n)\n'))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"The core project will only need the Java version of the new protobuf.\nUpdate its settings as follows:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-scala"},'libraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "compilerplugin" % scalapb.compiler.Version.scalapbVersion,\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion,\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",\n ),\n Compile / PB.protoSources += core.base / "src" / "main" / "protobuf",\n Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value / "scalapb"\n )\n')),Object(r.b)("p",{parentName:"li"},"This would tell ScalaPB to compile the protobuf that's in the core project protobuf directory. We\nare adding ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb")," as a ",Object(r.b)("inlineCode",{parentName:"p"},'"protobuf"')," dependency so it extracts ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb.proto"),", and its own\ntransitive dependencies which includes ",Object(r.b)("inlineCode",{parentName:"p"},"google/protobuf/descriptor.proto"),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Register the extension in the code generator. In your code generator , under ",Object(r.b)("inlineCode",{parentName:"p"},"code-gen/src/main/scala/"),"\nlook for the ",Object(r.b)("inlineCode",{parentName:"p"},"registerExtensions")," method, and add a call to register your own extension:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-scala"},"myorg.myplugin.Myplugin.registerAllExtensions(registry)\n"))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Now you are able to extract the extension value in your generator using the standard protobuf-java\nAPIs:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-scsala"},"messageDescriptor.getOptions.getExtension(myorg.myplugin.Myplugin.myopts).getMyOption\n"))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"You can now use the new option in your e2e tests. Also the newly added proto will be automatically\npackaged with the core jar. External projects will be able to unpack it by depending on the core\nlibrary with a ",Object(r.b)("inlineCode",{parentName:"p"},'% "protobuf"')," scope. To use:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},'import "myplugin.proto";\n\nmessage MyMessage {\n option (myplugin.myopts).my_option = false;\n}\n')))),Object(r.b)("h2",{id:"publishing-the-plugin"},"Publishing the plugin"),Object(r.b)("p",null,"The project can be published to Maven using the \u201cpublish\u201d command. We recommend to use the excellent ",Object(r.b)("a",{parentName:"p",href:"https://github.com/olafurpg/sbt-ci-release"},"sbt-ci-release")," plugin to automatically build a snapshot on each commit, and a full release when pushing a git tag."),Object(r.b)("p",null,"SBT users of your code generators will add your plugin to the build by adding it to their ",Object(r.b)("inlineCode",{parentName:"p"},"project/plugins.sbt")," like this:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value / "scalapb",\n com.myplugin.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(r.b)("p",null,"The template also publishes artifacts with names ending with ",Object(r.b)("inlineCode",{parentName:"p"},"unix.sh")," and ",Object(r.b)("inlineCode",{parentName:"p"},"windows.bat"),". These are executable jars for Unix and Windows systems that contain all the classes needed to run your code generator (except of a JVM which is expected to be in ",Object(r.b)("inlineCode",{parentName:"p"},"JAVA_HOME")," or in the ",Object(r.b)("inlineCode",{parentName:"p"},"PATH"),"). This is useful if your users need to use your plugin directly with protoc, or with a build tool such as maven."),Object(r.b)("h2",{id:"secondary-outputs"},"Secondary outputs"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",{parentName:"div",className:"admonition-heading"},Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",{parentName:"h5",className:"admonition-icon"},Object(r.b)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},Object(r.b)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),Object(r.b)("div",{parentName:"div",className:"admonition-content"},Object(r.b)("p",{parentName:"div"},"Secondary outputs were introduced in protoc-bridge 0.9.0 and are supported by sbt-protoc 1.0.0 and onwards."))),Object(r.b)("p",null,"Secondary outputs provide a simple way for protoc plugins to pass information for other protoc plugins running after them in the same protoc invocation. The information is passed through files that are created in a temporary directory. The absolute path of that temporary directory is provided to all protoc plugins. Plugins may create new files in that directory for subsequent plugins to consume."),Object(r.b)("p",null,"Conventions:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Names of secondary output files should be in ",Object(r.b)("inlineCode",{parentName:"li"},"kebab-case"),", and should clearly identify the plugin producing them. For example ",Object(r.b)("inlineCode",{parentName:"li"},"scalapb-validate-preprocessor"),"."),Object(r.b)("li",{parentName:"ul"},"The content of the file should be a serialized ",Object(r.b)("inlineCode",{parentName:"li"},"google.protobuf.Any")," message that packs the arbitrary payload the plugin wants to publish.")),Object(r.b)("h3",{id:"determining-the-secondary-output-directory-location"},"Determining the secondary output directory location"),Object(r.b)("p",null,"JVM-based plugins that are executed in the same JVM that spawns protoc (like the ones described on this page), receive the location of the secondary output directory via the ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorRequest"),". ",Object(r.b)("inlineCode",{parentName:"p"},"protoc-bridge")," appends to the request an unknown field carrying a message called ",Object(r.b)("inlineCode",{parentName:"p"},"ExtraEnv")," which contains the path to the secondary output directory."),Object(r.b)("p",null,"Other plugins that are invoked directly by protoc can find the secondary output directory by inspecting the ",Object(r.b)("inlineCode",{parentName:"p"},"SCALAPB_SECONDARY_OUTPUT_DIR")," environment variable."),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"protoc-bridge")," takes care of creating the temporary directory and setting up the environment variable before invoking ",Object(r.b)("inlineCode",{parentName:"p"},"protoc"),". If ",Object(r.b)("inlineCode",{parentName:"p"},"protoc")," is ran manually (for example, through the CLI), it is the user's responsibility to create a directory for secondary outputs and pass it as an environment variable to ",Object(r.b)("inlineCode",{parentName:"p"},"protoc"),". It's worth noting that ScalaPB only looks for secondary output directory if a preprocessor is requested, and therefore for the most part users do not need to worry about secondary output directories."),Object(r.b)("p",null,"In ScalaPB's code base, ",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/blob/75ad2323b8fc35f005c40471fa714a0eca0afd6d/compiler-plugin/src/main/scala/scalapb/compiler/SecondaryOutputProvider.scala#L78-L83"},"SecondaryOutputProvider")," provides a method to find the secondary output directory as described above."),Object(r.b)("h2",{id:"preprocessors"},"Preprocessors"),Object(r.b)("p",null,"Preprocessors are protoc plugins that provide ",Object(r.b)("a",{parentName:"p",href:"#secondary-outputs"},"secondary outputs")," that are consumed by ScalaPB. ScalaPB expects the secondary output to be a ",Object(r.b)("inlineCode",{parentName:"p"},"google.protobuf.Any")," that encodes a ",Object(r.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/blob/75ad2323b8fc35f005c40471fa714a0eca0afd6d/protobuf/scalapb/scalapb.proto#L346-L348"},"PreprocessorOutput"),". The message contains a map between proto file names (as given by ",Object(r.b)("inlineCode",{parentName:"p"},"FileDescriptor#getFullName()"),") to additional ",Object(r.b)("inlineCode",{parentName:"p"},"ScalaPbOptions")," that are merged with the files options. By appending to ",Object(r.b)("inlineCode",{parentName:"p"},"aux_field_options"),", a preprocessor can, for example, impact the generated types of ScalaPB fields."),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"ScalaPB applies the provided options to a proto file only if the original file lists the preprocessor secondary output filename in a ",Object(r.b)("inlineCode",{parentName:"li"},"preprocessors")," file-level option. That option can be inherited from a package-scoped option."),Object(r.b)("li",{parentName:"ul"},"To exclude a specific file from being preprocessed (if it would be otherwise impacted by a package-scoped option), add a ",Object(r.b)("inlineCode",{parentName:"li"},"-NAME")," entry to the list of preprocessors where ",Object(r.b)("inlineCode",{parentName:"li"},"NAME")," is the name of the preprocessor's secondary output."),Object(r.b)("li",{parentName:"ul"},"In case of multiple preprocessors, options of later preprocessors overrides the one of earlier processors. Options in the file are merged over the preprocessor's options. When merging, repeated fields get concatenated."),Object(r.b)("li",{parentName:"ul"},"Preprocessor plugins need to be invoked (in ",Object(r.b)("inlineCode",{parentName:"li"},"PB.targets")," or protoc's command line) before ScalaPB, so when ScalaPB runs their output is available."),Object(r.b)("li",{parentName:"ul"},"Plugins that depend on ScalaPB (such as scalapb-validate) rely on ",Object(r.b)("inlineCode",{parentName:"li"},"DescriptorImplicits")," which consume the preprocessor output and therefore also see the updated options.")),Object(r.b)("h2",{id:"summary"},"Summary"),Object(r.b)("p",null,"If you followed this guide all the way to here, then congratulations for creating your first protoc plugin in Scala!"),Object(r.b)("p",null,"If you have any questions, feel free to reach out to us on Gitter or Github."),Object(r.b)("p",null,"Did you write an interesting protoc plugin? Let us know on our gitter channel or our Google group and we'd love to mention it here!"))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/30c1f25e.cc03965a.js b/30c1f25e.cc03965a.js deleted file mode 100644 index a4398a611..000000000 --- a/30c1f25e.cc03965a.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return b})),a.d(t,"b",(function(){return m}));var n=a(0),o=a.n(n);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function s(e){for(var t=1;t=0||(o[a]=e[a]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(o[a]=e[a])}return o}var p=o.a.createContext({}),l=function(e){var t=o.a.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},b=function(e){var t=l(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},u=o.a.forwardRef((function(e,t){var a=e.components,n=e.mdxType,r=e.originalType,i=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=l(a),u=n,m=b["".concat(i,".").concat(u)]||b[u]||d[u]||r;return a?o.a.createElement(m,s(s({ref:t},p),{},{components:a})):o.a.createElement(m,s({ref:t},p))}));function m(e,t){var a=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=a.length,i=new Array(r);i[0]=u;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:n,i[1]=s;for(var p=2;p\n // Implicits gives you extension methods that provide ScalaPB\n // names and types for protobuf entities.\n val implicits =\n DescriptorImplicits.fromCodeGenRequest(params, request)\n\n // Process each top-level message in each file.\n // This can be customized if you want to traverse\n // the input in a different way.\n CodeGenResponse.succeed(\n for {\n file <- request.filesToGenerate\n message <- file.getMessageTypes().asScala\n } yield new MessagePrinter(message, implicits).result\n )\n case Left(error) =>\n CodeGenResponse.fail(error)\n }\n}\n')),Object(r.b)("p",null,"The object extends the ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenApp")," trait. This trait provides our application a ",Object(r.b)("inlineCode",{parentName:"p"},"main")," method so it can be used as a standalone protoc plugin. That trait extends another trait named ",Object(r.b)("inlineCode",{parentName:"p"},"ProtocCodeGenerator")," which facilitates the integration with ",Object(r.b)("inlineCode",{parentName:"p"},"sbt-protoc"),". ",Object(r.b)("inlineCode",{parentName:"p"},"ProtocCodeGenerator")," provides for us the method ",Object(r.b)("inlineCode",{parentName:"p"},"suggestedDependencies")," that let us specify which libraries we want to append to the ",Object(r.b)("inlineCode",{parentName:"p"},"libraryDependencies")," of our users. Normally, we want to add our ",Object(r.b)("inlineCode",{parentName:"p"},"core")," library. If you don't need to change the user's library dependencies you can remove this method as the default implementations return an empty list of artifacts."),Object(r.b)("p",null,"The ",Object(r.b)("inlineCode",{parentName:"p"},"registerExtensions")," method is called when parsing the request and used to install protobuf extensions inside an ",Object(r.b)("inlineCode",{parentName:"p"},"ExtensionRegistry"),". This is useful if you are planning to add ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"/docs/user_defined_options"}),"custom protobuf options"),'. See the section "Adding custom options" below to learn how to add custom options to your generator.'),Object(r.b)("p",null,"The main action happens at the ",Object(r.b)("inlineCode",{parentName:"p"},"process")," method that takes a ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenRequest")," and returns a ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGenResponse"),". These classes are simple wrappers around the Java based protobufs ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorRequest")," and ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorResponse")," and are provided by a helper project called ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/protoc-bridge/tree/master/protoc-gen/src/main/scala/protocgen"}),"protocgen"),". This is the place you would normally start to customize from. The template starts by parsing the parameters given in the request, then it creates a ",Object(r.b)("inlineCode",{parentName:"p"},"DescriptorImplicits")," object that provides us with ScalaPB-specific information about the protobuf entities such as the names of generated Scala types."),Object(r.b)("p",null,"It is important to pass ScalaPB's parameters to DescriptorImplicits rather than the default since parameters such as ",Object(r.b)("inlineCode",{parentName:"p"},"flat_package")," change the package name and thus the generated code may not compile due to trying to use a symbol that doesn't exist."),Object(r.b)("p",null,"The code instantiates a ",Object(r.b)("inlineCode",{parentName:"p"},"MessagePrinter")," for each message. We use a class rather than a method here so we only import the implicits in a single place:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'class MessagePrinter(message: Descriptor, implicits: DescriptorImplicits) {\n import implicits._\n\n private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNums")\n\n def scalaFileName =\n MessageObject.fullName.replace(\'.\', \'/\') + ".scala"\n\n def result: CodeGeneratorResponse.File = {\n val b = CodeGeneratorResponse.File.newBuilder()\n b.setName(scalaFileName)\n b.setContent(content)\n b.build()\n }\n\n def printObject(fp: FunctionalPrinter): FunctionalPrinter =\n fp\n .add(s"object ${MessageObject.name} {")\n .indented(\n _.print(message.getFields().asScala){ (fp, fd) => printField(fp, fd) }\n .add("")\n .print(message.getNestedTypes().asScala) {\n (fp, m) => new MessagePrinter(m, implicits).printObject(fp)\n }\n )\n .add("}")\n\n def printField(fp: FunctionalPrinter, fd: FieldDescriptor): FunctionalPrinter =\n fp.add(s"val ${fd.getName} = ${fd.getNumber}")\n\n def content: String = {\n val fp = new FunctionalPrinter()\n .add(\n s"package ${message.getFile.scalaPackage.fullName}",\n "",\n ).call(printObject)\n fp.result\n }\n}\n')),Object(r.b)("h2",{id:"changing-the-generated-code"},"Changing the generated code"),Object(r.b)("p",null,"Let's make a simple change for the generated code. For example, try changing the suffix of the generated classes from ",Object(r.b)("inlineCode",{parentName:"p"},"FieldNums")," to ",Object(r.b)("inlineCode",{parentName:"p"},"FieldNumbers"),":"),Object(r.b)("p",null,"Before:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNums")\n')),Object(r.b)("p",null,"After:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'private val MessageObject =\n message.scalaType.sibling(message.scalaType.name + "FieldNumbers")\n')),Object(r.b)("p",null," Then run ",Object(r.b)("inlineCode",{parentName:"p"},"e2eJVM2_12/test"),". The code in ",Object(r.b)("inlineCode",{parentName:"p"},"e2e")," will be regenerated, and you\u2019ll see a compilation error, since the tests still use the old names. You can open the generated code under ",Object(r.b)("inlineCode",{parentName:"p"},"target/scala_2.12")," directory to see the modified generated code. To finish this exercise on a positive note, make the tests in ",Object(r.b)("inlineCode",{parentName:"p"},"e2e/src/test/scala")," pass by updating the reference to the new class name.\nPublishing the code generator"),Object(r.b)("h2",{id:"adding-custom-options"},"Adding custom options"),Object(r.b)("p",null,"This section describes how you can let your users customize the generated code\nvia options. To add custom options, follow this process:"),Object(r.b)("ol",null,Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Create a proto file with the custom options you want to add under\n",Object(r.b)("inlineCode",{parentName:"p"},"core/src/main/protobuf"),". Name it something like ",Object(r.b)("inlineCode",{parentName:"p"},"myplugin.proto"),":"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'syntax = "proto2";\n\npackage myorg.myplugin;\n\nimport "google/protobuf/descriptor.proto";\n\nextend google.protobuf.MessageOptions {\n optional MyMessageOptions myopts = 60001;\n}\n\nmessage MyMessageOptions {\n optional bool my_option = 1;\n}\n')),Object(r.b)("div",Object(n.a)({parentName:"li"},{className:"admonition admonition-note alert alert--secondary"}),Object(r.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(n.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(n.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(n.a)({parentName:"svg"},{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})))),"The number 60001 above is just an example!")),Object(r.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"It's important that different extensions do not use the same numbers so they do not overwrite\neach other's data. If you publish your plugin externally, ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/protocolbuffers/protobuf/blob/master/docs/options.md"}),"request for an\nextension number here"),".")))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Make your ",Object(r.b)("inlineCode",{parentName:"p"},"core")," project generate both Java and Scala sources for the\ncustom options proto by adding the following settings to the ",Object(r.b)("inlineCode",{parentName:"p"},"core"),"\nproject in ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value / "scalapb",\n scalapb.gen(javaConversions = true) ->\n (Compile / sourceManaged).value / "scalapb",\n)\n'))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"The core project will only need the Java version of the new protobuf.\nUpdate its settings as follows:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'libraryDependencies ++= Seq(\n "com.thesamet.scalapb" %% "compilerplugin" % scalapb.compiler.Version.scalapbVersion,\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion,\n "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",\n ),\n Compile / PB.protoSources += core.base / "src" / "main" / "protobuf",\n Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value / "scalapb"\n )\n')),Object(r.b)("p",{parentName:"li"},"This would tell ScalaPB to compile the protobuf that's in the core project protobuf directory. We\nare adding ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb")," as a ",Object(r.b)("inlineCode",{parentName:"p"},'"protobuf"')," dependency so it extracts ",Object(r.b)("inlineCode",{parentName:"p"},"scalapb.proto"),", and its own\ntransitive dependencies which includes ",Object(r.b)("inlineCode",{parentName:"p"},"google/protobuf/descriptor.proto"),".")),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Register the extension in the code generator. In your code generator , under ",Object(r.b)("inlineCode",{parentName:"p"},"code-gen/src/main/scala/"),"\nlook for the ",Object(r.b)("inlineCode",{parentName:"p"},"registerExtensions")," method, and add a call to register your own extension:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),"myorg.myplugin.Myplugin.registerAllExtensions(registry)\n"))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"Now you are able to extract the extension value in your generator using the standard protobuf-java\nAPIs:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scsala"}),"messageDescriptor.getOptions.getExtension(myorg.myplugin.Myplugin.myopts).getMyOption\n"))),Object(r.b)("li",{parentName:"ol"},Object(r.b)("p",{parentName:"li"},"You can now use the new option in your e2e tests. Also the newly added proto will be automatically\npackaged with the core jar. External projects will be able to unpack it by depending on the core\nlibrary with a ",Object(r.b)("inlineCode",{parentName:"p"},'% "protobuf"')," scope. To use:"),Object(r.b)("pre",{parentName:"li"},Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-protobuf"}),'import "myplugin.proto";\n\nmessage MyMessage {\n option (myplugin.myopts).my_option = false;\n}\n')))),Object(r.b)("h2",{id:"publishing-the-plugin"},"Publishing the plugin"),Object(r.b)("p",null,"The project can be published to Maven using the \u201cpublish\u201d command. We recommend to use the excellent ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/olafurpg/sbt-ci-release"}),"sbt-ci-release")," plugin to automatically build a snapshot on each commit, and a full release when pushing a git tag."),Object(r.b)("p",null,"SBT users of your code generators will add your plugin to the build by adding it to their ",Object(r.b)("inlineCode",{parentName:"p"},"project/plugins.sbt")," like this:"),Object(r.b)("pre",null,Object(r.b)("code",Object(n.a)({parentName:"pre"},{className:"language-scala"}),'Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value / "scalapb",\n com.myplugin.gen() -> (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(r.b)("p",null,"The template also publishes artifacts with names ending with ",Object(r.b)("inlineCode",{parentName:"p"},"unix.sh")," and ",Object(r.b)("inlineCode",{parentName:"p"},"windows.bat"),". These are executable jars for Unix and Windows systems that contain all the classes needed to run your code generator (except of a JVM which is expected to be in ",Object(r.b)("inlineCode",{parentName:"p"},"JAVA_HOME")," or in the ",Object(r.b)("inlineCode",{parentName:"p"},"PATH"),"). This is useful if your users need to use your plugin directly with protoc, or with a build tool such as maven."),Object(r.b)("h2",{id:"secondary-outputs"},"Secondary outputs"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(n.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(n.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(n.a)({parentName:"svg"},{fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"})))),"note")),Object(r.b)("div",Object(n.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"Secondary outputs were introduced in protoc-bridge 0.9.0 and are supported by sbt-protoc 1.0.0 and onwards."))),Object(r.b)("p",null,"Secondary outputs provide a simple way for protoc plugins to pass information for other protoc plugins running after them in the same protoc invocation. The information is passed through files that are created in a temporary directory. The absolute path of that temporary directory is provided to all protoc plugins. Plugins may create new files in that directory for subsequent plugins to consume."),Object(r.b)("p",null,"Conventions:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"Names of secondary output files should be in ",Object(r.b)("inlineCode",{parentName:"li"},"kebab-case"),", and should clearly identify the plugin producing them. For example ",Object(r.b)("inlineCode",{parentName:"li"},"scalapb-validate-preprocessor"),"."),Object(r.b)("li",{parentName:"ul"},"The content of the file should be a serialized ",Object(r.b)("inlineCode",{parentName:"li"},"google.protobuf.Any")," message that packs the arbitrary payload the plugin wants to publish.")),Object(r.b)("h3",{id:"determining-the-secondary-output-directory-location"},"Determining the secondary output directory location"),Object(r.b)("p",null,"JVM-based plugins that are executed in the same JVM that spawns protoc (like the ones described on this page), receive the location of the secondary output directory via the ",Object(r.b)("inlineCode",{parentName:"p"},"CodeGeneratorRequest"),". ",Object(r.b)("inlineCode",{parentName:"p"},"protoc-bridge")," appends to the request an unknown field carrying a message called ",Object(r.b)("inlineCode",{parentName:"p"},"ExtraEnv")," which contains the path to the secondary output directory."),Object(r.b)("p",null,"Other plugins that are invoked directly by protoc can find the secondary output directory by inspecting the ",Object(r.b)("inlineCode",{parentName:"p"},"SCALAPB_SECONDARY_OUTPUT_DIR")," environment variable."),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"protoc-bridge")," takes care of creating the temporary directory and setting up the environment variable before invoking ",Object(r.b)("inlineCode",{parentName:"p"},"protoc"),". If ",Object(r.b)("inlineCode",{parentName:"p"},"protoc")," is ran manually (for example, through the CLI), it is the user's responsibility to create a directory for secondary outputs and pass it as an environment variable to ",Object(r.b)("inlineCode",{parentName:"p"},"protoc"),". It's worth noting that ScalaPB only looks for secondary output directory if a preprocessor is requested, and therefore for the most part users do not need to worry about secondary output directories."),Object(r.b)("p",null,"In ScalaPB's code base, ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/ScalaPB/blob/75ad2323b8fc35f005c40471fa714a0eca0afd6d/compiler-plugin/src/main/scala/scalapb/compiler/SecondaryOutputProvider.scala#L78-L83"}),"SecondaryOutputProvider")," provides a method to find the secondary output directory as described above."),Object(r.b)("h2",{id:"preprocessors"},"Preprocessors"),Object(r.b)("p",null,"Preprocessors are protoc plugins that provide ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"#secondary-outputs"}),"secondary outputs")," that are consumed by ScalaPB. ScalaPB expects the secondary output to be a ",Object(r.b)("inlineCode",{parentName:"p"},"google.protobuf.Any")," that encodes a ",Object(r.b)("a",Object(n.a)({parentName:"p"},{href:"https://github.com/scalapb/ScalaPB/blob/75ad2323b8fc35f005c40471fa714a0eca0afd6d/protobuf/scalapb/scalapb.proto#L346-L348"}),"PreprocessorOutput"),". The message contains a map between proto file names (as given by ",Object(r.b)("inlineCode",{parentName:"p"},"FileDescriptor#getFullName()"),") to additional ",Object(r.b)("inlineCode",{parentName:"p"},"ScalaPbOptions")," that are merged with the files options. By appending to ",Object(r.b)("inlineCode",{parentName:"p"},"aux_field_options"),", a preprocessor can, for example, impact the generated types of ScalaPB fields."),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"ScalaPB applies the provided options to a proto file only if the original file lists the preprocessor secondary output filename in a ",Object(r.b)("inlineCode",{parentName:"li"},"preprocessors")," file-level option. That option can be inherited from a package-scoped option."),Object(r.b)("li",{parentName:"ul"},"To exclude a specific file from being preprocessed (if it would be otherwise impacted by a package-scoped option), add a ",Object(r.b)("inlineCode",{parentName:"li"},"-NAME")," entry to the list of preprocessors where ",Object(r.b)("inlineCode",{parentName:"li"},"NAME")," is the name of the preprocessor's secondary output."),Object(r.b)("li",{parentName:"ul"},"In case of multiple preprocessors, options of later preprocessors overrides the one of earlier processors. Options in the file are merged over the preprocessor's options. When merging, repeated fields get concatenated."),Object(r.b)("li",{parentName:"ul"},"Preprocessor plugins need to be invoked (in ",Object(r.b)("inlineCode",{parentName:"li"},"PB.targets")," or protoc's command line) before ScalaPB, so when ScalaPB runs their output is available."),Object(r.b)("li",{parentName:"ul"},"Plugins that depend on ScalaPB (such as scalapb-validate) rely on ",Object(r.b)("inlineCode",{parentName:"li"},"DescriptorImplicits")," which consume the preprocessor output and therefore also see the updated options.")),Object(r.b)("h2",{id:"summary"},"Summary"),Object(r.b)("p",null,"If you followed this guide all the way to here, then congratulations for creating your first protoc plugin in Scala!"),Object(r.b)("p",null,"If you have any questions, feel free to reach out to us on Gitter or Github."),Object(r.b)("p",null,"Did you write an interesting protoc plugin? Let us know on our gitter channel or our Google group and we'd love to mention it here!"))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/3570154c.42857bb2.js b/3570154c.1ff3f249.js similarity index 54% rename from 3570154c.42857bb2.js rename to 3570154c.1ff3f249.js index b4b7a4c8b..2ebac1a95 100644 --- a/3570154c.42857bb2.js +++ b/3570154c.1ff3f249.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{119:function(e,t,r){"use strict";r.d(t,"a",(function(){return s})),r.d(t,"b",(function(){return m}));var n=r(0),o=r.n(n);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,c=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(c,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,l(l({ref:t},i),{},{components:r})):o.a.createElement(m,l({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,c=new Array(a);c[0]=f;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:n,c[1]=l;for(var i=2;i=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},b=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,c=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),b=n,m=s["".concat(c,".").concat(b)]||s[b]||f[b]||a;return r?o.a.createElement(m,l(l({ref:t},i),{},{components:r})):o.a.createElement(m,l({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,c=new Array(a);c[0]=b;var l={};for(var u in t)hasOwnProperty.call(t,u)&&(l[u]=t[u]);l.originalType=e,l.mdxType="string"==typeof e?e:n,c[1]=l;for(var i=2;i=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=o.a.createContext({}),u=function(e){var t=o.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},l=function(e){var t=u(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},m=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),l=u(n),m=a,b=l["".concat(i,".").concat(m)]||l[m]||d[m]||r;return n?o.a.createElement(b,c(c({ref:t},p),{},{components:n})):o.a.createElement(b,c({ref:t},p))}));function b(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=m;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:a,i[1]=c;for(var p=2;p=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var p=o.a.createContext({}),u=function(e){var t=o.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):c(c({},t),e)),n},l=function(e){var t=u(e.components);return o.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},m=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),l=u(n),m=a,b=l["".concat(i,".").concat(m)]||l[m]||d[m]||r;return n?o.a.createElement(b,c(c({ref:t},p),{},{components:n})):o.a.createElement(b,c({ref:t},p))}));function b(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=m;var c={};for(var s in t)hasOwnProperty.call(t,s)&&(c[s]=t[s]);c.originalType=e,c.mdxType="string"==typeof e?e:a,i[1]=c;for(var p=2;p=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=n.a.createContext({}),p=function(e){var t=n.a.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},u=function(e){var t=p(e.components);return n.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},m=n.a.forwardRef((function(e,t){var a=e.components,r=e.mdxType,c=e.originalType,o=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),u=p(a),m=r,d=u["".concat(o,".").concat(m)]||u[m]||b[m]||c;return a?n.a.createElement(d,s(s({ref:t},i),{},{components:a})):n.a.createElement(d,s({ref:t},i))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var c=a.length,o=new Array(c);o[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var i=2;i=\n0.6.0 would cover most use cases)")),Object(c.b)("h2",{id:"getting-started"},"Getting Started"),Object(c.b)("p",null,"Add to your library dependencies:"),Object(c.b)("pre",null,Object(c.b)("code",{parentName:"pre"},'libraryDependencies ++= Seq(\n "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion,\n\n // The following needed only if you include scalapb/scalapb.proto:\n "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n)\n')),Object(c.b)("h2",{id:"demo"},"Demo"),Object(c.b)("p",null,"Example project: ",Object(c.b)("a",{parentName:"p",href:"https://github.com/thesamet/scalapbjs-test"},"https://github.com/thesamet/scalapbjs-test")),Object(c.b)("p",null,"Example with multi-project build: ",Object(c.b)("a",{parentName:"p",href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/scalajs-multiproject"},"https://github.com/thesamet/sbt-protoc/tree/master/examples/scalajs-multiproject")),Object(c.b)("p",null,"Live demo: ",Object(c.b)("a",{parentName:"p",href:"http://thesamet.github.io/scalapbjs-test/"},"http://thesamet.github.io/scalapbjs-test/")))}u.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/3a4cb4c8.f649c61c.js b/3a4cb4c8.f649c61c.js deleted file mode 100644 index c8cbbfa18..000000000 --- a/3a4cb4c8.f649c61c.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{119:function(e,t,a){"use strict";a.d(t,"a",(function(){return b})),a.d(t,"b",(function(){return d}));var r=a(0),n=a.n(r);function c(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function o(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,r)}return a}function s(e){for(var t=1;t=0||(n[a]=e[a]);return n}(e,t);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(n[a]=e[a])}return n}var i=n.a.createContext({}),p=function(e){var t=n.a.useContext(i),a=t;return e&&(a="function"==typeof e?e(t):s(s({},t),e)),a},b=function(e){var t=p(e.components);return n.a.createElement(i.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},m=n.a.forwardRef((function(e,t){var a=e.components,r=e.mdxType,c=e.originalType,o=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),b=p(a),m=r,d=b["".concat(o,".").concat(m)]||b[m]||u[m]||c;return a?n.a.createElement(d,s(s({ref:t},i),{},{components:a})):n.a.createElement(d,s({ref:t},i))}));function d(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var c=a.length,o=new Array(c);o[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var i=2;i=\n0.6.0 would cover most use cases)")),Object(c.b)("h2",{id:"getting-started"},"Getting Started"),Object(c.b)("p",null,"Add to your library dependencies:"),Object(c.b)("pre",null,Object(c.b)("code",Object(r.a)({parentName:"pre"},{}),'libraryDependencies ++= Seq(\n "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion,\n\n // The following needed only if you include scalapb/scalapb.proto:\n "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n)\n')),Object(c.b)("h2",{id:"demo"},"Demo"),Object(c.b)("p",null,"Example project: ",Object(c.b)("a",Object(r.a)({parentName:"p"},{href:"https://github.com/thesamet/scalapbjs-test"}),"https://github.com/thesamet/scalapbjs-test")),Object(c.b)("p",null,"Example with multi-project build: ",Object(c.b)("a",Object(r.a)({parentName:"p"},{href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/scalajs-multiproject"}),"https://github.com/thesamet/sbt-protoc/tree/master/examples/scalajs-multiproject")),Object(c.b)("p",null,"Live demo: ",Object(c.b)("a",Object(r.a)({parentName:"p"},{href:"http://thesamet.github.io/scalapbjs-test/"}),"http://thesamet.github.io/scalapbjs-test/")))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/404.html b/404.html index b3457f448..72ee76654 100644 --- a/404.html +++ b/404.html @@ -8,16 +8,16 @@ -Page Not Found | ScalaPB - - - +Page Not Found | ScalaPB + + +

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - - + + + \ No newline at end of file diff --git a/409a7ded.c0c8198c.js b/409a7ded.c0c8198c.js new file mode 100644 index 000000000..9fad2e3bc --- /dev/null +++ b/409a7ded.c0c8198c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return g}));var r=t(0),a=t.n(r);function l(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function c(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=a.a.createContext({}),p=function(e){var n=a.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},b=function(e){var n=p(e.components);return a.a.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},d=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,i=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),b=p(t),d=r,g=b["".concat(i,".").concat(d)]||b[d]||u[d]||l;return t?a.a.createElement(g,c(c({ref:n},s),{},{components:t})):a.a.createElement(g,c({ref:n},s))}));function g(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,i=new Array(l);i[0]=d;var c={};for(var o in n)hasOwnProperty.call(n,o)&&(c[o]=n[o]);c.originalType=e,c.mdxType="string"==typeof e?e:r,i[1]=c;for(var s=2;s MergeStrategy.discard\n case x =>\n val oldStrategy = (assemblyMergeStrategy in assembly).value\n oldStrategy(x)\n}\n')))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/409a7ded.ef9fca60.js b/409a7ded.ef9fca60.js deleted file mode 100644 index 865b3c58b..000000000 --- a/409a7ded.ef9fca60.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return g}));var r=t(0),a=t.n(r);function l(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function c(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function i(e){for(var n=1;n=0||(a[t]=e[t]);return a}(e,n);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(a[t]=e[t])}return a}var s=a.a.createContext({}),p=function(e){var n=a.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},b=function(e){var n=p(e.components);return a.a.createElement(s.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},d=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,l=e.originalType,c=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),b=p(t),d=r,g=b["".concat(c,".").concat(d)]||b[d]||u[d]||l;return t?a.a.createElement(g,i(i({ref:n},s),{},{components:t})):a.a.createElement(g,i({ref:n},s))}));function g(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var l=t.length,c=new Array(l);c[0]=d;var i={};for(var o in n)hasOwnProperty.call(n,o)&&(i[o]=n[o]);i.originalType=e,i.mdxType="string"==typeof e?e:r,c[1]=i;for(var s=2;s MergeStrategy.discard\n case x =>\n val oldStrategy = (assemblyMergeStrategy in assembly).value\n oldStrategy(x)\n}\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/44966442.ef8626a8.js b/44966442.ef8626a8.js deleted file mode 100644 index c248c635a..000000000 --- a/44966442.ef8626a8.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{119:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return d}));var o=n(0),a=n.n(o);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=a.a.createContext({}),l=function(e){var t=a.a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=l(e.components);return a.a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},b=a.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=l(n),b=o,d=u["".concat(s,".").concat(b)]||u[b]||m[b]||r;return n?a.a.createElement(d,i(i({ref:t},c),{},{components:n})):a.a.createElement(d,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,s=new Array(r);s[0]=b;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:o,s[1]=i;for(var c=2;c=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var c=r.a.createContext({}),l=function(e){var t=r.a.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=l(e.components);return r.a.createElement(c.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},b=r.a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,s=e.originalType,a=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),u=l(n),b=o,d=u["".concat(a,".").concat(b)]||u[b]||m[b]||s;return n?r.a.createElement(d,i(i({ref:t},c),{},{components:n})):r.a.createElement(d,i({ref:t},c))}));function d(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var s=n.length,a=new Array(s);a[0]=b;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:o,a[1]=i;for(var c=2;c=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=r.a.createContext({}),u=function(e){var t=r.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=u(e.components);return r.a.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),p=u(n),d=a,b=p["".concat(c,".").concat(d)]||p[d]||m[d]||o;return n?r.a.createElement(b,l(l({ref:t},s),{},{components:n})):r.a.createElement(b,l({ref:t},s))}));function b(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=d;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var s=2;s{const n=document.createElement("textarea"),a=document.activeElement;n.value=e,n.setAttribute("readonly",""),n.style.contain="strict",n.style.position="absolute",n.style.left="-9999px",n.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let c=!1;try{c=document.execCommand("copy")}catch(l){}return n.remove(),o&&(r.removeAllRanges(),r.addRange(o)),a&&a.focus(),c};e.exports=a,e.exports.default=a},133:function(e,t){function n(e){let t,n=[];for(let a of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(a))n.push(parseInt(a,10));else if(t=a.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,a,r,o]=t;if(a&&o){a=parseInt(a),o=parseInt(o);const e=a0&&e[n-1]===t?e:e.concat(t)},f=function(e,t){var n=e.plain,a=Object.create(null),r=e.styles.reduce((function(e,n){var a=n.languages,r=n.style;return a&&!a.includes(t)||n.types.forEach((function(t){var n=p({},e[t],r);e[t]=n})),e}),a);return r.root=n,r.plain=p({},n,{backgroundColor:null}),r};function y(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===t.indexOf(a)&&(n[a]=e[a]);return n}var h=function(e){function t(){for(var t=this,n=[],a=arguments.length;a--;)n[a]=arguments[a];e.apply(this,n),u(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?f(e.theme,e.language):void 0;return t.themeDict=n})),u(this,"getLineProps",(function(e){var n=e.key,a=e.className,r=e.style,o=p({},y(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),c=t.getThemeDict(t.props);return void 0!==c&&(o.style=c.plain),void 0!==r&&(o.style=void 0!==o.style?p({},o.style,r):r),void 0!==n&&(o.key=n),a&&(o.className+=" "+a),o})),u(this,"getStyleForToken",(function(e){var n=e.types,a=e.empty,r=n.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===r&&"plain"===n[0])return a?{display:"inline-block"}:void 0;if(1===r&&!a)return o[n[0]];var c=a?{display:"inline-block"}:{},l=n.map((function(e){return o[e]}));return Object.assign.apply(Object,[c].concat(l))}})),u(this,"getTokenProps",(function(e){var n=e.key,a=e.className,r=e.style,o=e.token,c=p({},y(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==r&&(c.style=void 0!==c.style?p({},c.style,r):r),void 0!==n&&(c.key=n),a&&(c.className+=" "+a),c}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,a=e.code,r=e.children,o=this.getThemeDict(this.props),c=t.languages[n];return r({tokens:function(e){for(var t=[[]],n=[e],a=[0],r=[e.length],o=0,c=0,l=[],i=[l];c>-1;){for(;(o=a[c]++)0?u:["plain"],s=p):(u=b(u,p.type),p.alias&&(u=b(u,p.alias)),s=p.content),"string"==typeof s){var f=s.split(m),y=f.length;l.push({types:u,content:f[0]});for(var h=1;h0}))}c&&_.test(c)&&(v=c.match(_)[1]);var P=n&&n.replace(/language-/,"");!P&&i.defaultLanguage&&(P=i.defaultLanguage);var I=E.replace(/\n$/,"");if(0===h.length&&void 0!==P){for(var D,L="",B=function(e){switch(e){case"js":case"javascript":case"ts":case"typescript":return S(["js","jsBlock"]);case"jsx":case"tsx":return S(["js","jsBlock","jsx"]);case"html":return S(["js","jsBlock","html"]);case"python":case"py":return S(["python"]);default:return S()}}(P),M=E.replace(/\n$/,"").split("\n"),R=0;R=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var s=r.a.createContext({}),u=function(e){var t=r.a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=u(e.components);return r.a.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),p=u(n),d=a,b=p["".concat(c,".").concat(d)]||p[d]||m[d]||o;return n?r.a.createElement(b,l(l({ref:t},s),{},{components:n})):r.a.createElement(b,l({ref:t},s))}));function b(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,c=new Array(o);c[0]=d;var l={};for(var i in t)hasOwnProperty.call(t,i)&&(l[i]=t[i]);l.originalType=e,l.mdxType="string"==typeof e?e:a,c[1]=l;for(var s=2;s{const n=document.createElement("textarea"),a=document.activeElement;n.value=e,n.setAttribute("readonly",""),n.style.contain="strict",n.style.position="absolute",n.style.left="-9999px",n.style.fontSize="12pt";const r=document.getSelection();let o=!1;r.rangeCount>0&&(o=r.getRangeAt(0)),t.append(n),n.select(),n.selectionStart=0,n.selectionEnd=e.length;let c=!1;try{c=document.execCommand("copy")}catch(l){}return n.remove(),o&&(r.removeAllRanges(),r.addRange(o)),a&&a.focus(),c};e.exports=a,e.exports.default=a},133:function(e,t){function n(e){let t,n=[];for(let a of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(a))n.push(parseInt(a,10));else if(t=a.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,a,r,o]=t;if(a&&o){a=parseInt(a),o=parseInt(o);const e=a0&&e[n-1]===t?e:e.concat(t)},f=function(e,t){var n=e.plain,a=Object.create(null),r=e.styles.reduce((function(e,n){var a=n.languages,r=n.style;return a&&!a.includes(t)||n.types.forEach((function(t){var n=p({},e[t],r);e[t]=n})),e}),a);return r.root=n,r.plain=p({},n,{backgroundColor:null}),r};function y(e,t){var n={};for(var a in e)Object.prototype.hasOwnProperty.call(e,a)&&-1===t.indexOf(a)&&(n[a]=e[a]);return n}var h=function(e){function t(){for(var t=this,n=[],a=arguments.length;a--;)n[a]=arguments[a];e.apply(this,n),u(this,"getThemeDict",(function(e){if(void 0!==t.themeDict&&e.theme===t.prevTheme&&e.language===t.prevLanguage)return t.themeDict;t.prevTheme=e.theme,t.prevLanguage=e.language;var n=e.theme?f(e.theme,e.language):void 0;return t.themeDict=n})),u(this,"getLineProps",(function(e){var n=e.key,a=e.className,r=e.style,o=p({},y(e,["key","className","style","line"]),{className:"token-line",style:void 0,key:void 0}),c=t.getThemeDict(t.props);return void 0!==c&&(o.style=c.plain),void 0!==r&&(o.style=void 0!==o.style?p({},o.style,r):r),void 0!==n&&(o.key=n),a&&(o.className+=" "+a),o})),u(this,"getStyleForToken",(function(e){var n=e.types,a=e.empty,r=n.length,o=t.getThemeDict(t.props);if(void 0!==o){if(1===r&&"plain"===n[0])return a?{display:"inline-block"}:void 0;if(1===r&&!a)return o[n[0]];var c=a?{display:"inline-block"}:{},l=n.map((function(e){return o[e]}));return Object.assign.apply(Object,[c].concat(l))}})),u(this,"getTokenProps",(function(e){var n=e.key,a=e.className,r=e.style,o=e.token,c=p({},y(e,["key","className","style","token"]),{className:"token "+o.types.join(" "),children:o.content,style:t.getStyleForToken(o),key:void 0});return void 0!==r&&(c.style=void 0!==c.style?p({},c.style,r):r),void 0!==n&&(c.key=n),a&&(c.className+=" "+a),c}))}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.render=function(){var e=this.props,t=e.Prism,n=e.language,a=e.code,r=e.children,o=this.getThemeDict(this.props),c=t.languages[n];return r({tokens:function(e){for(var t=[[]],n=[e],a=[0],r=[e.length],o=0,c=0,l=[],i=[l];c>-1;){for(;(o=a[c]++)0?u:["plain"],s=p):(u=b(u,p.type),p.alias&&(u=b(u,p.alias)),s=p.content),"string"==typeof s){var f=s.split(m),y=f.length;l.push({types:u,content:f[0]});for(var h=1;h0}))}c&&S.test(c)&&(j=c.match(S)[1]);var _=n&&n.replace(/language-/,"");!_&&i.defaultLanguage&&(_=i.defaultLanguage);var I=E.replace(/\n$/,"");if(0===g.length&&void 0!==_){for(var D,L="",B=function(e){switch(e){case"js":case"javascript":case"ts":case"typescript":return T(["js","jsBlock"]);case"jsx":case"tsx":return T(["js","jsBlock","jsx"]);case"html":return T(["js","jsBlock","html"]);case"python":case"py":return T(["python"]);default:return T()}}(_),M=E.replace(/\n$/,"").split("\n"),R=0;R=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=a.a.createContext({}),b=function(e){var t=a.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=b(e.components);return a.a.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,l=p(e,["components","mdxType","originalType","parentName"]),s=b(n),d=r,m=s["".concat(c,".").concat(d)]||s[d]||u[d]||o;return n?a.a.createElement(m,i(i({ref:t},l),{},{components:n})):a.a.createElement(m,i({ref:t},l))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,c=new Array(o);c[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:r,c[1]=i;for(var l=2;l PB}\n")),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Remove")," this line:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},"PB.protobufSettings\n")),Object(o.b)("p",null,"If you set up ",Object(o.b)("inlineCode",{parentName:"p"},"protoc-jar"),", you can also ",Object(o.b)("strong",{parentName:"p"},"remove")," this setting, since this\nis the default:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},'PB.runProtoc in PB.protobufConfig := (args =>\n com.github.os72.protocjar.Protoc.runProtoc("-v300" +: args.toArray))\n')),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Add")," a value to ",Object(o.b)("inlineCode",{parentName:"p"},"gen.targets"),":"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},"Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("p",null,"If you need Java Conversions, flat packages, etc see\n",Object(o.b)("a",{parentName:"p",href:"/docs/sbt-settings"},"ScalaPB SBT Settings"),"."),Object(o.b)("p",null,"If you are using files like ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.proto")," and Google's well-known proto\nchange the library dependency from:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},'"com.trueaccord.scalapb" %% "scalapb-runtime" % "0.11.1" % PB.protobufConfig\n')),Object(o.b)("p",null,"to:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre"},'"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/5ee2bf2d.6801c681.js b/5ee2bf2d.6801c681.js deleted file mode 100644 index eae457efa..000000000 --- a/5ee2bf2d.6801c681.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{119:function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return m}));var r=n(0),a=n.n(r);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=a.a.createContext({}),b=function(e){var t=a.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},s=function(e){var t=b(e.components);return a.a.createElement(l.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},d=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,l=p(e,["components","mdxType","originalType","parentName"]),s=b(n),d=r,m=s["".concat(c,".").concat(d)]||s[d]||u[d]||o;return n?a.a.createElement(m,i(i({ref:t},l),{},{components:n})):a.a.createElement(m,i({ref:t},l))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,c=new Array(o);c[0]=d;var i={};for(var p in t)hasOwnProperty.call(t,p)&&(i[p]=t[p]);i.originalType=e,i.mdxType="string"==typeof e?e:r,c[1]=i;for(var l=2;l PB}\n")),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Remove")," this line:"),Object(o.b)("pre",null,Object(o.b)("code",Object(r.a)({parentName:"pre"},{}),"PB.protobufSettings\n")),Object(o.b)("p",null,"If you set up ",Object(o.b)("inlineCode",{parentName:"p"},"protoc-jar"),", you can also ",Object(o.b)("strong",{parentName:"p"},"remove")," this setting, since this\nis the default:"),Object(o.b)("pre",null,Object(o.b)("code",Object(r.a)({parentName:"pre"},{}),'PB.runProtoc in PB.protobufConfig := (args =>\n com.github.os72.protocjar.Protoc.runProtoc("-v300" +: args.toArray))\n')),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},"Add")," a value to ",Object(o.b)("inlineCode",{parentName:"p"},"gen.targets"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(r.a)({parentName:"pre"},{}),"Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("p",null,"If you need Java Conversions, flat packages, etc see\n",Object(o.b)("a",Object(r.a)({parentName:"p"},{href:"/docs/sbt-settings"}),"ScalaPB SBT Settings"),"."),Object(o.b)("p",null,"If you are using files like ",Object(o.b)("inlineCode",{parentName:"p"},"scalapb.proto")," and Google's well-known proto\nchange the library dependency from:"),Object(o.b)("pre",null,Object(o.b)("code",Object(r.a)({parentName:"pre"},{}),'"com.trueaccord.scalapb" %% "scalapb-runtime" % "0.11.1" % PB.protobufConfig\n')),Object(o.b)("p",null,"to:"),Object(o.b)("pre",null,Object(o.b)("code",Object(r.a)({parentName:"pre"},{}),'"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/63f1a026.a4a1f87b.js b/63f1a026.a4a1f87b.js deleted file mode 100644 index c812c1380..000000000 --- a/63f1a026.a4a1f87b.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),o=t.n(a);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function s(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=o.a.createContext({}),c=function(e){var n=o.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},d=function(e){var n=c(e.components);return o.a.createElement(p.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},u=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,r=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=c(t),u=a,m=d["".concat(r,".").concat(u)]||d[u]||b[u]||i;return t?o.a.createElement(m,s(s({ref:n},p),{},{components:t})):o.a.createElement(m,s({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,r=new Array(i);r[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,r[1]=s;for(var p=2;p println("Mobile!")\n case _ => println("Not mobile!")\n}\n')),Object(i.b)("h2",{id:"nested-messages"},"Nested messages"),Object(i.b)("p",null,"Nested messages appear as case classes inside the companion object of\nthe containing message."),Object(i.b)("h2",{id:"serialization"},"Serialization"),Object(i.b)("p",null,"Each message case class extends a base trait called ",Object(i.b)("inlineCode",{parentName:"p"},"GeneratedMessage")," which provides\nmethods that help serialize a message:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def toByteArray: Array[Byte]"),": serializes the message and return a byte array containing its raw bytes."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def writeTo(output: OutputStream): Unit"),": serializes the message and writes it to an ",Object(i.b)("inlineCode",{parentName:"li"},"OutputStream"),".")),Object(i.b)("h2",{id:"parsing"},"Parsing"),Object(i.b)("p",null,"The companion object of each message extends a base trait called ",Object(i.b)("inlineCode",{parentName:"p"},"GeneratedMessageCompanion[A]")," where ",Object(i.b)("inlineCode",{parentName:"p"},"A")," is the type of the message. It provides many\nuseful methods that helps dealing with a message in a generic way, however the primary use is parsing:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def parseFrom(input: InputStream): A"),": reads and parses a message from an ",Object(i.b)("inlineCode",{parentName:"li"},"InputStream"),"."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def parseFrom(s: Array[Byte]): A"),": parses a message from the given byte array.")),Object(i.b)("h2",{id:"parsing-from-an-input-stream"},"Parsing from an input stream"),Object(i.b)("p",null,"The following example code loads binary data from a file and parses it as an ",Object(i.b)("inlineCode",{parentName:"p"},"AddressBook"),". If the file doesn't exist it returns an empty ",Object(i.b)("inlineCode",{parentName:"p"},"AddressBook"),":"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),'def readFromFile(): AddressBook =\n Using(new FileInputStream("addressbook.pb")) { fileInputStream =>\n AddressBook.parseFrom(fileInputStream)\n }.recover {\n case _: FileNotFoundException =>\n println("No address book found. Will create a new file.")\n AddressBook()\n }.get\n')),Object(i.b)("h2",{id:"adding-new-person"},"Adding new person"),Object(i.b)("p",null,"The following code prompts the user to enter a person's data. It then loads\nthe address book from a file, adds the new person to the list, and saves it again:"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),'def personFromStdin(): Person = {\n print("Enter person ID (int): ")\n val id = StdIn.readInt()\n print("Enter name: ")\n val name = StdIn.readLine()\n print("Enter email address (blank for none): ")\n val email = StdIn.readLine()\n\n def getPhone(): Option[Person.PhoneNumber] = {\n print("Enter a phone number (or leave blank to finish): ")\n val number = StdIn.readLine()\n if (number.nonEmpty) {\n print("Is this a mobile, home, or work phone [mobile, home, work] ? ")\n val typ = StdIn.readLine() match {\n case "mobile" => Some(Person.PhoneType.MOBILE)\n case "home" => Some(Person.PhoneType.HOME)\n case "work" => Some(Person.PhoneType.WORK)\n case _ =>\n println("Unknown phone type. Leaving as None.")\n None\n }\n Some(Person.PhoneNumber(number = number, `type` = typ))\n } else None\n }\n\n // Keep prompting for phone numbers until None is returned.\n val phones =\n Iterator\n .continually(getPhone())\n .takeWhile(_.nonEmpty)\n .flatten\n .toSeq\n\n Person(\n id = id,\n name = name,\n email = if (email.nonEmpty) Some(email) else None,\n phones = phones\n )\n}\n\ndef addPerson(): Unit = {\n val newPerson = personFromStdin()\n val addressBook = readFromFile()\n // Append the new person to the people list field\n val updated = addressBook.update(\n _.people :+= newPerson\n )\n Using(new FileOutputStream("addressbook.pb")) { output =>\n updated.writeTo(output)\n }\n}\n')),Object(i.b)("h2",{id:"running-the-example"},"Running the example"),Object(i.b)("p",null,"In sbt, type ",Object(i.b)("inlineCode",{parentName:"p"},"run")),Object(i.b)("blockquote",null,Object(i.b)("p",{parentName:"blockquote"},'This document, "Protocol Buffer Tutorial: Scala" is a modification of ',Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://developers.google.com/protocol-buffers/docs/javatutorial"}),'"Protocol Buffer Basics: Java"'),", which is a work created and ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://developers.google.com/terms/site-policies"}),"shared by Google")," and used according to terms described in the ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://creativecommons.org/licenses/by/4.0/"}),"Creative Commons 4.0 Attribution License"),".")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/63f1a026.a79c8deb.js b/63f1a026.a79c8deb.js new file mode 100644 index 000000000..760db5127 --- /dev/null +++ b/63f1a026.a79c8deb.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{119:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),o=t.n(a);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function s(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=o.a.createContext({}),c=function(e){var n=o.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},d=function(e){var n=c(e.components);return o.a.createElement(p.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},u=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,r=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),d=c(t),u=a,m=d["".concat(r,".").concat(u)]||d[u]||b[u]||i;return t?o.a.createElement(m,s(s({ref:n},p),{},{components:t})):o.a.createElement(m,s({ref:n},p))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,r=new Array(i);r[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,r[1]=s;for(var p=2;p println("Mobile!")\n case _ => println("Not mobile!")\n}\n')),Object(i.b)("h2",{id:"nested-messages"},"Nested messages"),Object(i.b)("p",null,"Nested messages appear as case classes inside the companion object of\nthe containing message."),Object(i.b)("h2",{id:"serialization"},"Serialization"),Object(i.b)("p",null,"Each message case class extends a base trait called ",Object(i.b)("inlineCode",{parentName:"p"},"GeneratedMessage")," which provides\nmethods that help serialize a message:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def toByteArray: Array[Byte]"),": serializes the message and return a byte array containing its raw bytes."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def writeTo(output: OutputStream): Unit"),": serializes the message and writes it to an ",Object(i.b)("inlineCode",{parentName:"li"},"OutputStream"),".")),Object(i.b)("h2",{id:"parsing"},"Parsing"),Object(i.b)("p",null,"The companion object of each message extends a base trait called ",Object(i.b)("inlineCode",{parentName:"p"},"GeneratedMessageCompanion[A]")," where ",Object(i.b)("inlineCode",{parentName:"p"},"A")," is the type of the message. It provides many\nuseful methods that helps dealing with a message in a generic way, however the primary use is parsing:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def parseFrom(input: InputStream): A"),": reads and parses a message from an ",Object(i.b)("inlineCode",{parentName:"li"},"InputStream"),"."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"def parseFrom(s: Array[Byte]): A"),": parses a message from the given byte array.")),Object(i.b)("h2",{id:"parsing-from-an-input-stream"},"Parsing from an input stream"),Object(i.b)("p",null,"The following example code loads binary data from a file and parses it as an ",Object(i.b)("inlineCode",{parentName:"p"},"AddressBook"),". If the file doesn't exist it returns an empty ",Object(i.b)("inlineCode",{parentName:"p"},"AddressBook"),":"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},'def readFromFile(): AddressBook =\n Using(new FileInputStream("addressbook.pb")) { fileInputStream =>\n AddressBook.parseFrom(fileInputStream)\n }.recover {\n case _: FileNotFoundException =>\n println("No address book found. Will create a new file.")\n AddressBook()\n }.get\n')),Object(i.b)("h2",{id:"adding-new-person"},"Adding new person"),Object(i.b)("p",null,"The following code prompts the user to enter a person's data. It then loads\nthe address book from a file, adds the new person to the list, and saves it again:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-scala"},'def personFromStdin(): Person = {\n print("Enter person ID (int): ")\n val id = StdIn.readInt()\n print("Enter name: ")\n val name = StdIn.readLine()\n print("Enter email address (blank for none): ")\n val email = StdIn.readLine()\n\n def getPhone(): Option[Person.PhoneNumber] = {\n print("Enter a phone number (or leave blank to finish): ")\n val number = StdIn.readLine()\n if (number.nonEmpty) {\n print("Is this a mobile, home, or work phone [mobile, home, work] ? ")\n val typ = StdIn.readLine() match {\n case "mobile" => Some(Person.PhoneType.MOBILE)\n case "home" => Some(Person.PhoneType.HOME)\n case "work" => Some(Person.PhoneType.WORK)\n case _ =>\n println("Unknown phone type. Leaving as None.")\n None\n }\n Some(Person.PhoneNumber(number = number, `type` = typ))\n } else None\n }\n\n // Keep prompting for phone numbers until None is returned.\n val phones =\n Iterator\n .continually(getPhone())\n .takeWhile(_.nonEmpty)\n .flatten\n .toSeq\n\n Person(\n id = id,\n name = name,\n email = if (email.nonEmpty) Some(email) else None,\n phones = phones\n )\n}\n\ndef addPerson(): Unit = {\n val newPerson = personFromStdin()\n val addressBook = readFromFile()\n // Append the new person to the people list field\n val updated = addressBook.update(\n _.people :+= newPerson\n )\n Using(new FileOutputStream("addressbook.pb")) { output =>\n updated.writeTo(output)\n }\n}\n')),Object(i.b)("h2",{id:"running-the-example"},"Running the example"),Object(i.b)("p",null,"In sbt, type ",Object(i.b)("inlineCode",{parentName:"p"},"run")),Object(i.b)("blockquote",null,Object(i.b)("p",{parentName:"blockquote"},'This document, "Protocol Buffer Tutorial: Scala" is a modification of ',Object(i.b)("a",{parentName:"p",href:"https://developers.google.com/protocol-buffers/docs/javatutorial"},'"Protocol Buffer Basics: Java"'),", which is a work created and ",Object(i.b)("a",{parentName:"p",href:"https://developers.google.com/terms/site-policies"},"shared by Google")," and used according to terms described in the ",Object(i.b)("a",{parentName:"p",href:"https://creativecommons.org/licenses/by/4.0/"},"Creative Commons 4.0 Attribution License"),".")))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/6875c492.d2810576.js b/6875c492.c05025fc.js similarity index 100% rename from 6875c492.d2810576.js rename to 6875c492.c05025fc.js diff --git a/6a102a11.51224351.js b/6a102a11.51224351.js new file mode 100644 index 000000000..7cb9742a0 --- /dev/null +++ b/6a102a11.51224351.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{119:function(e,o,t){"use strict";t.d(o,"a",(function(){return m})),t.d(o,"b",(function(){return d}));var a=t(0),r=t.n(a);function n(e,o,t){return o in e?Object.defineProperty(e,o,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[o]=t,e}function c(e,o){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);o&&(a=a.filter((function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable}))),t.push.apply(t,a)}return t}function p(e){for(var o=1;o=0||(r[t]=e[t]);return r}(e,o);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),b=function(e){var o=r.a.useContext(s),t=o;return e&&(t="function"==typeof e?e(o):p(p({},o),e)),t},m=function(e){var o=b(e.components);return r.a.createElement(s.Provider,{value:o},e.children)},i={inlineCode:"code",wrapper:function(e){var o=e.children;return r.a.createElement(r.a.Fragment,{},o)}},u=r.a.forwardRef((function(e,o){var t=e.components,a=e.mdxType,n=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=b(t),u=a,d=m["".concat(c,".").concat(u)]||m[u]||i[u]||n;return t?r.a.createElement(d,p(p({ref:o},s),{},{components:t})):r.a.createElement(d,p({ref:o},s))}));function d(e,o){var t=arguments,a=o&&o.mdxType;if("string"==typeof e||a){var n=t.length,c=new Array(n);c[0]=u;var p={};for(var l in o)hasOwnProperty.call(o,l)&&(p[l]=o[l]);p.originalType=e,p.mdxType="string"==typeof e?e:a,c[1]=p;for(var s=2;s=0||(r[t]=e[t]);return r}(e,o);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),b=function(e){var o=r.a.useContext(s),t=o;return e&&(t="function"==typeof e?e(o):p(p({},o),e)),t},m=function(e){var o=b(e.components);return r.a.createElement(s.Provider,{value:o},e.children)},i={inlineCode:"code",wrapper:function(e){var o=e.children;return r.a.createElement(r.a.Fragment,{},o)}},u=r.a.forwardRef((function(e,o){var t=e.components,a=e.mdxType,n=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),m=b(t),u=a,d=m["".concat(c,".").concat(u)]||m[u]||i[u]||n;return t?r.a.createElement(d,p(p({ref:o},s),{},{components:t})):r.a.createElement(d,p({ref:o},s))}));function d(e,o){var t=arguments,a=o&&o.mdxType;if("string"==typeof e||a){var n=t.length,c=new Array(n);c[0]=u;var p={};for(var l in o)hasOwnProperty.call(o,l)&&(p[l]=o[l]);p.originalType=e,p.mdxType="string"==typeof e?e:a,c[1]=p;for(var s=2;s=0||(o[t]=e[t]);return o}(e,a);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=o.a.createContext({}),s=function(e){var a=o.a.useContext(p),t=a;return e&&(t="function"==typeof e?e(a):i(i({},a),e)),t},b=function(e){var a=s(e.components);return o.a.createElement(p.Provider,{value:a},e.children)},u={inlineCode:"code",wrapper:function(e){var a=e.children;return o.a.createElement(o.a.Fragment,{},a)}},d=o.a.forwardRef((function(e,a){var t=e.components,n=e.mdxType,r=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),b=s(t),d=n,m=b["".concat(c,".").concat(d)]||b[d]||u[d]||r;return t?o.a.createElement(m,i(i({ref:a},p),{},{components:t})):o.a.createElement(m,i({ref:a},p))}));function m(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var r=t.length,c=new Array(r);c[0]=d;var i={};for(var l in a)hasOwnProperty.call(a,l)&&(i[l]=a[l]);i.originalType=e,i.mdxType="string"==typeof e?e:n,c[1]=i;for(var p=2;p=0||(o[t]=e[t]);return o}(e,a);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var p=o.a.createContext({}),s=function(e){var a=o.a.useContext(p),t=a;return e&&(t="function"==typeof e?e(a):i(i({},a),e)),t},b=function(e){var a=s(e.components);return o.a.createElement(p.Provider,{value:a},e.children)},u={inlineCode:"code",wrapper:function(e){var a=e.children;return o.a.createElement(o.a.Fragment,{},a)}},d=o.a.forwardRef((function(e,a){var t=e.components,n=e.mdxType,r=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),b=s(t),d=n,m=b["".concat(c,".").concat(d)]||b[d]||u[d]||r;return t?o.a.createElement(m,i(i({ref:a},p),{},{components:t})):o.a.createElement(m,i({ref:a},p))}));function m(e,a){var t=arguments,n=a&&a.mdxType;if("string"==typeof e||n){var r=t.length,c=new Array(r);c[0]=d;var i={};for(var l in a)hasOwnProperty.call(a,l)&&(i[l]=a[l]);i.originalType=e,i.mdxType="string"==typeof e?e:n,c[1]=i;for(var p=2;p=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=o.a.createContext({}),s=function(e){var t=o.a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},p=function(e){var t=s(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),p=s(r),f=n,d=p["".concat(i,".").concat(f)]||p[f]||m[f]||a;return r?o.a.createElement(d,u(u({ref:t},l),{},{components:r})):o.a.createElement(d,u({ref:t},l))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:n,i[1]=u;for(var l=2;l=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=o.a.createContext({}),s=function(e){var t=o.a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},p=function(e){var t=s(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),p=s(r),f=n,d=p["".concat(i,".").concat(f)]||p[f]||m[f]||a;return r?o.a.createElement(d,u(u({ref:t},l),{},{components:r})):o.a.createElement(d,u({ref:t},l))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:n,i[1]=u;for(var l=2;l=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var s=a.a.createContext({}),l=function(e){var t=a.a.useContext(s),o=t;return e&&(o="function"==typeof e?e(t):p(p({},t),e)),o},b=function(e){var t=l(e.components);return a.a.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},m=a.a.forwardRef((function(e,t){var o=e.components,r=e.mdxType,n=e.originalType,i=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),b=l(o),m=r,u=b["".concat(i,".").concat(m)]||b[m]||d[m]||n;return o?a.a.createElement(u,p(p({ref:t},s),{},{components:o})):a.a.createElement(u,p({ref:t},s))}));function u(e,t){var o=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var n=o.length,i=new Array(n);i[0]=m;var p={};for(var c in t)hasOwnProperty.call(t,c)&&(p[c]=t[c]);p.originalType=e,p.mdxType="string"==typeof e?e:r,i[1]=p;for(var s=2;s (Compile / sourceManaged).value\n )\n )\n\n// myProject contains its own protos which rely on protos from externalProtos\nlazy val myProject = (project in file("my-project"))\n .dependsOn(externalProtos)\n .settings(\n Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value\n )\n )\n')),Object(n.b)("p",null,"See ",Object(n.b)("a",Object(r.a)({parentName:"p"},{href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/multi-with-external-jar"}),"full example here"),"."))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/91ea4504.dd0df415.js b/91ea4504.dd0df415.js new file mode 100644 index 000000000..ce584f793 --- /dev/null +++ b/91ea4504.dd0df415.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{119:function(e,t,o){"use strict";o.d(t,"a",(function(){return b})),o.d(t,"b",(function(){return u}));var r=o(0),a=o.n(r);function n(e,t,o){return t in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function i(e,t){var o=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),o.push.apply(o,r)}return o}function p(e){for(var t=1;t=0||(a[o]=e[o]);return a}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,o)&&(a[o]=e[o])}return a}var c=a.a.createContext({}),l=function(e){var t=a.a.useContext(c),o=t;return e&&(o="function"==typeof e?e(t):p(p({},t),e)),o},b=function(e){var t=l(e.components);return a.a.createElement(c.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},m=a.a.forwardRef((function(e,t){var o=e.components,r=e.mdxType,n=e.originalType,i=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),b=l(o),m=r,u=b["".concat(i,".").concat(m)]||b[m]||d[m]||n;return o?a.a.createElement(u,p(p({ref:t},c),{},{components:o})):a.a.createElement(u,p({ref:t},c))}));function u(e,t){var o=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var n=o.length,i=new Array(n);i[0]=m;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p.mdxType="string"==typeof e?e:r,i[1]=p;for(var c=2;c (Compile / sourceManaged).value\n )\n )\n\n// myProject contains its own protos which rely on protos from externalProtos\nlazy val myProject = (project in file("my-project"))\n .dependsOn(externalProtos)\n .settings(\n Compile / PB.targets := Seq(\n scalapb.gen() -> (Compile / sourceManaged).value\n )\n )\n')),Object(n.b)("p",null,"See ",Object(n.b)("a",{parentName:"p",href:"https://github.com/thesamet/sbt-protoc/tree/master/examples/multi-with-external-jar"},"full example here"),"."))}b.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/935f2afb.5e094e5e.js b/935f2afb.5b2cd0a8.js similarity index 100% rename from 935f2afb.5e094e5e.js rename to 935f2afb.5b2cd0a8.js diff --git a/9dcf530e.30e5d8a8.js b/9dcf530e.30e5d8a8.js deleted file mode 100644 index e115db35c..000000000 --- a/9dcf530e.30e5d8a8.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{119:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return m}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var b=r.a.createContext({}),s=function(e){var t=r.a.useContext(b),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return r.a.createElement(b.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},u=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,b=c(e,["components","mdxType","originalType","parentName"]),p=s(n),u=a,m=p["".concat(i,".").concat(u)]||p[u]||d[u]||o;return n?r.a.createElement(m,l(l({ref:t},b),{},{components:n})):r.a.createElement(m,l({ref:t},b))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var b=2;b (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(o.b)("p",null,"Running the ",Object(o.b)("inlineCode",{parentName:"p"},"compile")," command in sbt will generate Scala sources from\nyour protos and compile them. If you just want to generate Scala sources for your protocol buffers without compiling them, run ",Object(o.b)("inlineCode",{parentName:"p"},"protocGenerate"),"."),Object(o.b)("p",null,"Additionally, if you need ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"/docs/customizations"}),"customizations")," from\nscalapb/scalapb.proto or anything from ",Object(o.b)("inlineCode",{parentName:"p"},"google/protobuf/*.proto"),", add the\nfollowing to your ",Object(o.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),'libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')),Object(o.b)("h2",{id:"defaults"},"Defaults"),Object(o.b)("p",null,"The plugin assumes your ",Object(o.b)("inlineCode",{parentName:"p"},"proto")," files are under ",Object(o.b)("inlineCode",{parentName:"p"},"src/main/protobuf"),",\nhowever this is configurable using the ",Object(o.b)("inlineCode",{parentName:"p"},"Compile / PB.protoSources")," setting."),Object(o.b)("p",null,"By default, ",Object(o.b)("inlineCode",{parentName:"p"},"sbt-protoc")," invokes ",Object(o.b)("inlineCode",{parentName:"p"},"protoc")," 3.x that is shipped with ",Object(o.b)("inlineCode",{parentName:"p"},"protoc-jar"),".\nIf you would like to run a different version of ",Object(o.b)("inlineCode",{parentName:"p"},"protoc"),":"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),'PB.protocVersion := "-v3.11.4"\n')),Object(o.b)("p",null,"See all available options in ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://github.com/thesamet/sbt-protoc"}),"sbt-protoc documentation")),Object(o.b)("h2",{id:"java-conversions"},"Java Conversions"),Object(o.b)("p",null,"To enable Java conversions add the following to your build.sbt:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),"Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value,\n scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("h2",{id:"grpc"},"gRPC"),Object(o.b)("p",null,"Generating gRPC stubs for services is enabled by default. To disable:"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),"Compile / PB.targets := Seq(\n scalapb.gen(grpc=false) -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("h2",{id:"additional-options-to-the-generator"},"Additional options to the generator"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-scala"}),"scalapb.gen(\n flatPackage: Boolean = false,\n javaConversions: Boolean = false,\n grpc: Boolean = true,\n singleLineToProtoString: Boolean = false,\n asciiFormatToString: Boolean = false,\n lenses: Boolean = true,\n retainSourceCodeInfo: Boolean = false\n)\n")),Object(o.b)("table",null,Object(o.b)("thead",{parentName:"table"},Object(o.b)("tr",{parentName:"thead"},Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Option"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"scalapbc"),Object(o.b)("th",Object(a.a)({parentName:"tr"},{align:null}),"Description"))),Object(o.b)("tbody",{parentName:"table"},Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"flatPackage")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"flat_package")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"When set, ScalaPB will not append the protofile base name to the package name.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"javaConversions")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"java_conversions")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Generates in the companion object two functions, ",Object(o.b)("inlineCode",{parentName:"td"},"toJavaProto")," and ",Object(o.b)("inlineCode",{parentName:"td"},"fromJavaProto")," that convert between the Scala case class and the Java protobufs. For the generated code to compile, the Java protobuf code need to be also generated or available as a library dependency.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"grpc")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"grpc")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Generates gRPC code for services. Default is ",Object(o.b)("inlineCode",{parentName:"td"},"true")," in ",Object(o.b)("inlineCode",{parentName:"td"},"scalapb.gen"),", and need to be explicitly specified in ",Object(o.b)("inlineCode",{parentName:"td"},"scalapbc"),".")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"singleLineToProtoString")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"single_line_to_proto_string")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"By default, ScalaPB generates a ",Object(o.b)("inlineCode",{parentName:"td"},"toProtoString()")," method that renders the message as a multi-line format (using ",Object(o.b)("inlineCode",{parentName:"td"},"TextFormat.printToUnicodeString"),"). If set, ScalaPB generates ",Object(o.b)("inlineCode",{parentName:"td"},"toString()")," methods that use the single line format.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"asciiFormatToString")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"ascii_format_to_string")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Setting this to true, overrides ",Object(o.b)("inlineCode",{parentName:"td"},"toString")," to return a standard ASCII representation of the message by calling ",Object(o.b)("inlineCode",{parentName:"td"},"toProtoString"),".")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"lenses")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"no_lenses")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"By default, ScalaPB generates lenses for each message for easy updating. If you are not using this feature and would like to reduce code size or compilation time, you can set this to ",Object(o.b)("inlineCode",{parentName:"td"},"false")," and lenses will not be generated.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"retainSourceCodeInfo")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),Object(o.b)("inlineCode",{parentName:"td"},"retain_source_code_info")),Object(o.b)("td",Object(a.a)({parentName:"tr"},{align:null}),"Retain source code information (locations, comments) provided by protoc in the descriptors. Use the ",Object(o.b)("inlineCode",{parentName:"td"},"location")," accessor to get that information from a descriptor.")))))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/9dcf530e.e5b7c6fc.js b/9dcf530e.e5b7c6fc.js new file mode 100644 index 000000000..bc2879d79 --- /dev/null +++ b/9dcf530e.e5b7c6fc.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{119:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return m}));var a=n(0),r=n.n(a);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var b=r.a.createContext({}),s=function(e){var t=r.a.useContext(b),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},p=function(e){var t=s(e.components);return r.a.createElement(b.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},u=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,i=e.parentName,b=c(e,["components","mdxType","originalType","parentName"]),p=s(n),u=a,m=p["".concat(i,".").concat(u)]||p[u]||d[u]||o;return n?r.a.createElement(m,l(l({ref:t},b),{},{components:n})):r.a.createElement(m,l({ref:t},b))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=u;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var b=2;b (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(o.b)("p",null,"Running the ",Object(o.b)("inlineCode",{parentName:"p"},"compile")," command in sbt will generate Scala sources from\nyour protos and compile them. If you just want to generate Scala sources for your protocol buffers without compiling them, run ",Object(o.b)("inlineCode",{parentName:"p"},"protocGenerate"),"."),Object(o.b)("p",null,"Additionally, if you need ",Object(o.b)("a",{parentName:"p",href:"/docs/customizations"},"customizations")," from\nscalapb/scalapb.proto or anything from ",Object(o.b)("inlineCode",{parentName:"p"},"google/protobuf/*.proto"),", add the\nfollowing to your ",Object(o.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},'libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"\n')),Object(o.b)("h2",{id:"defaults"},"Defaults"),Object(o.b)("p",null,"The plugin assumes your ",Object(o.b)("inlineCode",{parentName:"p"},"proto")," files are under ",Object(o.b)("inlineCode",{parentName:"p"},"src/main/protobuf"),",\nhowever this is configurable using the ",Object(o.b)("inlineCode",{parentName:"p"},"Compile / PB.protoSources")," setting."),Object(o.b)("p",null,"By default, ",Object(o.b)("inlineCode",{parentName:"p"},"sbt-protoc")," invokes ",Object(o.b)("inlineCode",{parentName:"p"},"protoc")," 3.x that is shipped with ",Object(o.b)("inlineCode",{parentName:"p"},"protoc-jar"),".\nIf you would like to run a different version of ",Object(o.b)("inlineCode",{parentName:"p"},"protoc"),":"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},'PB.protocVersion := "-v3.11.4"\n')),Object(o.b)("p",null,"See all available options in ",Object(o.b)("a",{parentName:"p",href:"https://github.com/thesamet/sbt-protoc"},"sbt-protoc documentation")),Object(o.b)("h2",{id:"java-conversions"},"Java Conversions"),Object(o.b)("p",null,"To enable Java conversions add the following to your build.sbt:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value,\n scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("h2",{id:"grpc"},"gRPC"),Object(o.b)("p",null,"Generating gRPC stubs for services is enabled by default. To disable:"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"Compile / PB.targets := Seq(\n scalapb.gen(grpc=false) -> (Compile / sourceManaged).value\n)\n")),Object(o.b)("h2",{id:"additional-options-to-the-generator"},"Additional options to the generator"),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"scalapb.gen(\n flatPackage: Boolean = false,\n javaConversions: Boolean = false,\n grpc: Boolean = true,\n singleLineToProtoString: Boolean = false,\n asciiFormatToString: Boolean = false,\n lenses: Boolean = true,\n retainSourceCodeInfo: Boolean = false\n)\n")),Object(o.b)("table",null,Object(o.b)("thead",{parentName:"table"},Object(o.b)("tr",{parentName:"thead"},Object(o.b)("th",{parentName:"tr",align:null},"Option"),Object(o.b)("th",{parentName:"tr",align:null},"scalapbc"),Object(o.b)("th",{parentName:"tr",align:null},"Description"))),Object(o.b)("tbody",{parentName:"table"},Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"flatPackage")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"flat_package")),Object(o.b)("td",{parentName:"tr",align:null},"When set, ScalaPB will not append the protofile base name to the package name.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"javaConversions")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"java_conversions")),Object(o.b)("td",{parentName:"tr",align:null},"Generates in the companion object two functions, ",Object(o.b)("inlineCode",{parentName:"td"},"toJavaProto")," and ",Object(o.b)("inlineCode",{parentName:"td"},"fromJavaProto")," that convert between the Scala case class and the Java protobufs. For the generated code to compile, the Java protobuf code need to be also generated or available as a library dependency.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"grpc")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"grpc")),Object(o.b)("td",{parentName:"tr",align:null},"Generates gRPC code for services. Default is ",Object(o.b)("inlineCode",{parentName:"td"},"true")," in ",Object(o.b)("inlineCode",{parentName:"td"},"scalapb.gen"),", and need to be explicitly specified in ",Object(o.b)("inlineCode",{parentName:"td"},"scalapbc"),".")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"singleLineToProtoString")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"single_line_to_proto_string")),Object(o.b)("td",{parentName:"tr",align:null},"By default, ScalaPB generates a ",Object(o.b)("inlineCode",{parentName:"td"},"toProtoString()")," method that renders the message as a multi-line format (using ",Object(o.b)("inlineCode",{parentName:"td"},"TextFormat.printToUnicodeString"),"). If set, ScalaPB generates ",Object(o.b)("inlineCode",{parentName:"td"},"toString()")," methods that use the single line format.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"asciiFormatToString")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"ascii_format_to_string")),Object(o.b)("td",{parentName:"tr",align:null},"Setting this to true, overrides ",Object(o.b)("inlineCode",{parentName:"td"},"toString")," to return a standard ASCII representation of the message by calling ",Object(o.b)("inlineCode",{parentName:"td"},"toProtoString"),".")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"lenses")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"no_lenses")),Object(o.b)("td",{parentName:"tr",align:null},"By default, ScalaPB generates lenses for each message for easy updating. If you are not using this feature and would like to reduce code size or compilation time, you can set this to ",Object(o.b)("inlineCode",{parentName:"td"},"false")," and lenses will not be generated.")),Object(o.b)("tr",{parentName:"tbody"},Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"retainSourceCodeInfo")),Object(o.b)("td",{parentName:"tr",align:null},Object(o.b)("inlineCode",{parentName:"td"},"retain_source_code_info")),Object(o.b)("td",{parentName:"tr",align:null},"Retain source code information (locations, comments) provided by protoc in the descriptors. Use the ",Object(o.b)("inlineCode",{parentName:"td"},"location")," accessor to get that information from a descriptor.")))))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/a6aa9e1f.0848dbf3.js b/a6aa9e1f.8f1f5a6b.js similarity index 95% rename from a6aa9e1f.0848dbf3.js rename to a6aa9e1f.8f1f5a6b.js index 6dcb71c61..0f4e904be 100644 --- a/a6aa9e1f.0848dbf3.js +++ b/a6aa9e1f.8f1f5a6b.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{117:function(a,e,t){"use strict";t.r(e);var n=t(0),i=t.n(n),l=t(21),r=t(125),c=t(134),m=t(122);var s=function(a){var e=a.metadata,t=e.previousPage,n=e.nextPage;return i.a.createElement("nav",{className:"pagination-nav","aria-label":"Blog list page navigation"},i.a.createElement("div",{className:"pagination-nav__item"},t&&i.a.createElement(m.a,{className:"pagination-nav__link",to:t},i.a.createElement("div",{className:"pagination-nav__label"},"\xab Newer Entries"))),i.a.createElement("div",{className:"pagination-nav__item pagination-nav__item--next"},n&&i.a.createElement(m.a,{className:"pagination-nav__link",to:n},i.a.createElement("div",{className:"pagination-nav__label"},"Older Entries \xbb"))))},o=t(128);e.default=function(a){var e=a.metadata,t=a.items,n=a.sidebar,m=Object(l.default)().siteConfig.title,d=e.blogDescription,p=e.blogTitle,v="/"===e.permalink?m:p;return i.a.createElement(r.a,{title:v,description:d,wrapperClassName:"blog-wrapper"},i.a.createElement("div",{className:"container margin-vert--lg"},i.a.createElement("div",{className:"row"},i.a.createElement("div",{className:"col col--2"},i.a.createElement(o.a,{sidebar:n})),i.a.createElement("main",{className:"col col--8"},t.map((function(a){var e=a.content;return i.a.createElement(c.a,{key:e.metadata.permalink,frontMatter:e.frontMatter,metadata:e.metadata,truncated:e.metadata.truncated},i.a.createElement(e,null))})),i.a.createElement(s,{metadata:e})))))}}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{117:function(a,e,t){"use strict";t.r(e);var n=t(0),i=t.n(n),l=t(20),r=t(125),c=t(134),m=t(122);var s=function(a){var e=a.metadata,t=e.previousPage,n=e.nextPage;return i.a.createElement("nav",{className:"pagination-nav","aria-label":"Blog list page navigation"},i.a.createElement("div",{className:"pagination-nav__item"},t&&i.a.createElement(m.a,{className:"pagination-nav__link",to:t},i.a.createElement("div",{className:"pagination-nav__label"},"\xab Newer Entries"))),i.a.createElement("div",{className:"pagination-nav__item pagination-nav__item--next"},n&&i.a.createElement(m.a,{className:"pagination-nav__link",to:n},i.a.createElement("div",{className:"pagination-nav__label"},"Older Entries \xbb"))))},o=t(128);e.default=function(a){var e=a.metadata,t=a.items,n=a.sidebar,m=Object(l.default)().siteConfig.title,d=e.blogDescription,p=e.blogTitle,v="/"===e.permalink?m:p;return i.a.createElement(r.a,{title:v,description:d,wrapperClassName:"blog-wrapper"},i.a.createElement("div",{className:"container margin-vert--lg"},i.a.createElement("div",{className:"row"},i.a.createElement("div",{className:"col col--2"},i.a.createElement(o.a,{sidebar:n})),i.a.createElement("main",{className:"col col--8"},t.map((function(a){var e=a.content;return i.a.createElement(c.a,{key:e.metadata.permalink,frontMatter:e.frontMatter,metadata:e.metadata,truncated:e.metadata.truncated},i.a.createElement(e,null))})),i.a.createElement(s,{metadata:e})))))}}}]); \ No newline at end of file diff --git a/a7023ddc.400a3306.js b/a7023ddc.5979d515.js similarity index 100% rename from a7023ddc.400a3306.js rename to a7023ddc.5979d515.js diff --git a/a80da1cf.19728128.js b/a80da1cf.34d1a551.js similarity index 100% rename from a80da1cf.19728128.js rename to a80da1cf.34d1a551.js diff --git a/af172acd.8b232b46.js b/af172acd.8b232b46.js new file mode 100644 index 000000000..a61fa0b68 --- /dev/null +++ b/af172acd.8b232b46.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{102:function(e,t,r){"use strict";r.r(t),r.d(t,"frontMatter",(function(){return c})),r.d(t,"metadata",(function(){return u})),r.d(t,"toc",(function(){return i})),r.d(t,"default",(function(){return s}));var n=r(3),o=r(7),a=(r(0),r(119)),l=["components"],c={title:"Welcome",author:"Yangshun Tay",author_title:"Front End Engineer @ Facebook",author_url:"https://github.com/yangshun",author_image_url:"https://avatars0.githubusercontent.com/u/1315101?s=400&v=4",tags:["facebook","hello","docusaurus"]},u={permalink:"/blog/2019/05/30/welcome",source:"@site/blog/2019-05-30-welcome.md",description:"Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!",date:"2019-05-30T00:00:00.000Z",tags:[{label:"facebook",permalink:"/blog/tags/facebook"},{label:"hello",permalink:"/blog/tags/hello"},{label:"docusaurus",permalink:"/blog/tags/docusaurus"}],title:"Welcome",readingTime:.175,truncated:!1,nextItem:{title:"Hello",permalink:"/blog/2019/05/29/hello-world"}},i=[],p={toc:i};function s(e){var t=e.components,r=Object(o.a)(e,l);return Object(a.b)("wrapper",Object(n.a)({},p,r,{components:t,mdxType:"MDXLayout"}),Object(a.b)("p",null,"Blog features are powered by the blog plugin. Simply add files to the ",Object(a.b)("inlineCode",{parentName:"p"},"blog")," directory. It supports tags as well!"),Object(a.b)("p",null,"Delete the whole directory if you don't want the blog features. As simple as that!"))}s.isMDXComponent=!0},119:function(e,t,r){"use strict";r.d(t,"a",(function(){return s})),r.d(t,"b",(function(){return m}));var n=r(0),o=r.n(n);function a(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function l(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},i),{},{components:r})):o.a.createElement(m,c({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var i=o.a.createContext({}),p=function(e){var t=o.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(i.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,i=u(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},i),{},{components:r})):o.a.createElement(m,c({ref:t},i))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var u in t)hasOwnProperty.call(t,u)&&(c[u]=t[u]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var i=2;i (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(o.b)("h2",{id:"generated-code"},"Generated code"),Object(o.b)("p",null,"The generated code is designed to compile cleanly on all support versions of\nthe Scala compiler with the default compiler settings. It is known that currently\nthe generator will provide an error if ",Object(o.b)("inlineCode",{parentName:"p"},"-language:strictEquality")," is set."))}u.isMDXComponent=!0},119:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return m}));var r=n(0),a=n.n(r);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=a.a.createContext({}),s=function(e){var t=a.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=s(e.components);return a.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},b=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(n),b=r,m=u["".concat(c,".").concat(b)]||u[b]||d[b]||o;return n?a.a.createElement(m,i(i({ref:t},p),{},{components:n})):a.a.createElement(m,i({ref:t},p))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,c=new Array(o);c[0]=b;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:r,c[1]=i;for(var p=2;p (Compile / sourceManaged).value / "scalapb"\n)\n')),Object(o.b)("h2",{id:"generated-code"},"Generated code"),Object(o.b)("p",null,"The generated code is designed to compile cleanly on all support versions of\nthe Scala compiler with the default compiler settings. It is known that currently\nthe generator will provide an error if ",Object(o.b)("inlineCode",{parentName:"p"},"-language:strictEquality")," is set."))}s.isMDXComponent=!0},119:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return m}));var r=n(0),a=n.n(r);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var p=a.a.createContext({}),s=function(e){var t=a.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=s(e.components);return a.a.createElement(p.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.a.createElement(a.a.Fragment,{},t)}},b=a.a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=s(n),b=r,m=u["".concat(c,".").concat(b)]||u[b]||d[b]||o;return n?a.a.createElement(m,i(i({ref:t},p),{},{components:n})):a.a.createElement(m,i({ref:t},p))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,c=new Array(o);c[0]=b;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i.mdxType="string"==typeof e?e:r,c[1]=i;for(var p=2;p=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=o.a.createContext({}),s=function(e){var t=o.a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},p=function(e){var t=s(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),p=s(r),f=n,d=p["".concat(i,".").concat(f)]||p[f]||m[f]||a;return r?o.a.createElement(d,u(u({ref:t},l),{},{components:r})):o.a.createElement(d,u({ref:t},l))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:n,i[1]=u;for(var l=2;l=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=o.a.createContext({}),s=function(e){var t=o.a.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):u(u({},t),e)),r},p=function(e){var t=s(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),p=s(r),f=n,d=p["".concat(i,".").concat(f)]||p[f]||m[f]||a;return r?o.a.createElement(d,u(u({ref:t},l),{},{components:r})):o.a.createElement(d,u({ref:t},l))}));function d(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:n,i[1]=u;for(var l=2;l -Hola | ScalaPB - - - - - - - - - +Hola | ScalaPB + + + + + + + + +

Hola

Gao Wei

Gao Wei

Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

- - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/blog/2019/05/29/hello-world/index.html b/blog/2019/05/29/hello-world/index.html index 45f98e280..e1f023d36 100644 --- a/blog/2019/05/29/hello-world/index.html +++ b/blog/2019/05/29/hello-world/index.html @@ -8,28 +8,28 @@ -Hello | ScalaPB - - - - - - - - - +Hello | ScalaPB + + + + + + + + +
- - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/blog/2019/05/30/welcome/index.html b/blog/2019/05/30/welcome/index.html index 4b201b18c..7e85e0519 100644 --- a/blog/2019/05/30/welcome/index.html +++ b/blog/2019/05/30/welcome/index.html @@ -8,28 +8,28 @@ -Welcome | ScalaPB - - - - - - - - - +Welcome | ScalaPB + + + + + + + + +

Welcome

Yangshun Tay

Yangshun Tay

Front End Engineer @ Facebook

Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!

Delete the whole directory if you don't want the blog features. As simple as that!

- - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/blog/index.html b/blog/index.html index b80b180c7..91f19b223 100644 --- a/blog/index.html +++ b/blog/index.html @@ -8,34 +8,34 @@ -Blog | ScalaPB - - - - - - - - - - - - +Blog | ScalaPB + + + + + + + + + + + +

Welcome

Yangshun Tay

Yangshun Tay

Front End Engineer @ Facebook

Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!

Delete the whole directory if you don't want the blog features. As simple as that!

Hola

Gao Wei

Gao Wei

Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

- - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/tags/docusaurus/index.html b/blog/tags/docusaurus/index.html index ee92626b4..306a7670f 100644 --- a/blog/tags/docusaurus/index.html +++ b/blog/tags/docusaurus/index.html @@ -8,34 +8,34 @@ -Posts tagged "docusaurus" | ScalaPB - - - - - - - - - - - - +Posts tagged "docusaurus" | ScalaPB + + + + + + + + + + + +

3 posts tagged with "docusaurus"

View All Tags

Welcome

Yangshun Tay

Yangshun Tay

Front End Engineer @ Facebook

Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!

Delete the whole directory if you don't want the blog features. As simple as that!

Hola

Gao Wei

Gao Wei

Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

- - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/blog/tags/facebook/index.html b/blog/tags/facebook/index.html index bffe2cc85..b265778a4 100644 --- a/blog/tags/facebook/index.html +++ b/blog/tags/facebook/index.html @@ -8,30 +8,30 @@ -Posts tagged "facebook" | ScalaPB - - - - - - - - - - +Posts tagged "facebook" | ScalaPB + + + + + + + + + +

1 post tagged with "facebook"

View All Tags

Welcome

Yangshun Tay

Yangshun Tay

Front End Engineer @ Facebook

Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!

Delete the whole directory if you don't want the blog features. As simple as that!

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/blog/tags/hello/index.html b/blog/tags/hello/index.html index a7ff2f49d..508432ab0 100644 --- a/blog/tags/hello/index.html +++ b/blog/tags/hello/index.html @@ -8,32 +8,32 @@ -Posts tagged "hello" | ScalaPB - - - - - - - - - - - +Posts tagged "hello" | ScalaPB + + + + + + + + + + +

2 posts tagged with "hello"

View All Tags

Welcome

Yangshun Tay

Yangshun Tay

Front End Engineer @ Facebook

Blog features are powered by the blog plugin. Simply add files to the blog directory. It supports tags as well!

Delete the whole directory if you don't want the blog features. As simple as that!

- - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/blog/tags/hola/index.html b/blog/tags/hola/index.html index ec6e4db96..54ca3dded 100644 --- a/blog/tags/hola/index.html +++ b/blog/tags/hola/index.html @@ -8,30 +8,30 @@ -Posts tagged "hola" | ScalaPB - - - - - - - - - - +Posts tagged "hola" | ScalaPB + + + + + + + + + +

1 post tagged with "hola"

View All Tags

Hola

Gao Wei

Gao Wei

Docusaurus Core Team

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/blog/tags/index.html b/blog/tags/index.html index 93c05e7e4..e42cf5a81 100644 --- a/blog/tags/index.html +++ b/blog/tags/index.html @@ -8,26 +8,26 @@ -Tags | ScalaPB - - - - - - - - +Tags | ScalaPB + + + + + + + + - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/c0a0cb68.6772e505.js b/c0a0cb68.6772e505.js new file mode 100644 index 000000000..2477ab68d --- /dev/null +++ b/c0a0cb68.6772e505.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{106:function(e,t,r){"use strict";r.r(t),r.d(t,"frontMatter",(function(){return p})),r.d(t,"metadata",(function(){return l})),r.d(t,"toc",(function(){return i})),r.d(t,"default",(function(){return b}));var a=r(3),n=r(7),o=(r(0),r(119)),c=["components"],p={sidebar_label:"Introduction",slug:"/",title:"ScalaPB: Scala Protocol Buffer Compiler"},l={unversionedId:"intro",id:"intro",isDocsHomePage:!1,title:"ScalaPB: Scala Protocol Buffer Compiler",description:"ScalaPB is a protocol buffer compiler (protoc) plugin for Scala. It will",source:"@site/../docs/target/mdoc/intro.md",slug:"/",permalink:"/docs/",version:"current",sidebar_label:"Introduction",sidebar:"someSidebar",next:{title:"Installing ScalaPB",permalink:"/docs/installation"}},i=[{value:"Main features",id:"main-features",children:[]}],s={toc:i};function b(e){var t=e.components,r=Object(n.a)(e,c);return Object(o.b)("wrapper",Object(a.a)({},s,r,{components:t,mdxType:"MDXLayout"}),Object(o.b)("p",null,"ScalaPB is a protocol buffer compiler (",Object(o.b)("inlineCode",{parentName:"p"},"protoc"),") plugin for Scala. It will\ngenerate Scala case classes, parsers and serializers for your protocol\nbuffers."),Object(o.b)("p",null,"ScalaPB is hosted on ",Object(o.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB"},"Github"),"."),Object(o.b)("h2",{id:"main-features"},"Main features"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Built on top of Google's protocol buffer compiler to ensure perfect\ncompatibility with the language specification.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Supports both proto2 and proto3.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Nested updates are easy by using lenses:"))),Object(o.b)("pre",null,Object(o.b)("code",{parentName:"pre",className:"language-scala"},"val newOrder = order.update(_.creditCard.expirationYear := 2015)\n")),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Generated case classes can co-exist alongside the Java-generated code (the\nclass names will not clash). This allows gradual transition from Java to\nScala.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},"Can optionally generate conversion methods between the Java generated\nversion of Protocol Buffers to the Scala generated version. This makes\nit possible to migrate your project gradually.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"New:")," Supports for\n",Object(o.b)("a",{parentName:"p",href:"https://developers.google.com/protocol-buffers/docs/proto#oneof"},"Oneof"),"'s\nthat were introduced in Protocol Buffers 2.6.0.")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"Newer:")," Supports ",Object(o.b)("a",{parentName:"p",href:"/docs/scala.js"},"Scala.js")," (in 0.5.x).")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"Newer:")," Supports ",Object(o.b)("a",{parentName:"p",href:"http://www.grpc.io/"},"gRPC")," (in 0.5.x).")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"Newest:")," Supports ",Object(o.b)("a",{parentName:"p",href:"/docs/sparksql"},"SparkSQL")," (in 0.5.23).")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"Newest:")," Supports ",Object(o.b)("a",{parentName:"p",href:"/docs/json"},"converting to and from JSON")," (in 0.5.x).")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("p",{parentName:"li"},Object(o.b)("strong",{parentName:"p"},"Newest:")," Supports ",Object(o.b)("a",{parentName:"p",href:"/docs/user_defined_options"},"User-defined options")," (in 0.5.29)."))))}b.isMDXComponent=!0},119:function(e,t,r){"use strict";r.d(t,"a",(function(){return b})),r.d(t,"b",(function(){return m}));var a=r(0),n=r.n(a);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,a)}return r}function p(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var i=n.a.createContext({}),s=function(e){var t=n.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},b=function(e){var t=s(e.components);return n.a.createElement(i.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},f=n.a.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),b=s(r),f=a,m=b["".concat(c,".").concat(f)]||b[f]||u[f]||o;return r?n.a.createElement(m,p(p({ref:t},i),{},{components:r})):n.a.createElement(m,p({ref:t},i))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,c=new Array(o);c[0]=f;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:a,c[1]=p;for(var i=2;i=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var i=n.a.createContext({}),b=function(e){var t=n.a.useContext(i),r=t;return e&&(r="function"==typeof e?e(t):p(p({},t),e)),r},s=function(e){var t=b(e.components);return n.a.createElement(i.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return n.a.createElement(n.a.Fragment,{},t)}},f=n.a.forwardRef((function(e,t){var r=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,i=l(e,["components","mdxType","originalType","parentName"]),s=b(r),f=a,m=s["".concat(c,".").concat(f)]||s[f]||u[f]||o;return r?n.a.createElement(m,p(p({ref:t},i),{},{components:r})):n.a.createElement(m,p({ref:t},i))}));function m(e,t){var r=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=r.length,c=new Array(o);c[0]=f;var p={};for(var l in t)hasOwnProperty.call(t,l)&&(p[l]=t[l]);p.originalType=e,p.mdxType="string"==typeof e?e:a,c[1]=p;for(var i=2;i=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var p=r.a.createContext({}),l=function(e){var n=r.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},m=function(e){var n=l(e.components);return r.a.createElement(p.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},d=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),m=l(t),d=a,g=m["".concat(o,".").concat(d)]||m[d]||u[d]||i;return t?r.a.createElement(g,s(s({ref:n},p),{},{components:t})):r.a.createElement(g,s({ref:n},p))}));function g(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,o=new Array(i);o[0]=d;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;p=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var p=r.a.createContext({}),l=function(e){var t=r.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},m=function(e){var t=l(e.components);return r.a.createElement(p.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},d=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,b=m["".concat(o,".").concat(d)]||m[d]||u[d]||i;return n?r.a.createElement(b,s(s({ref:t},p),{},{components:n})):r.a.createElement(b,s({ref:t},p))}));function b(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=d;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:a,o[1]=s;for(var p=2;p0&&l.a.createElement("section",{className:p.a.features},l.a.createElement("div",{className:"container"},l.a.createElement("div",{className:"row"},d.map((function(e,a){return l.a.createElement(f,Object(r.a)({key:a},e))}))))),l.a.createElement("section",{className:p.a.sponsors},l.a.createElement("div",{className:"container"},l.a.createElement("h3",null,"Sponsors"),E.map((function(e,a){return l.a.createElement(g,Object(r.a)({key:a},e))})),l.a.createElement("a",{href:"https://github.com/sponsors/thesamet"},"Become a sponsor.")))))}}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{108:function(e,a,t){"use strict";t.r(a);var r=t(3),n=t(0),l=t.n(n),c=t(120),s=t(125),o=t(122),i=t(20),m=t(124),u=t(109),p=t.n(u),d=[{title:l.a.createElement(l.a.Fragment,null,"Easy to Use"),description:l.a.createElement(l.a.Fragment,null,"ScalaPB translates Protocol Buffers to Scala case classes. The generated API is easy to use!")},{title:l.a.createElement(l.a.Fragment,null,"Supports proto2 and proto3"),description:l.a.createElement(l.a.Fragment,null,"ScalaPB is built as a protoc plugin and has perfect compatibility with the protobuf language specification.")},{title:l.a.createElement(l.a.Fragment,null,"Nested updates"),description:l.a.createElement(l.a.Fragment,null,"Updating immutable nested structure is made easy by an optional lenses support. ",l.a.createElement("a",{href:"docs/generated-code#updating-messages"},"Learn more."))},{title:l.a.createElement(l.a.Fragment,null,"Interoperate with Java"),description:l.a.createElement(l.a.Fragment,null,"Scala Protocol Buffers can be converted to Java and vice versa. Scala and Java protobufs can co-exist in the same project to make it easier to gradually migrate, or interact with legacy Java APIs.")},{title:l.a.createElement(l.a.Fragment,null,"Scala.js support"),description:l.a.createElement(l.a.Fragment,null,"ScalaPB fully supports Scala.js so you can write Scala programs that use your domain-specific Protocol Buffers in the browser! ",l.a.createElement("a",{href:"docs/scala.js"},"Learn more."))},{title:l.a.createElement(l.a.Fragment,null,"gRPC"),description:l.a.createElement(l.a.Fragment,null,"Build gRPC servers and clients with ScalaPB. ScalaPB ships with its own wrapper around the official gRPC Java implementation. There are gRPC libraries for ZIO, Cats Effect and Akka. ",l.a.createElement("a",{href:"docs/grpc"}))}],E=[{name:l.a.createElement(l.a.Fragment,null,"MOIA"),profileUrl:"https://moia.io"}];function f(e){var a=e.imageUrl,t=e.title,r=e.description,n=Object(m.a)(a);return l.a.createElement("div",{className:Object(c.a)("col col--4",p.a.feature)},n&&l.a.createElement("div",{className:"text--center"},l.a.createElement("img",{className:p.a.featureImage,src:n,alt:t})),l.a.createElement("h3",null,t),l.a.createElement("p",null,r))}function g(e){var a=e.name,t=e.profileUrl;return l.a.createElement("div",{className:Object(c.a)("col col--4",p.a.sponsor)},l.a.createElement("a",{href:t},a))}a.default=function(){var e=Object(i.default)().siteConfig,a=void 0===e?{}:e,t=Object(m.a)("img/ScalaPB.png");return l.a.createElement(s.a,{title:"ScalaPB: Protocol Buffer Compiler for Scala",description:"ScalaPB compiles protocol buffers into Scala case classes."},l.a.createElement("header",{className:Object(c.a)("hero hero--primary",p.a.heroBanner)},l.a.createElement("div",{className:"container"},l.a.createElement("img",{src:t,width:"80%"}),l.a.createElement("p",{className:"hero__subtitle"},a.tagline),l.a.createElement("div",{className:p.a.buttons},l.a.createElement(o.a,{className:Object(c.a)(p.a.indexCtasGetStartedButton),to:Object(m.a)("docs/")},"Get Started")))),l.a.createElement("main",null,d&&d.length>0&&l.a.createElement("section",{className:p.a.features},l.a.createElement("div",{className:"container"},l.a.createElement("div",{className:"row"},d.map((function(e,a){return l.a.createElement(f,Object(r.a)({key:a},e))}))))),l.a.createElement("section",{className:p.a.sponsors},l.a.createElement("div",{className:"container"},l.a.createElement("h3",null,"Sponsors"),E.map((function(e,a){return l.a.createElement(g,Object(r.a)({key:a},e))})),l.a.createElement("a",{href:"https://github.com/sponsors/thesamet"},"Become a sponsor.")))))}}}]); \ No newline at end of file diff --git a/ccc49370.4e5ff17e.js b/ccc49370.4e5ff17e.js new file mode 100644 index 000000000..4fe453831 --- /dev/null +++ b/ccc49370.4e5ff17e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{118:function(e,t,a){"use strict";a.r(t);var n=a(0),l=a.n(n),r=a(125),i=a(134),c=a(122);var o=function(e){var t=e.nextItem,a=e.prevItem;return l.a.createElement("nav",{className:"pagination-nav","aria-label":"Blog post page navigation"},l.a.createElement("div",{className:"pagination-nav__item"},a&&l.a.createElement(c.a,{className:"pagination-nav__link",to:a.permalink},l.a.createElement("div",{className:"pagination-nav__sublabel"},"Newer Post"),l.a.createElement("div",{className:"pagination-nav__label"},"\xab ",a.title))),l.a.createElement("div",{className:"pagination-nav__item pagination-nav__item--next"},t&&l.a.createElement(c.a,{className:"pagination-nav__link",to:t.permalink},l.a.createElement("div",{className:"pagination-nav__sublabel"},"Older Post"),l.a.createElement("div",{className:"pagination-nav__label"},t.title," \xbb"))))},s=a(128),m=a(136),v=a(131);t.default=function(e){var t=e.content,a=e.sidebar,n=t.frontMatter,c=t.metadata,d=c.title,u=c.description,E=c.nextItem,f=c.prevItem,p=c.editUrl,g=n.hide_table_of_contents;return l.a.createElement(r.a,{title:d,description:u,wrapperClassName:"blog-wrapper"},t&&l.a.createElement("div",{className:"container margin-vert--lg"},l.a.createElement("div",{className:"row"},l.a.createElement("div",{className:"col col--2"},l.a.createElement(s.a,{sidebar:a})),l.a.createElement("main",{className:"col col--8"},l.a.createElement(i.a,{frontMatter:n,metadata:c,isBlogPostPage:!0},l.a.createElement(t,null)),l.a.createElement("div",null,p&&l.a.createElement("a",{href:p,target:"_blank",rel:"noreferrer noopener"},l.a.createElement(v.a,null),"Edit this page")),(E||f)&&l.a.createElement("div",{className:"margin-vert--xl"},l.a.createElement(o,{nextItem:E,prevItem:f}))),!g&&t.toc&&l.a.createElement("div",{className:"col col--2"},l.a.createElement(m.a,{toc:t.toc})))))}},131:function(e,t,a){"use strict";var n=a(3),l=a(7),r=a(0),i=a.n(r),c=a(120),o=a(57),s=a.n(o),m=["className"];t.a=function(e){var t=e.className,a=Object(l.a)(e,m);return i.a.createElement("svg",Object(n.a)({fill:"currentColor",height:"1.2em",width:"1.2em",preserveAspectRatio:"xMidYMid meet",role:"img",viewBox:"0 0 40 40",className:Object(c.a)(s.a.iconEdit,t)},a),i.a.createElement("g",null,i.a.createElement("path",{d:"m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"})))}},136:function(e,t,a){"use strict";var n=a(0),l=a.n(n),r=a(120);var i=function(e,t,a){var l=Object(n.useState)(void 0),r=l[0],i=l[1];Object(n.useEffect)((function(){function n(){var n=function(){var e=Array.from(document.getElementsByClassName("anchor")),t=e.find((function(e){return e.getBoundingClientRect().top>=a}));if(t){if(t.getBoundingClientRect().top>=a){var n=e[e.indexOf(t)-1];return null!=n?n:t}return t}return e[e.length-1]}();if(n)for(var l=0,c=!1,o=document.getElementsByClassName(e);l=a}));if(t){if(t.getBoundingClientRect().top>=a){var n=e[e.indexOf(t)-1];return null!=n?n:t}return t}return e[e.length-1]}();if(n)for(var l=0,c=!1,o=document.getElementsByClassName(e);l // handle cc\n case PaymentType.Bank(b) => // handle b\n case PaymentType.Empty => // handle exceptional case...\n}\n\n// The one of values are available as Option too:\nval maybeRoutingNumber: Option[String] = o3.paymentType.bank.map {\n b => b.routingNumber\n}\n')),Object(r.b)("h2",{id:"enumerations"},"Enumerations"),Object(r.b)("p",null,"Enumerations are implemented using sealed traits that extend ",Object(r.b)("inlineCode",{parentName:"p"},"GeneratedEnum"),".\nThis approach, rather than using Scala's standard Enumeration type, allows\ngetting a warning from the Scala compiler when a pattern match is incomplete."),Object(r.b)("p",null,"For a definition like:"),Object(r.b)("pre",null,Object(r.b)("code",Object(t.a)({parentName:"pre"},{className:"language-protobuf"}),"enum Weather {\n SUNNY = 1;\n PARTLY_CLOUDY = 2;\n RAIN = 3;\n}\n\nmessage Forecast {\n optional Weather weather = 1;\n}\n")),Object(r.b)("p",null,"The compiler will generate:"),Object(r.b)("pre",null,Object(r.b)("code",Object(t.a)({parentName:"pre"},{className:"language-scala"}),'sealed trait Weather extends GeneratedEnum {\n def isSunny: Boolean\n def isPartlyCloudy: Boolean\n def isRain: Boolean\n}\n\nobject Weather extends GeneratedEnumCompanion[Weather] {\n case object SUNNY extends Weather {\n val value = 1\n val name = "SUNNY"\n }\n\n // Similarly for the other enum values...\n case object PARTLY_CLOUDY extends Weather { ... }\n case object RAIN extends Weather { ... }\n\n // In ScalaPB >= 0.5.x, this captures unknown value that are received\n // from the wire format. Earlier versions throw a MatchError when\n // this happens.\n case class Unrecognized(value: Int) extends Weather { ... }\n\n // And a list of all possible values:\n lazy val values = Seq(SUNNY, PARTLY_CLOUDY, RAIN)\n}\n\ncase class Forecast(weather: Option[Weather]) { ... }\n')),Object(r.b)("p",null,"And we can write:"),Object(r.b)("pre",null,Object(r.b)("code",Object(t.a)({parentName:"pre"},{className:"language-scala"}),"val f = Forecast().update(_.weather := Weather.PARTLY_CLOUDY)\n\nassert(f.weather == Some(Weather.PARTLY_CLOUDY)\n\nif (f.getWeather.isRain) {\n // take an umbrella\n}\n\n// Pattern matching:\nf.getWeather match {\n case Weather.RAIN =>\n case Weather.SUNNY =>\n case _ =>\n}\n\n")),Object(r.b)("h2",{id:"ascii-representation"},"ASCII Representation"),Object(r.b)("p",null,"Each message case-class has ",Object(r.b)("inlineCode",{parentName:"p"},"toProtoString")," method that returns a string\nrepresentation of the message in an ASCII format. The ASCII format can be\nparsed back by the ",Object(r.b)("inlineCode",{parentName:"p"},"fromAscii()")," method available on the companion object."),Object(r.b)("p",null,"That format is not officially documented, but at least the standard Python,\nJava and C++ implementations of protobuf attempt to generate (and be able to parse)\ncompatible ASCII representations. ScalaPB's ",Object(r.b)("inlineCode",{parentName:"p"},"toString()")," and ",Object(r.b)("inlineCode",{parentName:"p"},"fromAscii"),"\nfollow the Java implementation."),Object(r.b)("p",null,"The format looks like this:"),Object(r.b)("pre",null,Object(r.b)("code",Object(t.a)({parentName:"pre"},{className:"language-protobuf"}),'int_field: 17\nstring_field: "foo"\nrepeated_string_field: "foo"\nrepeated_string_field: "bar"\nmessage_field {\n field1: "value1"\n color_enum: BLUE\n}\n')),Object(r.b)("p",null,"This format can be useful for debugging or for transient data processing, but\nbeware of persisting these ASCII representations: unknown fields throw an\nexception, and unlike the binary format, the ASCII format is senstitive to\nrenames."),Object(r.b)("h2",{id:"java-conversions"},"Java Conversions"),Object(r.b)("p",null,"If you are dealing with legacy Java protocol buffer code, while still wanting\nto write new code using ScalaPB, it can be useful to generate converters\nto/from the Java protocol buffers. To do this, set ",Object(r.b)("inlineCode",{parentName:"p"},"Compile / PB.targets"),"\nlike this in your ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",null,Object(r.b)("code",Object(t.a)({parentName:"pre"},{className:"language-scala"}),"Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value,\n scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value\n)\n")),Object(r.b)("p",null,"This will result in the following changes:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"The companion object for each message will have ",Object(r.b)("inlineCode",{parentName:"li"},"fromJavaProto")," and\n",Object(r.b)("inlineCode",{parentName:"li"},"toJavaProto")," methods."),Object(r.b)("li",{parentName:"ul"},"The companion object for enums will have ",Object(r.b)("inlineCode",{parentName:"li"},"fromJavaValue")," and\n",Object(r.b)("inlineCode",{parentName:"li"},"toJavaValue")," methods.")))}d.isMDXComponent=!0},119:function(e,n,a){"use strict";a.d(n,"a",(function(){return p})),a.d(n,"b",(function(){return u}));var t=a(0),i=a.n(t);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function o(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function s(e){for(var n=1;n=0||(i[a]=e[a]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var c=i.a.createContext({}),d=function(e){var n=i.a.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):s(s({},n),e)),a},p=function(e){var n=d(e.components);return i.a.createElement(c.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},m=i.a.forwardRef((function(e,n){var a=e.components,t=e.mdxType,r=e.originalType,o=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=d(a),m=t,u=p["".concat(o,".").concat(m)]||p[m]||b[m]||r;return a?i.a.createElement(u,s(s({ref:n},c),{},{components:a})):i.a.createElement(u,s({ref:n},c))}));function u(e,n){var a=arguments,t=n&&n.mdxType;if("string"==typeof e||t){var r=a.length,o=new Array(r);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:t,o[1]=s;for(var c=2;c // handle cc\n case PaymentType.Bank(b) => // handle b\n case PaymentType.Empty => // handle exceptional case...\n}\n\n// The one of values are available as Option too:\nval maybeRoutingNumber: Option[String] = o3.paymentType.bank.map {\n b => b.routingNumber\n}\n')),Object(r.b)("h2",{id:"enumerations"},"Enumerations"),Object(r.b)("p",null,"Enumerations are implemented using sealed traits that extend ",Object(r.b)("inlineCode",{parentName:"p"},"GeneratedEnum"),".\nThis approach, rather than using Scala's standard Enumeration type, allows\ngetting a warning from the Scala compiler when a pattern match is incomplete."),Object(r.b)("p",null,"For a definition like:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},"enum Weather {\n SUNNY = 1;\n PARTLY_CLOUDY = 2;\n RAIN = 3;\n}\n\nmessage Forecast {\n optional Weather weather = 1;\n}\n")),Object(r.b)("p",null,"The compiler will generate:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},'sealed trait Weather extends GeneratedEnum {\n def isSunny: Boolean\n def isPartlyCloudy: Boolean\n def isRain: Boolean\n}\n\nobject Weather extends GeneratedEnumCompanion[Weather] {\n case object SUNNY extends Weather {\n val value = 1\n val name = "SUNNY"\n }\n\n // Similarly for the other enum values...\n case object PARTLY_CLOUDY extends Weather { ... }\n case object RAIN extends Weather { ... }\n\n // In ScalaPB >= 0.5.x, this captures unknown value that are received\n // from the wire format. Earlier versions throw a MatchError when\n // this happens.\n case class Unrecognized(value: Int) extends Weather { ... }\n\n // And a list of all possible values:\n lazy val values = Seq(SUNNY, PARTLY_CLOUDY, RAIN)\n}\n\ncase class Forecast(weather: Option[Weather]) { ... }\n')),Object(r.b)("p",null,"And we can write:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},"val f = Forecast().update(_.weather := Weather.PARTLY_CLOUDY)\n\nassert(f.weather == Some(Weather.PARTLY_CLOUDY)\n\nif (f.getWeather.isRain) {\n // take an umbrella\n}\n\n// Pattern matching:\nf.getWeather match {\n case Weather.RAIN =>\n case Weather.SUNNY =>\n case _ =>\n}\n\n")),Object(r.b)("h2",{id:"ascii-representation"},"ASCII Representation"),Object(r.b)("p",null,"Each message case-class has ",Object(r.b)("inlineCode",{parentName:"p"},"toProtoString")," method that returns a string\nrepresentation of the message in an ASCII format. The ASCII format can be\nparsed back by the ",Object(r.b)("inlineCode",{parentName:"p"},"fromAscii()")," method available on the companion object."),Object(r.b)("p",null,"That format is not officially documented, but at least the standard Python,\nJava and C++ implementations of protobuf attempt to generate (and be able to parse)\ncompatible ASCII representations. ScalaPB's ",Object(r.b)("inlineCode",{parentName:"p"},"toString()")," and ",Object(r.b)("inlineCode",{parentName:"p"},"fromAscii"),"\nfollow the Java implementation."),Object(r.b)("p",null,"The format looks like this:"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-protobuf"},'int_field: 17\nstring_field: "foo"\nrepeated_string_field: "foo"\nrepeated_string_field: "bar"\nmessage_field {\n field1: "value1"\n color_enum: BLUE\n}\n')),Object(r.b)("p",null,"This format can be useful for debugging or for transient data processing, but\nbeware of persisting these ASCII representations: unknown fields throw an\nexception, and unlike the binary format, the ASCII format is senstitive to\nrenames."),Object(r.b)("h2",{id:"java-conversions"},"Java Conversions"),Object(r.b)("p",null,"If you are dealing with legacy Java protocol buffer code, while still wanting\nto write new code using ScalaPB, it can be useful to generate converters\nto/from the Java protocol buffers. To do this, set ",Object(r.b)("inlineCode",{parentName:"p"},"Compile / PB.targets"),"\nlike this in your ",Object(r.b)("inlineCode",{parentName:"p"},"build.sbt"),":"),Object(r.b)("pre",null,Object(r.b)("code",{parentName:"pre",className:"language-scala"},"Compile / PB.targets := Seq(\n PB.gens.java -> (Compile / sourceManaged).value,\n scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value\n)\n")),Object(r.b)("p",null,"This will result in the following changes:"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},"The companion object for each message will have ",Object(r.b)("inlineCode",{parentName:"li"},"fromJavaProto")," and\n",Object(r.b)("inlineCode",{parentName:"li"},"toJavaProto")," methods."),Object(r.b)("li",{parentName:"ul"},"The companion object for enums will have ",Object(r.b)("inlineCode",{parentName:"li"},"fromJavaValue")," and\n",Object(r.b)("inlineCode",{parentName:"li"},"toJavaValue")," methods.")))}p.isMDXComponent=!0},119:function(e,n,a){"use strict";a.d(n,"a",(function(){return p})),a.d(n,"b",(function(){return u}));var t=a(0),i=a.n(t);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function o(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),a.push.apply(a,t)}return a}function s(e){for(var n=1;n=0||(i[a]=e[a]);return i}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(t=0;t=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var c=i.a.createContext({}),d=function(e){var n=i.a.useContext(c),a=n;return e&&(a="function"==typeof e?e(n):s(s({},n),e)),a},p=function(e){var n=d(e.components);return i.a.createElement(c.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},m=i.a.forwardRef((function(e,n){var a=e.components,t=e.mdxType,r=e.originalType,o=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=d(a),m=t,u=p["".concat(o,".").concat(m)]||p[m]||b[m]||r;return a?i.a.createElement(u,s(s({ref:n},c),{},{components:a})):i.a.createElement(u,s({ref:n},c))}));function u(e,n){var a=arguments,t=n&&n.mdxType;if("string"==typeof e||t){var r=a.length,o=new Array(r);o[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:t,o[1]=s;for(var c=2;c=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var u=o.a.createContext({}),p=function(e){var t=o.a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},u),{},{components:r})):o.a.createElement(m,c({ref:t},u))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var i in t)hasOwnProperty.call(t,i)&&(c[i]=t[i]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var u=2;u=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var u=o.a.createContext({}),p=function(e){var t=o.a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},b={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},f=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,l=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),s=p(r),f=n,m=s["".concat(l,".").concat(f)]||s[f]||b[f]||a;return r?o.a.createElement(m,c(c({ref:t},u),{},{components:r})):o.a.createElement(m,c({ref:t},u))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=f;var c={};for(var i in t)hasOwnProperty.call(t,i)&&(c[i]=t[i]);c.originalType=e,c.mdxType="string"==typeof e?e:n,l[1]=c;for(var u=2;u -Common protos | ScalaPB - - - - - - - - - - +Common protos | ScalaPB + + + + + + + + + +
@@ -28,15 +28,15 @@ the protos in that jar. That requires a Scala class for them available in the classpath. This is accomplished by adding the library as a normal dependency.

If you don't have any proto files that import the common protos, then you can omit the "protobuf" dependency.

Adding new packages#

If you don't see your favorite third-party proto package here, and there is already a maven package for it that provides the proto files (with possibly Java generated classes), you can send a pull request to common-protos to have it added. See instruction on the ScalaPB Common Protos project page on Github.

Available packages#

proto-google-common-protos#

ScalaPB 0.11.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.11" % "2.5.0-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.11" % "2.5.0-2"
)

ScalaPB 0.10.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.10" % "2.5.0-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.10" % "2.5.0-2"
)

ScalaPB 0.9.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.9" % "2.5.0-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_0.9" % "2.5.0-2"
)

proto-google-cloud-pubsub-v1#

ScalaPB 0.11.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.11" % "1.96.2-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.11" % "1.96.2-2"
)

ScalaPB 0.10.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.10" % "1.96.2-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.10" % "1.96.2-2"
)

ScalaPB 0.9.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.9" % "1.96.2-2" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "proto-google-cloud-pubsub-v1-scalapb_0.9" % "1.96.2-2"
)

pgv-proto#

ScalaPB 0.11.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.11" % "0.6.1-0" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.11" % "0.6.1-0"
)

ScalaPB 0.10.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.10" % "0.6.1-0" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.10" % "0.6.1-0"
)

ScalaPB 0.9.x:

libraryDependencies ++= Seq(
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.9" % "0.6.1-0" % "protobuf",
"com.thesamet.scalapb.common-protos" %% "pgv-proto-scalapb_0.9" % "0.6.1-0"
)

footer

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/contact/index.html b/docs/contact/index.html index 6e63099de..efaa827c2 100644 --- a/docs/contact/index.html +++ b/docs/contact/index.html @@ -8,17 +8,17 @@ -Contacting us | ScalaPB - - - - - - - - - - +Contacting us | ScalaPB + + + + + + + + + +
@@ -45,15 +45,15 @@ payment options for this project work (small projects start at $200 USD). This would be a great way to support the time and effort put into the development of ScalaPB!

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/customizations/index.html b/docs/customizations/index.html index 0f5dae76b..fbdc8d594 100644 --- a/docs/customizations/index.html +++ b/docs/customizations/index.html @@ -8,17 +8,17 @@ -Customizations | ScalaPB - - - - - - - - - - +Customizations | ScalaPB + + + + + + + + + +
@@ -216,15 +216,15 @@ message and to individual fields:

message BarMessage {
option (scalapb.message).companion_annotations = "@mypackage.AnotherAnnotation2";
optional string x = 1 [
(scalapb.field).annotations = '@deprecated("Will be gone", "1.0")'
];
}

In ScalaPB 0.10.9, you can also add annotations to the auto generated unknownFields field:

message BarMessage {
option (scalapb.message).unknown_field_annotations = "@annotation1";
}

In ScalaPB 0.11.4, you can also add annotations to the enum values and the Unrecognized case class:

enum BarEnum {
option (scalapb.enum_options) = "@annotation"
}
enum BarEnum {
// every value will have the annotation added.
option (scalapb.enum_options).base_annotations = "@annotation1";
// only known values (case objects) will have the annotation added.
option (scalapb.enum_options).recognized_annotations = "@annotation2";
// only the unrecognized case class will have the annotation added.
option (scalapb.enum_options).unrecognized_annotations = "@annotation3";
// only this value (case object) will have the annotation added.
BarValue = 1 [(scalapb.enum_value).annotations = "@annotation4"];
}
- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/dotty/index.html b/docs/dotty/index.html index dbe22f6c5..1d96d0f24 100644 --- a/docs/dotty/index.html +++ b/docs/dotty/index.html @@ -8,17 +8,17 @@ -Using with Dotty | ScalaPB - - - - - - - - - - +Using with Dotty | ScalaPB + + + + + + + + + +
@@ -29,15 +29,15 @@
Compile / PB.targets := Seq(
scalapb.gen() -> (Compile / sourceManaged).value / "scalapb"
)

Generated code#

The generated code is designed to compile cleanly on all support versions of the Scala compiler with the default compiler settings. It is known that currently the generator will provide an error if -language:strictEquality is set.

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/faq/index.html b/docs/faq/index.html index 6628a0c77..5786cf2dd 100644 --- a/docs/faq/index.html +++ b/docs/faq/index.html @@ -8,17 +8,17 @@ -Frequently Asked Questions | ScalaPB - - - - - - - - - - +Frequently Asked Questions | ScalaPB + + + + + + + + + +
@@ -71,15 +71,15 @@
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.15.6'
}
plugins {
scalapb {
artifact = (org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) ?
"com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:windows@bat" :
"com.thesamet.scalapb:protoc-gen-scala:${scalapbVersion}:unix@sh"
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
// if you don't want java code to be generated.
remove java
}
task.plugins {
scalapb {
// add any ScalaPB generator options here. See: https://scalapb.github.io/scalapbc.html#passing-generator-parameters
// option 'flat_package'
}
}
}
}
}
// Add geneated Scala code as a source directory
sourceSets {
main {
scala {
srcDirs "${protobuf.generatedFilesBaseDir}/main/scalapb"
}
}
}

See full example here.

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/generated-code/index.html b/docs/generated-code/index.html index 8b87c5940..221d97f7a 100644 --- a/docs/generated-code/index.html +++ b/docs/generated-code/index.html @@ -8,17 +8,17 @@ -Generated Code | ScalaPB - - - - - - - - - - +Generated Code | ScalaPB + + + + + + + + + +
@@ -118,15 +118,15 @@ like this in your build.sbt:

Compile / PB.targets := Seq(
PB.gens.java -> (Compile / sourceManaged).value,
scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value
)

This will result in the following changes:

  • The companion object for each message will have fromJavaProto and toJavaProto methods.
  • The companion object for enums will have fromJavaValue and toJavaValue methods.
- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/generic/index.html b/docs/generic/index.html index 2a22da516..677c089de 100644 --- a/docs/generic/index.html +++ b/docs/generic/index.html @@ -8,17 +8,17 @@ -Writing generic code | ScalaPB - - - - - - - - - - +Writing generic code | ScalaPB + + + + + + + + + +
@@ -45,15 +45,15 @@
def readFromFile[A <: GeneratedMessage](fileName: String)(
implicit cmp: GeneratedMessageCompanion[A]): A = {
val byteArray = Files.readAllBytes(Paths.get(fileName))
cmp.parseFrom(byteArray)
}

When calling this function, you need to provide the specific type you want it to return, and the filename. The Scala compiler will automatically find the appropriate message companion to pass as cmp via implicit search:

readFromFile[Person]("/tmp/person.pb")
- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html index c014f8785..ec78f9f48 100644 --- a/docs/getting-started/index.html +++ b/docs/getting-started/index.html @@ -8,17 +8,17 @@ -Protocol Buffer Tutorial: Scala | ScalaPB - - - - - - - - - - +Protocol Buffer Tutorial: Scala | ScalaPB + + + + + + + + + +
@@ -45,15 +45,15 @@
// Keep prompting for phone numbers until None is returned.
val phones =
Iterator
.continually(getPhone())
.takeWhile(_.nonEmpty)
.flatten
.toSeq
Person(
id = id,
name = name,
email = if (email.nonEmpty) Some(email) else None,
phones = phones
)
}
def addPerson(): Unit = {
val newPerson = personFromStdin()
val addressBook = readFromFile()
// Append the new person to the people list field
val updated = addressBook.update(
_.people :+= newPerson
)
Using(new FileOutputStream("addressbook.pb")) { output =>
updated.writeTo(output)
}
}

Running the example#

In sbt, type run

This document, "Protocol Buffer Tutorial: Scala" is a modification of "Protocol Buffer Basics: Java", which is a work created and shared by Google and used according to terms described in the Creative Commons 4.0 Attribution License.

- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/grpc/index.html b/docs/grpc/index.html index 7dc2a74dd..156f7c4ba 100644 --- a/docs/grpc/index.html +++ b/docs/grpc/index.html @@ -8,17 +8,17 @@ -gRPC | ScalaPB - - - - - - - - - - +gRPC | ScalaPB + + + + + + + + + +
@@ -43,15 +43,15 @@ complete example server here.

Streaming clients, streaming servers, bidi#

Scalapb-grpc supports both client and server streaming. The Scala API follows closely the offical grpc-java API. Example project coming soon.

grpc-netty issues#

In certain situations (for example when you have a fat jar), you may see the following exception:

Exception in thread "main" io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional server found. Try adding a dependency on the grpc-netty artifact

To work around this issue, try the following solutions:

  1. Create a NettyServer explicitly using io.grpc.netty.NettyServerBuilder.

Example:

NettyServerBuilder
.forPort(9000)
.keepAliveTime(500, TimeUnit.SECONDS)
  1. If using SBT, try thefollowing merge conflict strategy:
assemblyMergeStrategy in assembly := {
case x if x.contains("io.netty.versions.properties") => MergeStrategy.discard
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
- - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 6ea6bafba..344655054 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,17 +8,17 @@ -ScalaPB: Scala Protocol Buffer Compiler | ScalaPB - - - - - - - - - - +ScalaPB: Scala Protocol Buffer Compiler | ScalaPB + + + + + + + + + +
@@ -32,15 +32,15 @@ it possible to migrate your project gradually.

  • New: Supports for Oneof's that were introduced in Protocol Buffers 2.6.0.

  • Newer: Supports Scala.js (in 0.5.x).

  • Newer: Supports gRPC (in 0.5.x).

  • Newest: Supports SparkSQL (in 0.5.23).

  • Newest: Supports converting to and from JSON (in 0.5.x).

  • Newest: Supports User-defined options (in 0.5.29).

  • - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/installation/index.html b/docs/installation/index.html index 126eeca06..17638937a 100644 --- a/docs/installation/index.html +++ b/docs/installation/index.html @@ -8,17 +8,17 @@ -Installing ScalaPB | ScalaPB - - - - - - - - - - +Installing ScalaPB | ScalaPB + + + + + + + + + +
    @@ -30,15 +30,15 @@ ScalaPB SBT Settings.

    Running Standalone Using scalapbc#

    If you would like to compile protocol buffers into Scala outside SBT, you can use scalapbc (ScalaPB compiler).

    See ScalaPBC.

    Running from Maven#

    Using ScalaPBC, you can get maven to generate the code for you. Check out the ScalaPB Maven example.

    Next:#

    Read about the Generated Code.

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/json/index.html b/docs/json/index.html index a3c378c8e..802bffb18 100644 --- a/docs/json/index.html +++ b/docs/json/index.html @@ -8,17 +8,17 @@ -ScalaPB and JSON | ScalaPB - - - - - - - - - - +ScalaPB and JSON | ScalaPB + + + + + + + + + +
    @@ -45,20 +45,20 @@ strings. To use the numeric representation, set this option to true. Note that due to the way Javascript represents numbers, there is a possibility to lose precision (more details here).

    The parser can be instantiated with new scalapb.json4s.Parser(), and various methods can return instances of the parser with customized configuration:

    • ignoringUnkownFields: by default the parser will throw a JsonFormatException when encountering unknown fields. By enabling this option, unknown options will be silently ignored.
    • ignoringOverlappingOneofFields: by default the parser will throw a JsonFormatException if values are provided for more than one field within the same oneof. By enabling this option, when more than one field is present for a oneof, one of the values of this field will be picked for the oneof.
    • mapEntriesAsKeyValuePairs: by default, protobuf maps are modeled as json objects. When this setting is enabled, protobuf maps are expected to be read as arrays of objects with key and value keys.

    See the list of constructor paramerters here

    Printing and parsing Anys#

    In Protocol Buffers, google.protobuf.Any is a type that embeds an arbitrary protobuf message. An Any is represented as a message that contains a typeUrl field that identifies the type, and a bytes field value which contains the serialized contents of a message. In JSON, the message embedded in the Any is serialized as usual, and there is a @type key added to it to identify which message it is. The parser expects this @type key to know which message it is. To accomplish this, all the expected embedded types need to be registered with a TypeRegistry so the printer and parser know how to process the embedded message.

    The following example is based on this proto.

    import com.thesamet.docs.json._
    import scalapb.json4s.{Printer, Parser, TypeRegistry}
    -
    val c = MyContainer(
    myAny=Some(
    com.google.protobuf.any.Any.pack(
    MyMessage(x=17)
    )
    )
    )
    // c: MyContainer = MyContainer(
    // Some(
    // Any(
    // "type.googleapis.com/com.thesamet.docs.MyMessage",
    // <ByteString@289cb4e4 size=2 contents="\b\021">,
    // UnknownFieldSet(Map())
    // )
    // ),
    // UnknownFieldSet(Map())
    // )
    -
    val typeRegistry = TypeRegistry().addMessage[MyMessage]
    // typeRegistry: TypeRegistry = TypeRegistry(
    // Map(
    // "type.googleapis.com/com.thesamet.docs.MyMessage" -> com.thesamet.docs.json.MyMessage$@14d1bf9
    // ),
    // Set()
    // )
    -
    val printer = new Printer().withTypeRegistry(typeRegistry)
    // printer: Printer = scalapb.json4s.Printer@5cd80bfc
    -
    printer.print(c)
    // res0: String = "{\"myAny\":{\"@type\":\"type.googleapis.com/com.thesamet.docs.MyMessage\",\"x\":17}}"

    Conversely, you can start from a JSON and parse it back to a MyContainer that contains an Any field:

    val parser = new Parser().withTypeRegistry(typeRegistry)
    // parser: Parser = scalapb.json4s.Parser@167c665e
    -
    parser.fromJsonString[MyContainer]("""
    {
    "myAny": {
    "@type": "type.googleapis.com/com.thesamet.docs.MyMessage",
    "x": 17
    }
    }""")
    // res1: MyContainer = MyContainer(
    // Some(
    // Any(
    // "type.googleapis.com/com.thesamet.docs.MyMessage",
    // <ByteString@2542d121 size=2 contents="\b\021">,
    // UnknownFieldSet(Map())
    // )
    // ),
    // UnknownFieldSet(Map())
    // )
    - - - - - - - - - - +
    val c = MyContainer(
    myAny=Some(
    com.google.protobuf.any.Any.pack(
    MyMessage(x=17)
    )
    )
    )
    // c: MyContainer = MyContainer(
    // Some(
    // Any(
    // "type.googleapis.com/com.thesamet.docs.MyMessage",
    // <ByteString@f843184 size=2 contents="\b\021">,
    // UnknownFieldSet(Map())
    // )
    // ),
    // UnknownFieldSet(Map())
    // )
    +
    val typeRegistry = TypeRegistry().addMessage[MyMessage]
    // typeRegistry: TypeRegistry = TypeRegistry(
    // Map(
    // "type.googleapis.com/com.thesamet.docs.MyMessage" -> com.thesamet.docs.json.MyMessage$@5e5e65ca
    // ),
    // Set()
    // )
    +
    val printer = new Printer().withTypeRegistry(typeRegistry)
    // printer: Printer = scalapb.json4s.Printer@4c01170
    +
    printer.print(c)
    // res0: String = "{\"myAny\":{\"@type\":\"type.googleapis.com/com.thesamet.docs.MyMessage\",\"x\":17}}"

    Conversely, you can start from a JSON and parse it back to a MyContainer that contains an Any field:

    val parser = new Parser().withTypeRegistry(typeRegistry)
    // parser: Parser = scalapb.json4s.Parser@1941d4f0
    +
    parser.fromJsonString[MyContainer]("""
    {
    "myAny": {
    "@type": "type.googleapis.com/com.thesamet.docs.MyMessage",
    "x": 17
    }
    }""")
    // res1: MyContainer = MyContainer(
    // Some(
    // Any(
    // "type.googleapis.com/com.thesamet.docs.MyMessage",
    // <ByteString@54500b2b size=2 contents="\b\021">,
    // UnknownFieldSet(Map())
    // )
    // ),
    // UnknownFieldSet(Map())
    // )
    + + + + + + + + + + \ No newline at end of file diff --git a/docs/sbt-settings/index.html b/docs/sbt-settings/index.html index 906290499..3d0bcc4e9 100644 --- a/docs/sbt-settings/index.html +++ b/docs/sbt-settings/index.html @@ -8,17 +8,17 @@ -SBT Settings | ScalaPB - - - - - - - - - - +SBT Settings | ScalaPB + + + + + + + + + +
    @@ -29,15 +29,15 @@ following to your build.sbt:

    libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"

    Defaults#

    The plugin assumes your proto files are under src/main/protobuf, however this is configurable using the Compile / PB.protoSources setting.

    By default, sbt-protoc invokes protoc 3.x that is shipped with protoc-jar. If you would like to run a different version of protoc:

    PB.protocVersion := "-v3.11.4"

    See all available options in sbt-protoc documentation

    Java Conversions#

    To enable Java conversions add the following to your build.sbt:

    Compile / PB.targets := Seq(
    PB.gens.java -> (Compile / sourceManaged).value,
    scalapb.gen(javaConversions=true) -> (Compile / sourceManaged).value
    )

    gRPC#

    Generating gRPC stubs for services is enabled by default. To disable:

    Compile / PB.targets := Seq(
    scalapb.gen(grpc=false) -> (Compile / sourceManaged).value
    )

    Additional options to the generator#

    scalapb.gen(
    flatPackage: Boolean = false,
    javaConversions: Boolean = false,
    grpc: Boolean = true,
    singleLineToProtoString: Boolean = false,
    asciiFormatToString: Boolean = false,
    lenses: Boolean = true,
    retainSourceCodeInfo: Boolean = false
    )
    OptionscalapbcDescription
    flatPackageflat_packageWhen set, ScalaPB will not append the protofile base name to the package name.
    javaConversionsjava_conversionsGenerates in the companion object two functions, toJavaProto and fromJavaProto that convert between the Scala case class and the Java protobufs. For the generated code to compile, the Java protobuf code need to be also generated or available as a library dependency.
    grpcgrpcGenerates gRPC code for services. Default is true in scalapb.gen, and need to be explicitly specified in scalapbc.
    singleLineToProtoStringsingle_line_to_proto_stringBy default, ScalaPB generates a toProtoString() method that renders the message as a multi-line format (using TextFormat.printToUnicodeString). If set, ScalaPB generates toString() methods that use the single line format.
    asciiFormatToStringascii_format_to_stringSetting this to true, overrides toString to return a standard ASCII representation of the message by calling toProtoString.
    lensesno_lensesBy default, ScalaPB generates lenses for each message for easy updating. If you are not using this feature and would like to reduce code size or compilation time, you can set this to false and lenses will not be generated.
    retainSourceCodeInforetain_source_code_infoRetain source code information (locations, comments) provided by protoc in the descriptors. Use the location accessor to get that information from a descriptor.
    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/scala.js/index.html b/docs/scala.js/index.html index 60809e71c..f7f0018bb 100644 --- a/docs/scala.js/index.html +++ b/docs/scala.js/index.html @@ -8,17 +8,17 @@ -Using ScalaPB with Scala.js | ScalaPB - - - - - - - - - - +Using ScalaPB with Scala.js | ScalaPB + + + + + + + + + +
    @@ -28,15 +28,15 @@ and Java descriptors do not work (though Scala descriptors in ScalaPB >= 0.6.0 would cover most use cases)

    Getting Started#

    Add to your library dependencies:

    libraryDependencies ++= Seq(
    "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion,
    // The following needed only if you include scalapb/scalapb.proto:
    "com.thesamet.scalapb" %%% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"
    )

    Demo#

    Example project: https://github.com/thesamet/scalapbjs-test

    Example with multi-project build: https://github.com/thesamet/sbt-protoc/tree/master/examples/scalajs-multiproject

    Live demo: http://thesamet.github.io/scalapbjs-test/

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/scalapbc/index.html b/docs/scalapbc/index.html index cdd3a604c..348d436d4 100644 --- a/docs/scalapbc/index.html +++ b/docs/scalapbc/index.html @@ -8,17 +8,17 @@ -ScalaPBC: ScalaPB's standalone compiler | ScalaPB - - - - - - - - - - +ScalaPBC: ScalaPB's standalone compiler | ScalaPB + + + + + + + + + +
    @@ -36,15 +36,15 @@ that use ZIO. This also generates ScalaPB case classes for messages and the GRPC descriptors that the generated ZIO code depends on.

    bin/scalapbc --plugin-artifact=com.thesamet.scalapb.zio-grpc:protoc-gen-zio:0.1.0:default,classifier=unix,ext=sh,type=jar -- e2e/src/main/protobuf/service.proto --zio_out=/tmp/out --scala_out=grpc:/tmp/out -Ie2e/src/main/protobuf -Ithird_party -Iprotobuf

    bin/scalapbc --plugin-artifact=io.grpc:grpc-java:

    Using ScalaPB as a proper protoc plugin#

    You may want to use ScalaPB code generator as a standard protoc plugin (rather than using scalapbc as a wrapper or through SBT).

    For Linux and Mac OS X, you can download a native executable version of the plugin for Scala from our release page:

    Those zip files contain native executables of the plugin for the respective operating system built using GraalVM. If you are using another operating system (such as Windows), or prefer to use a JVM based plugin implementation, you will find in scalapbc-0.11.1.zip an executable named bin/protoc-gen-scala which requires a JVM to run (a JVM needs to be available on the path, or through the JAVA_HOME environment variable)

    To generate code:

    protoc my.protos --plugin=/path/to/bin/protoc-gen-scala --scala_out=scala

    On Windows:

    protoc my.protos --plugin=protoc-gen-scala=/path/to/bin/protoc-gen-scala.bat --scala_out=scala

    For passing parameters to the plugin, see the section above.

    Note that the standalone plugin provided in scalapbc needs to be able to find a JVM in the path or through JAVA_HOME environment variable. If you encounter unexpected errors, try to execute the plugin directly from the command line, and the output printed may be useful for further debugging.

    The generated code depends on scalapb-runtime to compile. To get the code to work, add a dependency on scalapb-runtime to your project. The version of scalapb-runtime needs to match or be newer than the version of the plugin.

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/sealed-oneofs/index.html b/docs/sealed-oneofs/index.html index 9907e7656..24e396f40 100644 --- a/docs/sealed-oneofs/index.html +++ b/docs/sealed-oneofs/index.html @@ -8,17 +8,17 @@ -Sealed oneofs | ScalaPB - - - - - - - - - - +Sealed oneofs | ScalaPB + + + + + + + + + +
    @@ -40,15 +40,15 @@
    case class Add(left: Option[Expr], right: Option[Expr]) extends Expr with GeneratedMessage
    case class Mul(left: Option[Expr], right: Option[Expr]) extends Expr with GeneratedMessage
    case class Programs(exprs: Seq[Option[Expr]]) extends GeneratedMessage
    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/sparksql/index.html b/docs/sparksql/index.html index 35b04e0ce..a0f411fb5 100644 --- a/docs/sparksql/index.html +++ b/docs/sparksql/index.html @@ -8,30 +8,37 @@ -Using ScalaPB with Spark | ScalaPB - - - - - - - - - - +Using ScalaPB with Spark | ScalaPB + + + + + + + + + +

    Using ScalaPB with Spark

    Introduction#

    By default, Spark uses reflection to derive schemas and encoders from case classes. This doesn't work well when there are messages that contain types that -Spark does not understand such as enums, ByteStrings and oneofs. To get around this, sparksql-scalapb provides its own Encoders for protocol buffers.

    However, it turns out there is another obstacle. Spark does not provide any mechanism to compose user-provided encoders with its own reflection-derived Encoders. Therefore, merely providing an Encoder for protocol buffers is insufficient to derive an encoder for regular case-classes that contain a protobuf as a field. To solve this problem, ScalaPB uses frameless which relies on implicit search to derive encoders. This approach enables combining ScalaPB's encoders with frameless encoders that takes care for all non-protobuf types.

    Setting up your project#

    The version of sparksql-scalapb needs to match the Spark and -ScalaPB version:

    SparkScalaPBSparkSQL-ScalaPB
    3.00.11.x0.11.0
    3.00.10.x0.11.0-RC1
    2.x0.10.x0.10.4
    2.x0.9.x0.9.3

    We are going to use sbt-assembly to deploy a fat JAR containing ScalaPB, and +Spark does not understand such as enums, ByteStrings and oneofs. To get around this, sparksql-scalapb provides its own Encoders for protocol buffers.

    However, it turns out there is another obstacle. Spark does not provide any mechanism to compose user-provided encoders with its own reflection-derived Encoders. Therefore, merely providing an Encoder for protocol buffers is insufficient to derive an encoder for regular case-classes that contain a protobuf as a field. To solve this problem, ScalaPB uses frameless which relies on implicit search to derive encoders. This approach enables combining ScalaPB's encoders with frameless encoders that takes care for all non-protobuf types.

    Setting up your project#

    We are going to use sbt-assembly to deploy a fat JAR containing ScalaPB, and your compiled protos. Make sure in project/plugins.sbt you have a line -that adds sbt-assembly:

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")

    In build.sbt add a dependency on sparksql-scalapb:

    libraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.11.0"

    Spark ships with an old version of Google's Protocol Buffers runtime that is not compatible with +that adds sbt-assembly:

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")

    To add sparksql-scalapb to your project, add one of the following lines that +matches both the version of ScalaPB and Spark you use:

    // Spark 3.2 and ScalaPB 0.11
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql32-scalapb0_11" % "1.0.0-M1"
    +
    // Spark 3.1 and ScalaPB 0.11
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql31-scalapb0_11" % "1.0.0-M1"
    +
    // Spark 3.0 and ScalaPB 0.11
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql30-scalapb0_11" % "1.0.0-M1"
    +
    // Spark 3.2 and ScalaPB 0.10
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql32-scalapb0_10" % "1.0.0-M1"
    +
    // Spark 3.1 and ScalaPB 0.10
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql31-scalapb0_10" % "1.0.0-M1"
    +
    // Spark 3.0 and ScalaPB 0.10
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql30-scalapb0_10" % "1.0.0-M1"
    +
    // Spark 2.x and ScalaPB 0.10
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.10.4"
    +
    // Spark 2.x and ScalaPB 0.9
    libraryDependencies += "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.9.3"

    Spark ships with an old version of Google's Protocol Buffers runtime that is not compatible with the current version. Therefore, we need to shade our copy of the Protocol Buffer runtime. Spark 3 also ships with an incompatible version of scala-collection-compat. Add the following to your build.sbt:

    assemblyShadeRules in assembly := Seq(
    ShadeRule.rename("com.google.protobuf.**" -> "shadeproto.@1").inAll,
    ShadeRule.rename("scala.collection.compat.**" -> "shadecompat.@1").inAll
    )

    See complete example of build.sbt.

    Using sparksql-scalapb#

    We assume you have a SparkSession assigned to the variable spark. In a standalone Scala program, this can be created with:

    import org.apache.spark.sql.SparkSession
    -
    val spark: SparkSession = SparkSession
    .builder()
    .appName("ScalaPB Demo")
    .master("local[2]")
    .getOrCreate()
    // spark: SparkSession = org.apache.spark.sql.SparkSession@61ef672

    IMPORTANT: Ensure you do not import spark.implicits._ to avoid ambiguity between ScalaPB provided encoders and Spark's default encoders. You may want to import StringToColumn to convert $"col name" into a Column. Add an import scalapb.spark.Implicits to add ScalaPB's encoders for protocol buffers into the implicit search scope:

    import org.apache.spark.sql.{Dataset, DataFrame, functions => F}
    import spark.implicits.StringToColumn
    import scalapb.spark.ProtoSQL
    +
    val spark: SparkSession = SparkSession
    .builder()
    .appName("ScalaPB Demo")
    .master("local[2]")
    .getOrCreate()
    // spark: SparkSession = org.apache.spark.sql.SparkSession@25fc57af

    IMPORTANT: Ensure you do not import spark.implicits._ to avoid ambiguity between ScalaPB provided encoders and Spark's default encoders. You may want to import StringToColumn to convert $"col name" into a Column. Add an import scalapb.spark.Implicits to add ScalaPB's encoders for protocol buffers into the implicit search scope:

    import org.apache.spark.sql.{Dataset, DataFrame, functions => F}
    import spark.implicits.StringToColumn
    import scalapb.spark.ProtoSQL
    import scalapb.spark.Implicits._

    The code snippets below use the Person message.

    We start by creating some test data:

    import scalapb.docs.person.Person
    import scalapb.docs.person.Person.{Address, AddressType}
    val testData = Seq(
    Person(name="John", age=32, addresses=Vector(
    Address(addressType=AddressType.HOME, street="Market", city="SF"))
    ),
    Person(name="Mike", age=29, addresses=Vector(
    Address(addressType=AddressType.WORK, street="Castro", city="MV"),
    Address(addressType=AddressType.HOME, street="Church", city="MV"))
    ),
    Person(name="Bart", age=27)
    )

    We can create a DataFrame from the test data:

    val df = ProtoSQL.createDataFrame(spark, testData)
    // df: DataFrame = [name: string, age: int ... 1 more field]
    df.printSchema()
    // root
    // |-- name: string (nullable = true)
    // |-- age: integer (nullable = true)
    // |-- addresses: array (nullable = false)
    // | |-- element: struct (containsNull = false)
    // | | |-- address_type: string (nullable = true)
    // | | |-- street: string (nullable = true)
    // | | |-- city: string (nullable = true)
    //
    df.show()
    // +----+---+--------------------+
    // |name|age| addresses|
    // +----+---+--------------------+
    // |John| 32|[{HOME, Market, SF}]|
    // |Mike| 29|[{WORK, Castro, M...|
    // |Bart| 27| []|
    // +----+---+--------------------+
    //

    and then process it as any other Dataframe in Spark:

    df.select($"name", F.size($"addresses").alias("address_count")).show()
    // +----+-------------+
    // |name|address_count|
    // +----+-------------+
    // |John| 1|
    // |Mike| 2|
    // |Bart| 0|
    // +----+-------------+
    //
    val nameAndAddress = df.select($"name", $"addresses".getItem(0).alias("firstAddress"))
    // nameAndAddress: DataFrame = [name: string, firstAddress: struct<address_type: string, street: string ... 1 more field>]
    @@ -40,7 +47,7 @@
    val protoRDD: RDD[Person] = spark.sparkContext.parallelize(testData)
    val protoDF: DataFrame = ProtoSQL.protoToDataFrame(spark, protoRDD)
    val protoDS: Dataset[Person] = spark.createDataset(protoRDD)

    UDFs#

    If you need to write a UDF that returns a message, it would not pick up our encoder and you may get a runtime failure. To work around this, sparksql-scalapb provides ProtoSQL.udf to create UDFs. For example, if you need to parse a binary column into a proto:

    val binaryDF = protosBinary.toDF("value")
    // binaryDF: DataFrame = [value: binary]
    -
    val parsePersons = ProtoSQL.udf { bytes: Array[Byte] => Person.parseFrom(bytes) }
    // parsePersons: org.apache.spark.sql.Column => org.apache.spark.sql.Column = scalapb.spark.Udfs$$Lambda$11273/18226139@4575c0dd
    +
    val parsePersons = ProtoSQL.udf { bytes: Array[Byte] => Person.parseFrom(bytes) }
    // parsePersons: org.apache.spark.sql.Column => org.apache.spark.sql.Column = scalapb.spark.Udfs$$Lambda$11321/1255281891@7d1d1ae5
    binaryDF.withColumn("person", parsePersons($"value"))
    // res7: DataFrame = [value: binary, person: struct<name: string, age: int ... 1 more field>]

    Primitive wrappers#

    In ProtoSQL 0.9.x and 0.10.x, primitive wrappers are represented in Spark as structs witha single field named value. A better representation in Spark would be a nullable field of the primitive type. The better representation will be the @@ -49,15 +56,15 @@ Instead of importing scalapb.spark.Implicits._, import scalapb.spark.ProtoSQL.implicits._

    See example in WrappersSpec.

    Datasets and <none> is not a term#

    You will see this error if for some reason Spark's Encoders are being picked up instead of the ones provided by sparksql-scalapb. Please ensure you are not importing spark.implicits._. See instructions above for imports.

    Example#

    Check out a complete example here.

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/third-party-protos/index.html b/docs/third-party-protos/index.html index ec2dedd8c..a67e4dd7e 100644 --- a/docs/third-party-protos/index.html +++ b/docs/third-party-protos/index.html @@ -8,32 +8,32 @@ -Using third-party protos | ScalaPB - - - - - - - - - - +Using third-party protos | ScalaPB + + + + + + + + + +

    Using third-party protos

    The protos you are trying to generate code may depend on other protos which are currently are not a part of your build. We need to solve two problems:

    1. Making those proto files available to protoc's import search path so the import statements in your protos don't cause errors and code is generated.
    2. Providing Scala classes for those third-party protos.

    There are multiple ways to solve those problems.

    Common protos: maybe a Scala package for the protos already exists?#

    Check whether a ScalaPB Common Protos package is already available for the protos. If the proto library you are looking for is unavailable, consider making a PR or filing a feature request.

    You will add such libraries to your project twice: once with a protobuf suffix and once without:

    libraryDependencies ++= Seq(
    "com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_1.0" % "1.17.0-0" % "protobuf"
    "com.thesamet.scalapb.common-protos" %% "proto-google-common-protos-scalapb_1.0" % "1.17.0-0"
    )

    The first one makes sbt-protoc unpack the protos from the jar and add them to the import search path so protoc can import them (Problem 1 above), and the second import adds the compiled Scala classes to your classpath (Problem 2 above). In this solution, protoc will not generate code for the third-party protos: the provided package already gives you compiled classes for the generated code.

    There is a library on Maven with the protos (and possibly generated Java code)#

    Consider adding it to Common Protos. If this is not possible (for example, maybe the package is on a repository internal to your company), then you can have your SBT project download the library and build it by using the protobuf-src config. For example:

    libraryDependencies += "com.somepackage" %% "with-protos" % "1.0" % "protobuf-src" intransitive()

    This would make sbt-protoc download this JAR unpack it to target/protobuf_external_src, and make it both available for imports and generate code for it (which solves both problems above at once).

    Without the intransitive() modifier, sbt-protoc would generate code for all the dependencies of this package, and this is generally undesirable - since this is likely to lead to duplicate classes being generated.

    If the given package has dependencies, you will need to manually add them. The dependencies should be added with protobuf-src scope if you want to build them too. If you already have compiled packages for these dependencies, add the package both with protobuf and without like in the "common protos" example above.

    It is recommended to create a separate SBT sub-project for the third-party protos. For example:

    lazy val externalProtos = (project in file("ext-protos"))
    .settings(
    libraryDependencies ++= Seq(
    "com.thesamet.test" % "test-protos" % "0.1" % "protobuf-src" intransitive(),
    "com.thesamet.scalapb" %% "scalapb-runtime" % scalapbVersion % "protobuf"
    ),
    Compile / PB.targets := Seq(
    scalapb.gen() -> (Compile / sourceManaged).value
    )
    )
    // myProject contains its own protos which rely on protos from externalProtos
    lazy val myProject = (project in file("my-project"))
    .dependsOn(externalProtos)
    .settings(
    Compile / PB.targets := Seq(
    scalapb.gen() -> (Compile / sourceManaged).value
    )
    )

    See full example here.

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/transformations/index.html b/docs/transformations/index.html index 6bd5d72b7..6ec456b98 100644 --- a/docs/transformations/index.html +++ b/docs/transformations/index.html @@ -8,17 +8,17 @@ -Transformations | ScalaPB - - - - - - - - - - +Transformations | ScalaPB + + + + + + + + + +
    @@ -43,15 +43,15 @@
    package com.e;
    import "scalapb/scalapb.proto";
    option (scalapb.options) = {
    scope: PACKAGE
    field_transformations : [
    {
    when : {
    type: TYPE_MESSAGE
    type_name: ".google.protobuf.Timestamp"
    }
    set : {[scalapb.field] {type : 'com.myexample.MyType' }}
    }
    ]
    };
    note

    Note the . (dot) prefix in the type_name field above. It is needed as explained here. In this example we assume the user's package is not named google or google.protobuf since then type_name could be relative and would not match.

    Now, we need to make sure there is an implicit typemapper converting between google.protobuf.timestamp.Timestamp and com.myexample.MyType. The typemapper can be defined in the companion object of MyType as exampled in custom types.

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/upgrading/index.html b/docs/upgrading/index.html index b797003aa..8f4bf2770 100644 --- a/docs/upgrading/index.html +++ b/docs/upgrading/index.html @@ -8,17 +8,17 @@ -Upgrade guide | ScalaPB - - - - - - - - - - +Upgrade guide | ScalaPB + + + + + + + + + +
    @@ -33,15 +33,15 @@ is the default:

    PB.runProtoc in PB.protobufConfig := (args =>
    com.github.os72.protocjar.Protoc.runProtoc("-v300" +: args.toArray))

    Add a value to gen.targets:

    Compile / PB.targets := Seq(
    scalapb.gen() -> (Compile / sourceManaged).value
    )

    If you need Java Conversions, flat packages, etc see ScalaPB SBT Settings.

    If you are using files like scalapb.proto and Google's well-known proto change the library dependency from:

    "com.trueaccord.scalapb" %% "scalapb-runtime" % "0.11.1" % PB.protobufConfig

    to:

    "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf"
    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/user_defined_options/index.html b/docs/user_defined_options/index.html index 63f2eaa57..8b78d8e85 100644 --- a/docs/user_defined_options/index.html +++ b/docs/user_defined_options/index.html @@ -8,17 +8,17 @@ -Defining custom options | ScalaPB - - - - - - - - - - +Defining custom options | ScalaPB + + + + + + + + + +
    @@ -44,15 +44,15 @@ method:

    assert(use_opts.CustomOptionsUseOptsProto.scalaDescriptor.getOptions.extension(
    my_opts.CustomOptionsMyOptsProto.myFileOption) == Some("hello!"))
    assert(use_opts.OneMessage.scalaDescriptor.getOptions.extension(
    my_opts.CustomOptionsMyOptsProto.myMessageOption).get ==
    my_opts.MyMessageOption().update(_.priority := 17))
    assert(numberField.getOptions.extension(
    my_opts.Wrapper.tags) == Seq(
    my_opts.Tag(name = Some("tag1")),
    my_opts.Tag(name = Some("tag2"))))

    Example code#

    The full source code of this example is available below:

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/validation/index.html b/docs/validation/index.html index 461ab5f32..8963acc40 100644 --- a/docs/validation/index.html +++ b/docs/validation/index.html @@ -8,17 +8,17 @@ -Validating Protobufs | ScalaPB - - - - - - - - - - +Validating Protobufs | ScalaPB + + + + + + + + + +
    @@ -66,15 +66,15 @@
    option (scalapb.options) = {
    preprocessors : [ "scalapb-validate-preprocessor" ]
    import : "eu.timepit.refined.api.Refined"
    import : "eu.timepit.refined.numeric._"
    import : "eu.timepit.refined.generic._"
    import : "shapeless.{Witness => W}"
    field_transformations : [ {
    when : {options: {[validate.rules] {int32 : {gt : 1}}}} // <-- 1 can be replaced with any number
    set : {type : "Int Refined Greater[$(options.[validate.rules].int32.gt)]"}
    match_type : PRESENCE
    } ]
    };
    message Test {
    int32 gt_test = 1 [ (validate.rules).int32 = {gt : 5} ]; // transformed to: Int Refined Greater[5]
    }

    For this to work, a typemapper for refined types need to be either put in a package object in the same package where the code is generated, or be manually imported through import options.

    The typemapper used in scalapb-validate tests is here.

    Additional resources:

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/writing-plugins/index.html b/docs/writing-plugins/index.html index 96c357d67..a8a867e42 100644 --- a/docs/writing-plugins/index.html +++ b/docs/writing-plugins/index.html @@ -8,17 +8,17 @@ -Writing protoc plugins in Scala | ScalaPB - - - - - - - - - - +Writing protoc plugins in Scala | ScalaPB + + + + + + + + + +
    @@ -52,15 +52,15 @@ packaged with the core jar. External projects will be able to unpack it by depending on the core library with a % "protobuf" scope. To use:

    import "myplugin.proto";
    message MyMessage {
    option (myplugin.myopts).my_option = false;
    }

    Publishing the plugin#

    The project can be published to Maven using the “publish” command. We recommend to use the excellent sbt-ci-release plugin to automatically build a snapshot on each commit, and a full release when pushing a git tag.

    SBT users of your code generators will add your plugin to the build by adding it to their project/plugins.sbt like this:

    Compile / PB.targets := Seq(
    scalapb.gen() -> (Compile / sourceManaged).value / "scalapb",
    com.myplugin.gen() -> (Compile / sourceManaged).value / "scalapb"
    )

    The template also publishes artifacts with names ending with unix.sh and windows.bat. These are executable jars for Unix and Windows systems that contain all the classes needed to run your code generator (except of a JVM which is expected to be in JAVA_HOME or in the PATH). This is useful if your users need to use your plugin directly with protoc, or with a build tool such as maven.

    Secondary outputs#

    note

    Secondary outputs were introduced in protoc-bridge 0.9.0 and are supported by sbt-protoc 1.0.0 and onwards.

    Secondary outputs provide a simple way for protoc plugins to pass information for other protoc plugins running after them in the same protoc invocation. The information is passed through files that are created in a temporary directory. The absolute path of that temporary directory is provided to all protoc plugins. Plugins may create new files in that directory for subsequent plugins to consume.

    Conventions:

    • Names of secondary output files should be in kebab-case, and should clearly identify the plugin producing them. For example scalapb-validate-preprocessor.
    • The content of the file should be a serialized google.protobuf.Any message that packs the arbitrary payload the plugin wants to publish.

    Determining the secondary output directory location#

    JVM-based plugins that are executed in the same JVM that spawns protoc (like the ones described on this page), receive the location of the secondary output directory via the CodeGeneratorRequest. protoc-bridge appends to the request an unknown field carrying a message called ExtraEnv which contains the path to the secondary output directory.

    Other plugins that are invoked directly by protoc can find the secondary output directory by inspecting the SCALAPB_SECONDARY_OUTPUT_DIR environment variable.

    protoc-bridge takes care of creating the temporary directory and setting up the environment variable before invoking protoc. If protoc is ran manually (for example, through the CLI), it is the user's responsibility to create a directory for secondary outputs and pass it as an environment variable to protoc. It's worth noting that ScalaPB only looks for secondary output directory if a preprocessor is requested, and therefore for the most part users do not need to worry about secondary output directories.

    In ScalaPB's code base, SecondaryOutputProvider provides a method to find the secondary output directory as described above.

    Preprocessors#

    Preprocessors are protoc plugins that provide secondary outputs that are consumed by ScalaPB. ScalaPB expects the secondary output to be a google.protobuf.Any that encodes a PreprocessorOutput. The message contains a map between proto file names (as given by FileDescriptor#getFullName()) to additional ScalaPbOptions that are merged with the files options. By appending to aux_field_options, a preprocessor can, for example, impact the generated types of ScalaPB fields.

    • ScalaPB applies the provided options to a proto file only if the original file lists the preprocessor secondary output filename in a preprocessors file-level option. That option can be inherited from a package-scoped option.
    • To exclude a specific file from being preprocessed (if it would be otherwise impacted by a package-scoped option), add a -NAME entry to the list of preprocessors where NAME is the name of the preprocessor's secondary output.
    • In case of multiple preprocessors, options of later preprocessors overrides the one of earlier processors. Options in the file are merged over the preprocessor's options. When merging, repeated fields get concatenated.
    • Preprocessor plugins need to be invoked (in PB.targets or protoc's command line) before ScalaPB, so when ScalaPB runs their output is available.
    • Plugins that depend on ScalaPB (such as scalapb-validate) rely on DescriptorImplicits which consume the preprocessor output and therefore also see the updated options.

    Summary#

    If you followed this guide all the way to here, then congratulations for creating your first protoc plugin in Scala!

    If you have any questions, feel free to reach out to us on Gitter or Github.

    Did you write an interesting protoc plugin? Let us know on our gitter channel or our Google group and we'd love to mention it here!

    - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/e16015ca.a4c8d715.js b/e16015ca.130c2bd6.js similarity index 100% rename from e16015ca.a4c8d715.js rename to e16015ca.130c2bd6.js diff --git a/e901dba7.88a54853.js b/e901dba7.88a54853.js new file mode 100644 index 000000000..c317ce256 --- /dev/null +++ b/e901dba7.88a54853.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{114:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return p})),n.d(t,"metadata",(function(){return s})),n.d(t,"toc",(function(){return l})),n.d(t,"default",(function(){return b}));var a=n(3),o=n(7),i=(n(0),n(119)),r=["components"],p={title:"Transformations",layout:"docs"},s={unversionedId:"transformations",id:"transformations",isDocsHomePage:!1,title:"Transformations",description:"Introduction",source:"@site/../docs/target/mdoc/transformations.md",slug:"/transformations",permalink:"/docs/transformations",version:"current",sidebar:"someSidebar",previous:{title:"SBT Settings",permalink:"/docs/sbt-settings"},next:{title:"Generated Code",permalink:"/docs/generated-code"}},l=[{value:"Introduction",id:"introduction",children:[]},{value:"Example use-case",id:"example-use-case",children:[]},{value:"Syntax",id:"syntax",children:[{value:"Referencing rules values",id:"referencing-rules-values",children:[]}]},{value:"Example: customizing third-party types",id:"example-customizing-third-party-types",children:[]}],c={toc:l};function b(e){var t=e.components,n=Object(o.a)(e,r);return Object(i.b)("wrapper",Object(a.a)({},c,n,{components:t,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"introduction"},"Introduction"),Object(i.b)("p",null,"Field transformations were introduced in ScalaPB 0.10.10 and allow you to automatically apply ScalaPB field-level options when a given field match certain conditions. In the future, we expect to have transformations for additional protobuf entities."),Object(i.b)("p",null,"This document assumes that you are already familiar with:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"https://developers.google.com/protocol-buffers/docs/proto#customoptions"},"Protocol Buffer custom options"),"."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("a",{parentName:"li",href:"/docs/customizations"},"ScalaPB customizations")," and type mappers."),Object(i.b)("li",{parentName:"ul"},"Protobuf Descriptors, and specifically ",Object(i.b)("a",{parentName:"li",href:"https://github.com/protocolbuffers/protobuf/blob/48234f5f012582843bb476ee3afef36cda94cb66/src/google/protobuf/descriptor.proto#L138-L239"},"FieldDescriptorProto"),".")),Object(i.b)("h2",{id:"example-use-case"},"Example use-case"),Object(i.b)("p",null,"Assume that your project uses a custom option called ",Object(i.b)("inlineCode",{parentName:"p"},"sensitive"),", and whenever this option is set to ",Object(i.b)("inlineCode",{parentName:"p"},"true")," on a ",Object(i.b)("inlineCode",{parentName:"p"},"string")," field, you would ScalaPB to use a custom type, ",Object(i.b)("inlineCode",{parentName:"p"},"SensitiveString")," instead of a standard ",Object(i.b)("inlineCode",{parentName:"p"},"String"),"."),Object(i.b)("p",null,"The custom option definition could look like this:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'// opts.proto\nsyntax = "proto2";\n\npackage mypkg;\n\nimport "google/protobuf/descriptor.proto";\n\nextend google.protobuf.FieldOptions {\n optional MyCustomOptions opts = 50001;\n}\n\nmessage MyCustomOptions {\n optional bool sensitive = 1;\n optional int32 num = 2;\n}\n')),Object(i.b)("p",null,"Example usage of the custom options:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'// usage.proto\n\nsyntax = "proto3";\n\npackage mypkg;\n\nimport "opts.proto";\n\nmessage User {\n string secret = 1 [(mypkg.opts).sensitive = true];\n}\n')),Object(i.b)("p",null,"We want the type of ",Object(i.b)("inlineCode",{parentName:"p"},"secret")," in the case class to be ",Object(i.b)("inlineCode",{parentName:"p"},"SensitiveString"),". We could manually set\n",Object(i.b)("inlineCode",{parentName:"p"},"(scalapb.field).type")," to ",Object(i.b)("inlineCode",{parentName:"p"},"SensitiveString"),":"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'message User {\n string secret = 1 [(mypkg.opts).sensitive = true,\n (scalapb.field).type = "mypkg.SensitiveString"];\n}\n')),Object(i.b)("p",null,"but it would be nice if there was a way to automatically apply ",Object(i.b)("inlineCode",{parentName:"p"},"(scalapb.field).type")," automatically whenever ",Object(i.b)("inlineCode",{parentName:"p"},"sensitive")," was set to true on a ",Object(i.b)("inlineCode",{parentName:"p"},"string")," field. This is the problem field transformations are set to solve:"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'// Usage.proto:\nsyntax = "proto3";\n\nimport "scalapb/scalapb.proto";\nimport "opts.proto";\n\noption (scalapb.options) = {\n field_transformations : [\n {\n when : {\n options {\n [mypkg.opts]{sensitive : true}\n }\n type: TYPE_STRING\n }\n set : {[scalapb.field] {type : \'mypkg.SensitiveString\'}}\n }\n}\n\nmessage User {\n string secret = 1 [(mypkg.opts).sensitive = true];\n}\n')),Object(i.b)("p",null,"The transformation above matches when the custom option ",Object(i.b)("inlineCode",{parentName:"p"},"senstive")," is true, and the field type\nis ",Object(i.b)("inlineCode",{parentName:"p"},"string"),". When it matches, it sets the ScalaPB option ",Object(i.b)("inlineCode",{parentName:"p"},"type"),"."),Object(i.b)("h2",{id:"syntax"},"Syntax"),Object(i.b)("p",null,"FieldTransformations are defined in ",Object(i.b)("a",{parentName:"p",href:"https://github.com/scalapb/ScalaPB/blob/master/protobuf/scalapb/scalapb.proto"},"scalapb.proto"),":"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},"enum MatchType {\n CONTAINS = 0;\n EXACT = 1;\n PRESENCE = 2;\n}\n\nmessage FieldTransformation {\n optional google.protobuf.FieldDescriptorProto when = 1;\n optional MatchType match_type = 2 [default=CONTAINS];\n optional google.protobuf.FieldOptions set = 3;\n}\n")),Object(i.b)("p",null,"ScalaPB has a file-level option ",Object(i.b)("inlineCode",{parentName:"p"},"field_transformations")," which is a ",Object(i.b)("inlineCode",{parentName:"p"},"repeated FieldTransformation"),". The scope\nof the field transformations is the same proto-file, and can be passed down to the entire package as a package-scoped\noption (when ",Object(i.b)("inlineCode",{parentName:"p"},"scope: PACKAGE")," option is set)."),Object(i.b)("p",null,"A field transformation matches on the ",Object(i.b)("inlineCode",{parentName:"p"},"when")," condition which a ",Object(i.b)("a",{parentName:"p",href:"https://github.com/protocolbuffers/protobuf/blob/48234f5f012582843bb476ee3afef36cda94cb66/src/google/protobuf/descriptor.proto#L138-L239"},"FieldDescriptorProto"),". This allows it to match on the field's type, or label (",Object(i.b)("inlineCode",{parentName:"p"},"LABEL_REPEATED"),", ",Object(i.b)("inlineCode",{parentName:"p"},"LABEL_OPTIONAL"),", ",Object(i.b)("inlineCode",{parentName:"p"},"LABEL_REQUIRED"),"), as well as on custom options like in the previous example. There are few matching modes that are described below and can be selected using ",Object(i.b)("inlineCode",{parentName:"p"},"match_type"),". The ",Object(i.b)("inlineCode",{parentName:"p"},"set")," field tells ScalaPB what options to apply to the field if the rule conditions match. Currently, only ",Object(i.b)("inlineCode",{parentName:"p"},"[scalapb.field]")," options may appear in the ",Object(i.b)("inlineCode",{parentName:"p"},"set")," field."),Object(i.b)("p",null,"There are three matching modes available:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"CONTAINS")," is the default matching mode. In this mode, ScalaPB checks that all the options in the ",Object(i.b)("inlineCode",{parentName:"li"},"when")," pattern are defined on the field descriptor and having the same value. Additional fields may be defined on the field besides the ones on the ",Object(i.b)("inlineCode",{parentName:"li"},"when")," pattern."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"EXACT")," is a strict equality comparison between the ",Object(i.b)("inlineCode",{parentName:"li"},"when")," pattern and the field descriptor."),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"PRESENCE")," checks whether every field that is present on the ",Object(i.b)("inlineCode",{parentName:"li"},"when")," pattern is also present on the field's rules. The specific value the option has is not compared. This allows matching on any value. For example, ",Object(i.b)("inlineCode",{parentName:"li"},"{int32: {gt: 1}}")," would match for any number assigned to ",Object(i.b)("inlineCode",{parentName:"li"},"int32.gt"),".")),Object(i.b)("h3",{id:"referencing-rules-values"},"Referencing rules values"),Object(i.b)("p",null,"It is possible to reference values in the rules and use them on the ",Object(i.b)("inlineCode",{parentName:"p"},"set")," part. Whenever there is a singular string field under the field descriptor, ScalaPB would replace tokens in the format ",Object(i.b)("inlineCode",{parentName:"p"},"$(p)")," with the value of the field's option at the path ",Object(i.b)("inlineCode",{parentName:"p"},"p"),", relative to the ",Object(i.b)("inlineCode",{parentName:"p"},"FieldDescriptorProto")," of the field. To reference extension fields, wrap the extension full name in brackets (",Object(i.b)("inlineCode",{parentName:"p"},"[]"),"). For example, ",Object(i.b)("inlineCode",{parentName:"p"},"$(options.[pkg.opts].num)")," would be substituted with the value of that option on the field. If the option is not set on the field, a default value will be replaced (0 for numeric types, empty string, and so on)."),Object(i.b)("p",null,"The paths that are referenced don't have to appear on the ",Object(i.b)("inlineCode",{parentName:"p"},"when")," pattern. While referencing rule values is useful when the matching mode is ",Object(i.b)("inlineCode",{parentName:"p"},"PRESENCE"),", it is supported to reference rule values in all matching modes."),Object(i.b)("p",null,"One application for this is in conjunction with ",Object(i.b)("a",{parentName:"p",href:"https://github.com/fthomas/refined"},"refined types"),". See example in ",Object(i.b)("a",{parentName:"p",href:"/docs/validation#using-with-refined"},"ScalaPB validate documentation"),"."),Object(i.b)("h2",{id:"example-customizing-third-party-types"},"Example: customizing third-party types"),Object(i.b)("p",null,"When you want to customize your own messages, ScalaPB lets you add ",Object(i.b)("a",{parentName:"p",href:"/docs/customizations#message-level-custom-type-and-boxing"},"custom\noptions")," within the message is defined. You may also want to apply customizations to types defined in third-party protos which you can not change. To accomplish that, we can use field transformations. In the following example, we match on ",Object(i.b)("inlineCode",{parentName:"p"},"google.protobuf.Timestamp")," and map it to a custom type. In ",Object(i.b)("inlineCode",{parentName:"p"},"src/main/protobuf/myexample/options.proto"),":"),Object(i.b)("pre",null,Object(i.b)("code",{parentName:"pre",className:"language-protobuf"},'syntax = "proto2";\n\npackage com.e;\n\nimport "scalapb/scalapb.proto";\n\noption (scalapb.options) = {\n scope: PACKAGE\n field_transformations : [\n {\n when : {\n type: TYPE_MESSAGE\n type_name: ".google.protobuf.Timestamp"\n }\n set : {[scalapb.field] {type : \'com.myexample.MyType\' }}\n }\n ]\n};\n')),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",{parentName:"div",className:"admonition-heading"},Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",{parentName:"h5",className:"admonition-icon"},Object(i.b)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},Object(i.b)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),Object(i.b)("div",{parentName:"div",className:"admonition-content"},Object(i.b)("p",{parentName:"div"},"Note the ",Object(i.b)("inlineCode",{parentName:"p"},".")," (dot) prefix in the ",Object(i.b)("inlineCode",{parentName:"p"},"type_name")," field above. It is needed as ",Object(i.b)("a",{parentName:"p",href:"https://github.com/protocolbuffers/protobuf/blob/68cb69ea68822d96eee6d6104463edf85e70d689/src/google/protobuf/descriptor.proto#L187-L192"},"explained here"),". In this example we assume the user's package is not named ",Object(i.b)("inlineCode",{parentName:"p"},"google")," or ",Object(i.b)("inlineCode",{parentName:"p"},"google.protobuf")," since then ",Object(i.b)("inlineCode",{parentName:"p"},"type_name")," could be relative and would not match."))),Object(i.b)("p",null,"Now, we need to make sure there is an implicit typemapper converting between ",Object(i.b)("inlineCode",{parentName:"p"},"google.protobuf.timestamp.Timestamp")," and ",Object(i.b)("inlineCode",{parentName:"p"},"com.myexample.MyType"),". The typemapper can be defined in the companion object of ",Object(i.b)("inlineCode",{parentName:"p"},"MyType")," as exampled in ",Object(i.b)("a",{parentName:"p",href:"/docs/customizations#custom-types"},"custom types"),"."))}b.isMDXComponent=!0},119:function(e,t,n){"use strict";n.d(t,"a",(function(){return b})),n.d(t,"b",(function(){return u}));var a=n(0),o=n.n(a);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function p(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=o.a.createContext({}),c=function(e){var t=o.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},b=function(e){var t=c(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,r=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),b=c(n),d=a,u=b["".concat(r,".").concat(d)]||b[d]||m[d]||i;return n?o.a.createElement(u,p(p({ref:t},l),{},{components:n})):o.a.createElement(u,p({ref:t},l))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p.mdxType="string"==typeof e?e:a,r[1]=p;for(var l=2;l=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=o.a.createContext({}),c=function(e){var t=o.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):p(p({},t),e)),n},b=function(e){var t=c(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,r=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),b=c(n),d=a,u=b["".concat(r,".").concat(d)]||b[d]||m[d]||i;return n?o.a.createElement(u,p(p({ref:t},l),{},{components:n})):o.a.createElement(u,p({ref:t},l))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,r=new Array(i);r[0]=d;var p={};for(var s in t)hasOwnProperty.call(t,s)&&(p[s]=t[s]);p.originalType=e,p.mdxType="string"==typeof e?e:a,r[1]=p;for(var l=2;l -ScalaPB: Protocol Buffer Compiler for Scala | ScalaPB - - - - - - +ScalaPB: Protocol Buffer Compiler for Scala | ScalaPB + + + + + +

    Your Docusaurus site did not load properly.

    A very common reason is a wrong site baseUrl configuration.

    Current configured baseUrl = / (default value)

    We suggest trying baseUrl =

    Protocol Buffer Compiler for Scala

    Easy to Use

    ScalaPB translates Protocol Buffers to Scala case classes. The generated API is easy to use!

    Supports proto2 and proto3

    ScalaPB is built as a protoc plugin and has perfect compatibility with the protobuf language specification.

    Nested updates

    Updating immutable nested structure is made easy by an optional lenses support. Learn more.

    Interoperate with Java

    Scala Protocol Buffers can be converted to Java and vice versa. Scala and Java protobufs can co-exist in the same project to make it easier to gradually migrate, or interact with legacy Java APIs.

    Scala.js support

    ScalaPB fully supports Scala.js so you can write Scala programs that use your domain-specific Protocol Buffers in the browser! Learn more.

    gRPC

    Build gRPC servers and clients with ScalaPB. ScalaPB ships with its own wrapper around the official gRPC Java implementation. There are gRPC libraries for ZIO, Cats Effect and Akka.

    - - - - - - + + + + + + \ No newline at end of file diff --git a/main.a3b1c0bb.js b/main.a3b1c0bb.js deleted file mode 100644 index 41ae6a0c7..000000000 --- a/main.a3b1c0bb.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.a3b1c0bb.js.LICENSE.txt */ -(window.webpackJsonp=window.webpackJsonp||[]).push([[47],[function(e,t,n){"use strict";e.exports=n(38)},function(e,t,n){e.exports=n(42)()},function(e,t,n){"use strict";n.d(t,"a",(function(){return y})),n.d(t,"b",(function(){return w})),n.d(t,"c",(function(){return T})),n.d(t,"d",(function(){return C})),n.d(t,"e",(function(){return b})),n.d(t,"f",(function(){return L})),n.d(t,"g",(function(){return F})),n.d(t,"h",(function(){return h})),n.d(t,"i",(function(){return S})),n.d(t,"j",(function(){return _})),n.d(t,"k",(function(){return M})),n.d(t,"l",(function(){return z})),n.d(t,"m",(function(){return U})),n.d(t,"n",(function(){return B})),n.d(t,"o",(function(){return j}));var r=n(4),a=n(0),o=n.n(a),i=(n(1),n(6)),l=n(19),u=n(5),s=n(3),c=n(20),f=n.n(c),d=(n(26),n(7)),p=n(32),m=n.n(p),g=function(e){var t=Object(l.a)();return t.displayName=e,t}("Router-History"),h=function(e){var t=Object(l.a)();return t.displayName=e,t}("Router"),b=function(e){function t(t){var n;return(n=e.call(this,t)||this).state={location:t.history.location},n._isMounted=!1,n._pendingLocation=null,t.staticContext||(n.unlisten=t.history.listen((function(e){n._isMounted?n.setState({location:e}):n._pendingLocation=e}))),n}Object(r.a)(t,e),t.computeRootMatch=function(e){return{path:"/",url:"/",params:{},isExact:"/"===e}};var n=t.prototype;return n.componentDidMount=function(){this._isMounted=!0,this._pendingLocation&&this.setState({location:this._pendingLocation})},n.componentWillUnmount=function(){this.unlisten&&this.unlisten()},n.render=function(){return o.a.createElement(h.Provider,{value:{history:this.props.history,location:this.state.location,match:t.computeRootMatch(this.state.location.pathname),staticContext:this.props.staticContext}},o.a.createElement(g.Provider,{children:this.props.children||null,value:this.props.history}))},t}(o.a.Component);var y=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a=0;d--){var p=i[d];"."===p?o(i,d):".."===p?(o(i,d),f++):f&&(o(i,d),f--)}if(!s)for(;f--;f)i.unshift("..");!s||""===i[0]||i[0]&&a(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};function l(e){return e.valueOf?e.valueOf():Object.prototype.valueOf.call(e)}var u=function e(t,n){if(t===n)return!0;if(null==t||null==n)return!1;if(Array.isArray(t))return Array.isArray(n)&&t.length===n.length&&t.every((function(t,r){return e(t,n[r])}));if("object"==typeof t||"object"==typeof n){var r=l(t),a=l(n);return r!==t||a!==n?e(r,a):Object.keys(Object.assign({},t,n)).every((function(r){return e(t[r],n[r])}))}return!1},s=n(5);function c(e){return"/"===e.charAt(0)?e:"/"+e}function f(e){return"/"===e.charAt(0)?e.substr(1):e}function d(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function p(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function m(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function g(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e)).state=t:(void 0===(o=Object(r.a)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function h(e,t){return e.pathname===t.pathname&&e.search===t.search&&e.hash===t.hash&&e.key===t.key&&u(e.state,t.state)}function b(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),f({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=g(e,t,d(),w.location);c.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,f({action:r,location:a}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t=0||(a[n]=e[n]);return a}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";var r=!("undefined"==typeof window||!window.document||!window.document.createElement),a={canUseDOM:r,canUseEventListeners:r&&!(!window.addEventListener&&!window.attachEvent),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&!!window.screen};t.a=a},function(e,t,n){"use strict";n.d(t,"a",(function(){return l})),n.d(t,"b",(function(){return u}));var r=n(2),a=n(3),o=n(0),i=n.n(o);function l(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var a=e.path?Object(r.j)(t,e):n.length?n[n.length-1].match:r.e.computeRootMatch(t);return a&&(n.push({route:e,match:a}),e.routes&&l(e.routes,t,n)),a})),n}function u(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?i.a.createElement(r.g,n,e.map((function(e,n){return i.a.createElement(r.d,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render(Object(a.a)({},n,{},t,{route:e})):i.a.createElement(e.component,Object(a.a)({},n,t,{route:e}))}})}))):null}},function(e,t,n){"use strict";n.r(t),t.default={title:"ScalaPB",tagline:"Protocol Buffer Compiler for Scala",url:"https://scalapb.github.io/",baseUrl:"/",onBrokenLinks:"throw",favicon:"img/favicon.ico",organizationName:"scalapb",projectName:"scalapb.github.io",themeConfig:{sidebarCollapsible:!1,image:"https://scalapb.github.io/img/scalapb-social-light.png",navbar:{logo:{alt:"ScalaPB",src:"img/ScalaPB.png"},items:[{to:"docs/",activeBasePath:"docs",label:"Docs",position:"left"},{href:"https://github.com/scalapb/ScalaPB",label:"GitHub",position:"right"}],hideOnScroll:!1},footer:{style:"dark",links:[{title:"Docs",items:[{label:"Introduction",to:"docs/"},{label:"Installation",to:"docs/installation"},{label:"ScalaDoc",href:"https://scalapb.github.io/api/scalapb"}]},{title:"Community",items:[{label:"Stack Overflow",href:"https://stackoverflow.com/questions/tagged/scalapb"},{label:"Gitter",href:"https://gitter.im/ScalaPB/community"},{label:"Google Groups",href:"https://groups.google.com/g/scalapb"}]},{title:"More",items:[{label:"GitHub",href:"https://github.com/scalapb/ScalaPB"}]}],copyright:'Copyright \xa9 2014-2022, Nadav Samet'},prism:{additionalLanguages:["scala","protobuf"],theme:{plain:{color:"#403f53",backgroundColor:"#FBFBFB"},styles:[{types:["changed"],style:{color:"rgb(162, 191, 252)",fontStyle:"italic"}},{types:["deleted"],style:{color:"rgba(239, 83, 80, 0.56)",fontStyle:"italic"}},{types:["inserted","attr-name"],style:{color:"rgb(72, 118, 214)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(152, 159, 177)",fontStyle:"italic"}},{types:["string","builtin","char","constant","url"],style:{color:"rgb(72, 118, 214)"}},{types:["variable"],style:{color:"rgb(201, 103, 101)"}},{types:["number"],style:{color:"rgb(170, 9, 130)"}},{types:["punctuation"],style:{color:"rgb(153, 76, 195)"}},{types:["function","selector","doctype"],style:{color:"rgb(153, 76, 195)",fontStyle:"italic"}},{types:["class-name"],style:{color:"rgb(17, 17, 17)"}},{types:["tag"],style:{color:"rgb(153, 76, 195)"}},{types:["operator","property","keyword","namespace"],style:{color:"rgb(12, 150, 155)"}},{types:["boolean"],style:{color:"rgb(188, 84, 84)"}}]},darkTheme:{plain:{color:"#F8F8F2",backgroundColor:"#282A36"},styles:[{types:["prolog","constant","builtin"],style:{color:"rgb(189, 147, 249)"}},{types:["inserted","function"],style:{color:"rgb(80, 250, 123)"}},{types:["deleted"],style:{color:"rgb(255, 85, 85)"}},{types:["changed"],style:{color:"rgb(255, 184, 108)"}},{types:["punctuation","symbol"],style:{color:"rgb(248, 248, 242)"}},{types:["string","char","tag","selector"],style:{color:"rgb(255, 121, 198)"}},{types:["keyword","variable"],style:{color:"rgb(189, 147, 249)",fontStyle:"italic"}},{types:["comment"],style:{color:"rgb(98, 114, 164)"}},{types:["attr-name"],style:{color:"rgb(241, 250, 140)"}}]}},googleAnalytics:{trackingID:"UA-346180-20"},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!1,switchConfig:{darkIcon:"\ud83c\udf1c",darkIconStyle:{},lightIcon:"\ud83c\udf1e",lightIconStyle:{}}},docs:{versionPersistence:"localStorage"},metadatas:[],hideableSidebar:!1},presets:[["@docusaurus/preset-classic",{docs:{sidebarPath:"/home/runner/work/ScalaPB/ScalaPB/website/sidebars.js",path:"../docs/target/mdoc"},blog:{showReadingTime:!0},theme:{customCss:"/home/runner/work/ScalaPB/ScalaPB/website/src/css/custom.css"}}]],baseUrlIssueBanner:!0,i18n:{defaultLocale:"en",locales:["en"],localeConfigs:{}},onBrokenMarkdownLinks:"warn",onDuplicateRoutes:"warn",customFields:{},plugins:[],themes:[],titleDelimiter:"|",noIndex:!1}},function(e,t,n){"use strict";n.d(t,"a",(function(){return f})),n.d(t,"b",(function(){return d})),n.d(t,"c",(function(){return y})),n.d(t,"e",(function(){return E}));var r=n(2);n.d(t,"d",(function(){return r.a})),n.d(t,"f",(function(){return r.b})),n.d(t,"g",(function(){return r.c})),n.d(t,"h",(function(){return r.d})),n.d(t,"i",(function(){return r.e})),n.d(t,"j",(function(){return r.f})),n.d(t,"k",(function(){return r.g})),n.d(t,"l",(function(){return r.i})),n.d(t,"m",(function(){return r.j})),n.d(t,"n",(function(){return r.k})),n.d(t,"o",(function(){return r.l})),n.d(t,"p",(function(){return r.m})),n.d(t,"q",(function(){return r.n})),n.d(t,"r",(function(){return r.o}));var a=n(4),o=n(0),i=n.n(o),l=n(6),u=(n(1),n(3)),s=n(7),c=n(5),f=function(e){function t(){for(var t,n=arguments.length,r=new Array(n),a=0;a
    '};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),s=o.querySelector(r.barSelector),c=r.speed,f=r.easing;return o.offsetWidth,l((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),u(s,i(e,c,f)),1===e?(u(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){u(o,{transition:"all "+c+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),c)}),c)):setTimeout(t,c)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),l=e?"-100":o(n.status||0),s=document.querySelector(r.parent);return u(i,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&p(a),s!=document.body&&c(s,"nprogress-custom-parent"),s.appendChild(t),t},n.remove=function(){f(document.documentElement,"nprogress-busy"),f(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var l=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),u=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function s(e,t){return("string"==typeof e?e:d(e)).indexOf(" "+t+" ")>=0}function c(e,t){var n=d(e),r=n+t;s(n,t)||(e.className=r.substring(1))}function f(e,t){var n,r=d(e);s(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function d(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n})?r.call(t,n,t,e):r)||(e.exports=a)},,,function(e,t,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function a(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var l=n(0),u=n(1),s=[],c=[];function f(e){var t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then((function(e){return n.loading=!1,n.loaded=e,e})).catch((function(e){throw n.loading=!1,n.error=e,e})),n}function d(e){var t={loading:!1,loaded:{},error:null},n=[];try{Object.keys(e).forEach((function(r){var a=f(e[r]);a.loading?t.loading=!0:(t.loaded[r]=a.loaded,t.error=a.error),n.push(a.promise),a.promise.then((function(e){t.loaded[r]=e})).catch((function(e){t.error=e}))}))}catch(r){t.error=r}return t.promise=Promise.all(n).then((function(e){return t.loading=!1,e})).catch((function(e){throw t.loading=!1,e})),t}function p(e,t){return l.createElement((n=e)&&n.__esModule?n.default:n,t);var n}function m(e,t){var f,d;if(!t.loading)throw new Error("react-loadable requires a `loading` component");var m=Object.assign({loader:null,loading:null,delay:200,timeout:null,render:p,webpack:null,modules:null},t),g=null;function h(){return g||(g=e(m.loader)),g.promise}return s.push(h),"function"==typeof m.webpack&&c.push((function(){if(e=m.webpack,"object"===r(n.m)&&e().every((function(e){return void 0!==e&&void 0!==n.m[e]})))return h();var e})),d=f=function(t){function n(r){a(this,n);var i=o(this,t.call(this,r));return i.retry=function(){i.setState({error:null,loading:!0,timedOut:!1}),g=e(m.loader),i._loadModule()},h(),i.state={error:g.error,pastDelay:!1,timedOut:!1,loading:g.loading,loaded:g.loaded},i}return i(n,t),n.preload=function(){return h()},n.prototype.componentWillMount=function(){this._mounted=!0,this._loadModule()},n.prototype._loadModule=function(){var e=this;if(this.context.loadable&&Array.isArray(m.modules)&&m.modules.forEach((function(t){e.context.loadable.report(t)})),g.loading){"number"==typeof m.delay&&(0===m.delay?this.setState({pastDelay:!0}):this._delay=setTimeout((function(){e.setState({pastDelay:!0})}),m.delay)),"number"==typeof m.timeout&&(this._timeout=setTimeout((function(){e.setState({timedOut:!0})}),m.timeout));var t=function(){e._mounted&&(e.setState({error:g.error,loaded:g.loaded,loading:g.loading}),e._clearTimeouts())};g.promise.then((function(){t()})).catch((function(e){t()}))}},n.prototype.componentWillUnmount=function(){this._mounted=!1,this._clearTimeouts()},n.prototype._clearTimeouts=function(){clearTimeout(this._delay),clearTimeout(this._timeout)},n.prototype.render=function(){return this.state.loading||this.state.error?l.createElement(m.loading,{isLoading:this.state.loading,pastDelay:this.state.pastDelay,timedOut:this.state.timedOut,error:this.state.error,retry:this.retry}):this.state.loaded?m.render(this.state.loaded,this.props):null},n}(l.Component),f.contextTypes={loadable:u.shape({report:u.func.isRequired})},d}function g(e){return m(f,e)}g.Map=function(e){if("function"!=typeof e.render)throw new Error("LoadableMap requires a `render(loaded, props)` function");return m(d,e)};var h=function(e){function t(){return a(this,t),o(this,e.apply(this,arguments))}return i(t,e),t.prototype.getChildContext=function(){return{loadable:{report:this.props.report}}},t.prototype.render=function(){return l.Children.only(this.props.children)},t}(l.Component);function b(e){for(var t=[];e.length;){var n=e.pop();t.push(n())}return Promise.all(t).then((function(){if(e.length)return b(e)}))}h.propTypes={report:u.func.isRequired},h.childContextTypes={loadable:u.shape({report:u.func.isRequired}).isRequired},g.Capture=h,g.preloadAll=function(){return new Promise((function(e,t){b(s).then(e,t)}))},g.preloadReady=function(){return new Promise((function(e,t){b(c).then(e,e)}))},e.exports=g},function(e,t,n){"use strict";(function(e){var r=n(0),a=n.n(r),o=n(4),i=n(1),l=n.n(i),u=1073741823,s="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==e?e:{};function c(e){var t=[];return{on:function(e){t.push(e)},off:function(e){t=t.filter((function(t){return t!==e}))},get:function(){return e},set:function(n,r){e=n,t.forEach((function(t){return t(e,r)}))}}}var f=a.a.createContext||function(e,t){var n,a,i,f="__create-react-context-"+((s[i="__global_unique_id__"]=(s[i]||0)+1)+"__"),d=function(e){function n(){var t;return(t=e.apply(this,arguments)||this).emitter=c(t.props.value),t}Object(o.a)(n,e);var r=n.prototype;return r.getChildContext=function(){var e;return(e={})[f]=this.emitter,e},r.componentWillReceiveProps=function(e){if(this.props.value!==e.value){var n,r=this.props.value,a=e.value;((o=r)===(i=a)?0!==o||1/o==1/i:o!=o&&i!=i)?n=0:(n="function"==typeof t?t(r,a):u,0!==(n|=0)&&this.emitter.set(e.value,n))}var o,i},r.render=function(){return this.props.children},n}(r.Component);d.childContextTypes=((n={})[f]=l.a.object.isRequired,n);var p=function(t){function n(){var e;return(e=t.apply(this,arguments)||this).state={value:e.getValue()},e.onUpdate=function(t,n){0!=((0|e.observedBits)&n)&&e.setState({value:e.getValue()})},e}Object(o.a)(n,t);var r=n.prototype;return r.componentWillReceiveProps=function(e){var t=e.observedBits;this.observedBits=null==t?u:t},r.componentDidMount=function(){this.context[f]&&this.context[f].on(this.onUpdate);var e=this.props.observedBits;this.observedBits=null==e?u:e},r.componentWillUnmount=function(){this.context[f]&&this.context[f].off(this.onUpdate)},r.getValue=function(){return this.context[f]?this.context[f].get():e},r.render=function(){return(e=this.props.children,Array.isArray(e)?e[0]:e)(this.state.value);var e},n}(r.Component);return p.contextTypes=((a={})[f]=l.a.object,a),{Provider:d,Consumer:p}};t.a=f}).call(this,n(25))},function(e,t,n){var r=n(44);e.exports=p,e.exports.parse=o,e.exports.compile=function(e,t){return l(o(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=d;var a=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function o(e,t){for(var n,r=[],o=0,i=0,l="",c=t&&t.delimiter||"/";null!=(n=a.exec(e));){var f=n[0],d=n[1],p=n.index;if(l+=e.slice(i,p),i=p+f.length,d)l+=d[1];else{var m=e[i],g=n[2],h=n[3],b=n[4],y=n[5],v=n[6],w=n[7];l&&(r.push(l),l="");var E=null!=g&&null!=m&&m!==g,k="+"===v||"*"===v,S="?"===v||"*"===v,T=n[2]||c,x=b||y;r.push({name:h||o++,prefix:g||"",delimiter:T,optional:S,repeat:k,partial:E,asterisk:!!w,pattern:x?s(x):w?".*":"[^"+u(T)+"]+?"})}}return ie.length)return;if(!(E instanceof u)){if(g&&v!=t.length-1){if(d.lastIndex=w,!(_=d.exec(e)))break;for(var k=_.index+(m?_[1].length:0),S=_.index+_[0].length,T=v,x=w,O=t.length;T=(x+=t[T].length)&&(++v,w=x);if(t[v]instanceof u)continue;C=T-v,E=e.slice(w,x),_.index-=w}else{d.lastIndex=0;var _=d.exec(E),C=1}if(_){m&&(h=_[1]?_[1].length:0),S=(k=_.index+h)+(_=_[0].slice(h)).length;var P=E.slice(0,k),A=E.slice(S),N=[v,C];P&&(++v,w+=P.length,N.push(P));var R=new u(s,p?a.tokenize(_,p):_,b,_,g);if(N.push(R),A&&N.push(A),Array.prototype.splice.apply(t,N),1!=C&&a.matchGrammar(e,t,n,v,w,!0,s),i)break}else if(i)break}}}}},hooks:{add:function(){}},tokenize:function(e,t,n){var r=[e],o=t.rest;if(o){for(var i in o)t[i]=o[i];delete t.rest}return a.matchGrammar(e,r,t,0,0,!1),r}},(o=a.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a}).stringify=function(e,t,n){if("string"==typeof e)return e;if("Array"===a.util.type(e))return e.map((function(n){return o.stringify(n,t,e)})).join("");var r={type:e.type,content:o.stringify(e.content,t,n),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:n};if(e.alias){var i="Array"===a.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(r.classes,i)}var l=Object.keys(r.attributes).map((function(e){return e+'="'+(r.attributes[e]||"").replace(/"/g,""")+'"'})).join(" ");return"<"+r.tag+' class="'+r.classes.join(" ")+'"'+(l?" "+l:"")+">"+r.content+""},a);i.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},i.languages.markup.tag.inside["attr-value"].inside.entity=i.languages.markup.entity,i.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(i.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:i.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:i.languages[t]};var a={};a[e]={pattern:RegExp(/(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g,e),"i"),lookbehind:!0,greedy:!0,inside:r},i.languages.insertBefore("markup","cdata",a)}}),i.languages.xml=i.languages.extend("markup",{}),i.languages.html=i.languages.markup,i.languages.mathml=i.languages.markup,i.languages.svg=i.languages.markup,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0},{pattern:/(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/,greedy:!0,inside:n}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}};for(var r=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],a=n.variable[1].inside,o=0;o=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},i.languages.c=i.languages.extend("clike",{"class-name":{pattern:/(\b(?:enum|struct)\s+)\w+/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),i.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete i.languages.c.boolean,i.languages.cpp=i.languages.extend("c",{"class-name":{pattern:/(\b(?:class|enum|struct)\s+)\w+/,lookbehind:!0},keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),i.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),function(e){var t=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/@[\w-]+/}},url:{pattern:RegExp("url\\((?:"+t.source+"|[^\n\r()]*)\\)","i"),inside:{function:/^url/i,punctuation:/^\(|\)$/}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+t.source+")*?(?=\\s*\\{)"),string:{pattern:t,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},n.tag))}(i),i.languages.css.selector={pattern:i.languages.css.selector,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-:.\w]+/,id:/#[-:.\w]+/,attribute:{pattern:/\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/,greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},attribute:{pattern:/^(\s*)[-\w\xA0-\uFFFF]+/,lookbehind:!0},value:[/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,{pattern:/(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],punctuation:/[()]/}},i.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i,lookbehind:!0}}),i.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:/#[\da-f]{3,8}/i,entity:/\\[\da-f]{1,8}/i,unit:{pattern:/(\d)(?:%|[a-z]+)/,lookbehind:!0},number:/-?[\d.]+/}),i.languages.javascript=i.languages.extend("clike",{"class-name":[i.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),i.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,i.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:i.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:i.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:i.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:i.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),i.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:i.languages.javascript}},string:/[\s\S]+/}}}),i.languages.markup&&i.languages.markup.tag.addInlined("script","javascript"),i.languages.js=i.languages.javascript,function(e){var t=e.util.clone(e.languages.javascript);e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=/<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}))*\s*\/?)?>/i,e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/i,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.insertBefore("inside","attr-name",{spread:{pattern:/\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}/,inside:{punctuation:/\.{3}|[{}.]/,"attr-value":/\w+/}}},e.languages.jsx.tag),e.languages.insertBefore("inside","attr-value",{script:{pattern:/=(\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i,inside:{"script-punctuation":{pattern:/^=(?={)/,alias:"punctuation"},rest:e.languages.jsx},alias:"language-javascript"}},e.languages.jsx.tag);var n=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(n).join(""):""},r=function(t){for(var a=[],o=0;o0&&a[a.length-1].tagName===n(i.content[0].content[1])&&a.pop():"/>"===i.content[i.content.length-1].content||a.push({tagName:n(i.content[0].content[1]),openedBraces:0}):a.length>0&&"punctuation"===i.type&&"{"===i.content?a[a.length-1].openedBraces++:a.length>0&&a[a.length-1].openedBraces>0&&"punctuation"===i.type&&"}"===i.content?a[a.length-1].openedBraces--:l=!0),(l||"string"==typeof i)&&a.length>0&&0===a[a.length-1].openedBraces){var u=n(i);o0&&("string"==typeof t[o-1]||"plain-text"===t[o-1].type)&&(u=n(t[o-1])+u,t.splice(o-1,1),o--),t[o]=new e.Token("plain-text",u,null,u)}i.content&&"string"!=typeof i.content&&r(i.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||r(e.tokens)}))}(i),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^\s*(?:\/{3}|\*|\/\*\*)\s*@(?:param|arg|arguments)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^\s*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){"string"==typeof t&&(t=[t]),t.forEach((function(t){!function(t,n){var r="doc-comment",a=e.languages[t];if(a){var o=a[r];if(!o){var i={"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,alias:"comment"}};o=(a=e.languages.insertBefore(t,"comment",i))[r]}if(o instanceof RegExp&&(o=a[r]={pattern:o}),Array.isArray(o))for(var l=0,u=o.length;l>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","class-name",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0},namespace:{pattern:/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(\.[a-z]\w*)+/,lookbehind:!0,inside:{punctuation:/\./}},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":n,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(i),function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,l=i.length;-1!==n.code.indexOf(a=t(r,l));)++l;return i[l]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(l){for(var u=0;u=o.length);u++){var s=l[u];if("string"==typeof s||s.content&&"string"==typeof s.content){var c=o[a],f=n.tokenStack[c],d="string"==typeof s?s:s.content,p=t(r,c),m=d.indexOf(p);if(m>-1){++a;var g=d.substring(0,m),h=new e.Token(r,e.tokenize(f,n.grammar),"language-"+r,f),b=d.substring(m+p.length),y=[];g&&y.push.apply(y,i([g])),y.push(h),b&&y.push.apply(y,i([b])),"string"==typeof s?l.splice.apply(l,[u,1].concat(y)):s.content=y}}else s.content&&i(s.content)}return l}(n.tokens)}}}})}(i),function(e){e.languages.php=e.languages.extend("clike",{keyword:/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,boolean:{pattern:/\b(?:false|true)\b/i,alias:"constant"},constant:[/\b[A-Z_][A-Z0-9_]*\b/,/\b(?:null)\b/i],comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),e.languages.insertBefore("php","string",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),e.languages.insertBefore("php","comment",{delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"}}),e.languages.insertBefore("php","keyword",{variable:/\$+(?:\w+\b|(?={))/i,package:{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),e.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}});var t={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,lookbehind:!0,inside:{rest:e.languages.php}};e.languages.insertBefore("php","string",{"nowdoc-string":{pattern:/<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},"heredoc-string":{pattern:/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,greedy:!0,alias:"string",inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:t}},"single-quoted-string":{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0,alias:"string"},"double-quoted-string":{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,alias:"string",inside:{interpolation:t}}}),delete e.languages.php.string,e.hooks.add("before-tokenize",(function(t){if(/<\?/.test(t.code)){e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/gi)}})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(i),function(e){var t=e.languages.javascript,n=/{(?:[^{}]|{(?:[^{}]|{[^{}]*})*})+}/.source,r="(@(?:param|arg|argument|property)\\s+(?:"+n+"\\s+)?)";e.languages.jsdoc=e.languages.extend("javadoclike",{parameter:{pattern:RegExp(r+/[$\w\xA0-\uFFFF.]+(?=\s|$)/.source),lookbehind:!0,inside:{punctuation:/\./}}}),e.languages.insertBefore("jsdoc","keyword",{"optional-parameter":{pattern:RegExp(r+/\[[$\w\xA0-\uFFFF.]+(?:=[^[\]]+)?\](?=\s|$)/.source),lookbehind:!0,inside:{parameter:{pattern:/(^\[)[$\w\xA0-\uFFFF\.]+/,lookbehind:!0,inside:{punctuation:/\./}},code:{pattern:/(=)[\s\S]*(?=\]$)/,lookbehind:!0,inside:t,alias:"language-javascript"},punctuation:/[=[\]]/}},"class-name":[{pattern:RegExp("(@[a-z]+\\s+)"+n),lookbehind:!0,inside:{punctuation:/[.,:?=<>|{}()[\]]/}},{pattern:/(@(?:augments|extends|class|interface|memberof!?|this)\s+)[A-Z]\w*(?:\.[A-Z]\w*)*/,lookbehind:!0,inside:{punctuation:/\./}}],example:{pattern:/(@example\s+)[^@]+?(?=\s*(?:\*\s*)?(?:@\w|\*\/))/,lookbehind:!0,inside:{code:{pattern:/^(\s*(?:\*\s*)?).+$/m,lookbehind:!0,inside:t,alias:"language-javascript"}}}}),e.languages.javadoclike.addSupport("javascript",e.languages.jsdoc)}(i),i.languages.actionscript=i.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),i.languages.actionscript["class-name"].alias="function",i.languages.markup&&i.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:i.languages.markup}}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},rest:e.languages.javascript}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(i),function(e){e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:(?:Uint|Int)(?:8|16|32)|Uint8Clamped|Float(?:32|64))?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|(?:Weak)?(?:Set|Map)|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:/(\.\s*)#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*/,lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|location|navigator|performance|(?:local|session)Storage|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var t=["function","function-variable","method","method-variable","property-access"],n=0;n))/i,delete e.languages.flow.parameter,e.languages.insertBefore("flow","operator",{"flow-punctuation":{pattern:/\{\||\|\}/,alias:"punctuation"}}),Array.isArray(e.languages.flow.keyword)||(e.languages.flow.keyword=[e.languages.flow.keyword]),e.languages.flow.keyword.unshift({pattern:/(^|[^$]\b)(?:type|opaque|declare|Class)\b(?!\$)/,lookbehind:!0},{pattern:/(^|[^$]\B)\$(?:await|Diff|Exact|Keys|ObjMap|PropertyType|Shape|Record|Supertype|Subtype|Enum)\b(?!\$)/,lookbehind:!0})}(i),i.languages.n4js=i.languages.extend("javascript",{keyword:/\b(?:any|Array|boolean|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|module|new|null|number|package|private|protected|public|return|set|static|string|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/}),i.languages.insertBefore("n4js","constant",{annotation:{pattern:/@+\w+/,alias:"operator"}}),i.languages.n4jsd=i.languages.n4js,i.languages.typescript=i.languages.extend("javascript",{keyword:/\b(?:abstract|as|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield)\b/,builtin:/\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/}),i.languages.ts=i.languages.typescript,function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function l(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function u(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function s(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,u(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function c(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,c={},f=u(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=l(i++,r)););return c[n]=a,n})).join(""),n,r),d=Object.keys(c);return i=0,function e(t){for(var n=0;n=d.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=d[i],o="string"==typeof r?r:r.content,l=o.indexOf(a);if(-1!==l){++i;var u=o.substring(0,l),f=s(c[a]),p=o.substring(l+a.length),m=[];if(u&&m.push(u),m.push(f),p){var g=[p];e(g),m.push.apply(m,g)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(m)),n+=m.length-1):r.content=m}}else{var h=r.content;Array.isArray(h)?e(h):e([h])}}}(f),new e.Token(r,f,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:md|markdown)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),t].filter(Boolean);var f={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function d(e){return"string"==typeof e?e:Array.isArray(e)?e.map(d).join(""):d(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in f&&function t(n){for(var r=0,a=n.length;r/g,t),n&&(e=e+"|"+e.replace(/_/g,"\\*")),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``.+?``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\r?\n|\r)|$)/.source.replace(/__/g,r),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\r?\n|\r)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/(^[ \t]*(?:\r?\n|\r))(?: {4}|\t).+(?:(?:\r?\n|\r)(?: {4}|\t).+)*/m,lookbehind:!0,alias:"keyword"},{pattern:/``.+?``|`[^`\r\n]+`/,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\r?\n|\r))[\s\S]+?(?=(?:\r?\n|\r)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\r?\n|\r)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/__(?:(?!_)|_(?:(?!_))+_)+__/.source,!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/_(?:(?!_)|__(?:(?!_))+__)+_/.source,!0),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+?\2/.source,!1),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[(?:(?!\]))+\])/.source,!1),lookbehind:!0,greedy:!0,inside:{variable:{pattern:/(\[)[^\]]+(?=\]$)/,lookbehind:!0},content:{pattern:/(^!?\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(i),i.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/m,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/m}},coord:/^@@.*@@$/m,commit_sha1:/^commit \w{40}$/m},i.languages.go=i.languages.extend("clike",{keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/,boolean:/\b(?:_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,string:{pattern:/(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0}}),delete i.languages.go["class-name"],function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/i,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:true|false)\b/,block:{pattern:/^(\s*~?\s*)[#\/]\S+?(?=\s*~?\s*$|\s)/i,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")}))}(i),i.languages.json={property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,number:/-?\d+\.?\d*(e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},i.languages.less=i.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-]+?(?:\([^{}]+\)|[^(){};])*?(?=\s*\{)/i,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\([^{}]*\)|[^{};@])*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,operator:/[+\-*\/]/}),i.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-]+.*?(?=[(;])/,lookbehind:!0,alias:"function"}}),i.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^[^:=\r\n]+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},i.languages.objectivec=i.languages.extend("c",{keyword:/\b(?:asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,string:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|@"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete i.languages.objectivec["class-name"],i.languages.ocaml={comment:/\(\*[\s\S]*?\*\)/,string:[{pattern:/"(?:\\.|[^\\\r\n"])*"/,greedy:!0},{pattern:/(['`])(?:\\(?:\d+|x[\da-f]+|.)|(?!\1)[^\\\r\n])\1/i,greedy:!0}],number:/\b(?:0x[\da-f][\da-f_]+|(?:0[bo])?\d[\d_]*\.?[\d_]*(?:e[+-]?[\d_]+)?)/i,type:{pattern:/\B['`]\w*/,alias:"variable"},directive:{pattern:/\B#\w+/,alias:"function"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|object|of|open|prefix|private|rec|then|sig|struct|to|try|type|val|value|virtual|where|while|with)\b/,boolean:/\b(?:false|true)\b/,operator:/:=|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lxor|lsl|lsr|mod|nor|or)\b/,punctuation:/[(){}\[\]|_.,:;]/},i.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]+?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/i,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},i.languages.python["string-interpolation"].inside.interpolation.inside.rest=i.languages.python,i.languages.py=i.languages.python,i.languages.reason=i.languages.extend("clike",{comment:{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:mod|land|lor|lxor|lsl|lsr|asr)\b/}),i.languages.insertBefore("reason","class-name",{character:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,alias:"string"},constructor:{pattern:/\b[A-Z]\w*\b(?!\s*\.)/,alias:"variable"},label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete i.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t]+.+)*/m,lookbehind:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s+)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s]+.*)/m,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/([ \t]*)\S(?:,?[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,?[^,\r\n]+)*)*/,lookbehind:!0}})}(i),i.languages.scss=i.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()]|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),i.languages.insertBefore("scss","atrule",{keyword:[/@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,{pattern:/( +)(?:from|through)(?= )/,lookbehind:!0}]}),i.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),i.languages.insertBefore("scss","function",{placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,lookbehind:!0}}),i.languages.scss.atrule.inside.rest=i.languages.scss,i.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t={url:/url\((["']?).*?\1\)/i,string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:if|else|for|return|unless)(?=\s+|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,number:/\b\d+(?:\.\d+)?%?/,boolean:/\b(?:true|false)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.+|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],punctuation:/[{}()\[\];:,]/};t.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^{|}$/,alias:"punctuation"},rest:t}},t.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:t}},e.languages.stylus={comment:{pattern:/(^|[^\\])(\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},"atrule-declaration":{pattern:/(^\s*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:t}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:(?:\{[^}]*\}|.+)|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:t}},statement:{pattern:/(^[ \t]*)(?:if|else|for|return|unless)[ \t]+.+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:t}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)[^{\r\n]*(?:;|[^{\r\n,](?=$)(?!(\r?\n|\r)(?:\{|\2[ \t]+)))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:t.interpolation}},rest:t}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t]+)))/m,lookbehind:!0,inside:{interpolation:t.interpolation,punctuation:/[{},]/}},func:t.func,string:t.string,interpolation:t.interpolation,punctuation:/[{}()\[\];:.]/}}(i);var l=i.util.clone(i.languages.typescript);i.languages.tsx=i.languages.extend("jsx",l),i.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|nearest|neg?|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|store(?:8|16|32)?|sqrt|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^_`|~]+/i,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/},i.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},boolean:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},null:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}|\s*#))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},i.languages.yml=i.languages.yaml,t.a=i},function(e,t,n){"use strict";var r=n(0),a=n.n(r),o=n(33);t.a=function(e){return a.a.createElement(o.a,Object.assign({},e))}},function(e,t,n){"use strict";var r=n(9);t.a=r.b},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(r){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";e.exports=n(45)},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(39)},function(e){e.exports=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"intro","docs":[{"id":"common-protos","path":"/docs/common-protos","sidebar":"someSidebar"},{"id":"contact","path":"/docs/contact","sidebar":"someSidebar"},{"id":"customizations","path":"/docs/customizations","sidebar":"someSidebar"},{"id":"dotty","path":"/docs/dotty","sidebar":"someSidebar"},{"id":"faq","path":"/docs/faq","sidebar":"someSidebar"},{"id":"generated-code","path":"/docs/generated-code","sidebar":"someSidebar"},{"id":"generic","path":"/docs/generic","sidebar":"someSidebar"},{"id":"getting-started","path":"/docs/getting-started","sidebar":"someSidebar"},{"id":"grpc","path":"/docs/grpc","sidebar":"someSidebar"},{"id":"installation","path":"/docs/installation","sidebar":"someSidebar"},{"id":"intro","path":"/docs/","sidebar":"someSidebar"},{"id":"json","path":"/docs/json","sidebar":"someSidebar"},{"id":"sbt-settings","path":"/docs/sbt-settings","sidebar":"someSidebar"},{"id":"scala.js","path":"/docs/scala.js","sidebar":"someSidebar"},{"id":"scalapbc","path":"/docs/scalapbc","sidebar":"someSidebar"},{"id":"sealed-oneofs","path":"/docs/sealed-oneofs","sidebar":"someSidebar"},{"id":"sparksql","path":"/docs/sparksql","sidebar":"someSidebar"},{"id":"third-party-protos","path":"/docs/third-party-protos","sidebar":"someSidebar"},{"id":"transformations","path":"/docs/transformations","sidebar":"someSidebar"},{"id":"upgrading","path":"/docs/upgrading","sidebar":"someSidebar"},{"id":"user_defined_options","path":"/docs/user_defined_options","sidebar":"someSidebar"},{"id":"validation","path":"/docs/validation","sidebar":"someSidebar"},{"id":"writing-plugins","path":"/docs/writing-plugins","sidebar":"someSidebar"}]}]}}}')},function(e){e.exports=JSON.parse('{"defaultLocale":"en","locales":["en"],"localeConfigs":{"en":{"label":"en"}},"currentLocale":"en"}')},function(e){e.exports=JSON.parse("{}")},function(e){e.exports=JSON.parse('{"docusaurusVersion":"2.0.0-alpha.70","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.0.0-alpha.70"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.0.0-alpha.70"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.0.0-alpha.70"},"docusaurus-plugin-google-analytics":{"type":"package","name":"@docusaurus/plugin-google-analytics","version":"2.0.0-alpha.70"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.0.0-alpha.70"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.0.0-alpha.70"}}}')},function(e,t,n){"use strict";var r=n(26),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function u(e){return r.isMemo(e)?i:l[e.$$typeof]||a}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var s=Object.defineProperty,c=Object.getOwnPropertyNames,f=Object.getOwnPropertySymbols,d=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var a=p(n);a&&a!==m&&e(t,a,r)}var i=c(n);f&&(i=i.concat(f(n)));for(var l=u(t),g=u(n),h=0;h=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},q=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},G=function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return!1===t?String(e):String(e).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")},K=function(e){var t=J(e,w.TITLE),n=J(e,D);if(n&&t)return n.replace(/%s/g,(function(){return Array.isArray(t)?t.join(""):t}));var r=J(e,I);return t||r||void 0},Y=function(e){return J(e,j)||function(){}},Q=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return W({},e,t)}),{})},X=function(e,t){return t.filter((function(e){return void 0!==e[w.BASE]})).map((function(e){return e[w.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var r=Object.keys(n),a=0;a=0;n--){var r=e[n];if(r.hasOwnProperty(t))return r[t]}return null},ee=(r=Date.now(),function(e){var t=Date.now();t-r>16?(r=t,e(t)):setTimeout((function(){ee(e)}),0)}),te=function(e){return clearTimeout(e)},ne="undefined"!=typeof window?window.requestAnimationFrame&&window.requestAnimationFrame.bind(window)||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||ee:e.requestAnimationFrame||ee,re="undefined"!=typeof window?window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||te:e.cancelAnimationFrame||te,ae=function(e){return console&&"function"==typeof console.warn&&console.warn(e)},oe=null,ie=function(e,t){var n=e.baseTag,r=e.bodyAttributes,a=e.htmlAttributes,o=e.linkTags,i=e.metaTags,l=e.noscriptTags,u=e.onChangeClientState,s=e.scriptTags,c=e.styleTags,f=e.title,d=e.titleAttributes;se(w.BODY,r),se(w.HTML,a),ue(f,d);var p={baseTag:ce(w.BASE,n),linkTags:ce(w.LINK,o),metaTags:ce(w.META,i),noscriptTags:ce(w.NOSCRIPT,l),scriptTags:ce(w.SCRIPT,s),styleTags:ce(w.STYLE,c)},m={},g={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,r=t.oldTags;n.length&&(m[e]=n),r.length&&(g[e]=p[e].oldTags)})),t&&t(),u(e,m,g)},le=function(e){return Array.isArray(e)?e.join(""):e},ue=function(e,t){void 0!==e&&document.title!==e&&(document.title=le(e)),se(w.TITLE,t)},se=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var r=n.getAttribute(U),a=r?r.split(","):[],o=[].concat(a),i=Object.keys(t),l=0;l=0;f--)n.removeAttribute(o[f]);a.length===o.length?n.removeAttribute(U):n.getAttribute(U)!==i.join(",")&&n.setAttribute(U,i.join(","))}},ce=function(e,t){var n=document.head||document.querySelector(w.HEAD),r=n.querySelectorAll(e+"["+"data-react-helmet]"),a=Array.prototype.slice.call(r),o=[],i=void 0;return t&&t.length&&t.forEach((function(t){var n=document.createElement(e);for(var r in t)if(t.hasOwnProperty(r))if(r===x)n.innerHTML=t.innerHTML;else if(r===k)n.styleSheet?n.styleSheet.cssText=t.cssText:n.appendChild(document.createTextNode(t.cssText));else{var l=void 0===t[r]?"":t[r];n.setAttribute(r,l)}n.setAttribute(U,"true"),a.some((function(e,t){return i=t,n.isEqualNode(e)}))?a.splice(i,1):o.push(n)})),a.forEach((function(e){return e.parentNode.removeChild(e)})),o.forEach((function(e){return n.appendChild(e)})),{oldTags:a,newTags:o}},fe=function(e){return Object.keys(e).reduce((function(t,n){var r=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+r:r}),"")},de=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Object.keys(e).reduce((function(t,n){return t[R[n]||n]=e[n],t}),t)},pe=function(e,t,n){switch(e){case w.TITLE:return{toComponent:function(){return e=t.title,n=t.titleAttributes,(r={key:e})[U]=!0,a=de(n,r),[m.a.createElement(w.TITLE,a,e)];var e,n,r,a},toString:function(){return function(e,t,n,r){var a=fe(n),o=le(t);return a?"<"+e+' data-react-helmet="true" '+a+">"+G(o,r)+"":"<"+e+' data-react-helmet="true">'+G(o,r)+""}(e,t.title,t.titleAttributes,n)}};case b:case y:return{toComponent:function(){return de(t)},toString:function(){return fe(t)}};default:return{toComponent:function(){return function(e,t){return t.map((function(t,n){var r,a=((r={key:n})[U]=!0,r);return Object.keys(t).forEach((function(e){var n=R[e]||e;if(n===x||n===k){var r=t.innerHTML||t.cssText;a.dangerouslySetInnerHTML={__html:r}}else a[n]=t[e]})),m.a.createElement(e,a)}))}(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,r){var a=Object.keys(r).filter((function(e){return!(e===x||e===k)})).reduce((function(e,t){var a=void 0===r[t]?t:t+'="'+G(r[t],n)+'"';return e?e+" "+a:a}),""),o=r.innerHTML||r.cssText||"",i=-1===z.indexOf(e);return t+"<"+e+' data-react-helmet="true" '+a+(i?"/>":">"+o+"")}),"")}(e,t,n)}}}},me=function(e){var t=e.baseTag,n=e.bodyAttributes,r=e.encode,a=e.htmlAttributes,o=e.linkTags,i=e.metaTags,l=e.noscriptTags,u=e.scriptTags,s=e.styleTags,c=e.title,f=void 0===c?"":c,d=e.titleAttributes;return{base:pe(w.BASE,t,r),bodyAttributes:pe(b,n,r),htmlAttributes:pe(y,a,r),link:pe(w.LINK,o,r),meta:pe(w.META,i,r),noscript:pe(w.NOSCRIPT,l,r),script:pe(w.SCRIPT,u,r),style:pe(w.STYLE,s,r),title:pe(w.TITLE,{title:f,titleAttributes:d},r)}},ge=c()((function(e){return{baseTag:X([S,N],e),bodyAttributes:Q(b,e),defer:J(e,L),encode:J(e,F),htmlAttributes:Q(y,e),linkTags:Z(w.LINK,[P,S],e),metaTags:Z(w.META,[_,E,T,C,O],e),noscriptTags:Z(w.NOSCRIPT,[x],e),onChangeClientState:Y(e),scriptTags:Z(w.SCRIPT,[A,x],e),styleTags:Z(w.STYLE,[k],e),title:K(e),titleAttributes:Q(v,e)}}),(function(e){oe&&re(oe),e.defer?oe=ne((function(){ie(e,(function(){oe=null}))})):(ie(e),oe=null)}),me)((function(){return null})),he=(a=ge,i=o=function(e){function t(){return $(this,t),q(this,e.apply(this,arguments))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t.prototype.shouldComponentUpdate=function(e){return!d()(this.props,e)},t.prototype.mapNestedChildrenToProps=function(e,t){if(!t)return null;switch(e.type){case w.SCRIPT:case w.NOSCRIPT:return{innerHTML:t};case w.STYLE:return{cssText:t}}throw new Error("<"+e.type+" /> elements are self-closing and can not contain children. Refer to our API for more information.")},t.prototype.flattenArrayTypeChildren=function(e){var t,n=e.child,r=e.arrayTypeChildren,a=e.newChildProps,o=e.nestedChildren;return W({},r,((t={})[n.type]=[].concat(r[n.type]||[],[W({},a,this.mapNestedChildrenToProps(n,o))]),t))},t.prototype.mapObjectTypeChildren=function(e){var t,n,r=e.child,a=e.newProps,o=e.newChildProps,i=e.nestedChildren;switch(r.type){case w.TITLE:return W({},a,((t={})[r.type]=i,t.titleAttributes=W({},o),t));case w.BODY:return W({},a,{bodyAttributes:W({},o)});case w.HTML:return W({},a,{htmlAttributes:W({},o)})}return W({},a,((n={})[r.type]=W({},o),n))},t.prototype.mapArrayTypeChildrenToProps=function(e,t){var n=W({},t);return Object.keys(e).forEach((function(t){var r;n=W({},n,((r={})[t]=e[t],r))})),n},t.prototype.warnOnInvalidChildren=function(e,t){return!0},t.prototype.mapChildrenToProps=function(e,t){var n=this,r={};return m.a.Children.forEach(e,(function(e){if(e&&e.props){var a=e.props,o=a.children,i=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return Object.keys(e).reduce((function(t,n){return t[M[n]||n]=e[n],t}),t)}(V(a,["children"]));switch(n.warnOnInvalidChildren(e,o),e.type){case w.LINK:case w.META:case w.NOSCRIPT:case w.SCRIPT:case w.STYLE:r=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:r,newChildProps:i,nestedChildren:o});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:i,nestedChildren:o})}}})),t=this.mapArrayTypeChildrenToProps(r,t)},t.prototype.render=function(){var e=this.props,t=e.children,n=V(e,["children"]),r=W({},n);return t&&(r=this.mapChildrenToProps(t,r)),m.a.createElement(a,r)},H(t,null,[{key:"canUseDOM",set:function(e){a.canUseDOM=e}}]),t}(m.a.Component),o.propTypes={base:u.a.object,bodyAttributes:u.a.object,children:u.a.oneOfType([u.a.arrayOf(u.a.node),u.a.node]),defaultTitle:u.a.string,defer:u.a.bool,encodeSpecialCharacters:u.a.bool,htmlAttributes:u.a.object,link:u.a.arrayOf(u.a.object),meta:u.a.arrayOf(u.a.object),noscript:u.a.arrayOf(u.a.object),onChangeClientState:u.a.func,script:u.a.arrayOf(u.a.object),style:u.a.arrayOf(u.a.object),title:u.a.string,titleAttributes:u.a.object,titleTemplate:u.a.string},o.defaultProps={defer:!0,encodeSpecialCharacters:!0},o.peek=a.peek,o.rewind=function(){var e=a.rewind();return e||(e=me({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}})),e},i);he.renderStatic=he.rewind}).call(this,n(25))},function(e,t,n){"use strict";var r,a=n(0),o=(r=a)&&"object"==typeof r&&"default"in r?r.default:r;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var l=!("undefined"==typeof window||!window.document||!window.document.createElement);e.exports=function(e,t,n){if("function"!=typeof e)throw new Error("Expected reducePropsToState to be a function.");if("function"!=typeof t)throw new Error("Expected handleStateChangeOnClient to be a function.");if(void 0!==n&&"function"!=typeof n)throw new Error("Expected mapStateOnServer to either be undefined or a function.");return function(r){if("function"!=typeof r)throw new Error("Expected WrappedComponent to be a React component.");var u,s=[];function c(){u=e(s.map((function(e){return e.props}))),f.canUseDOM?t(u):n&&(u=n(u))}var f=function(e){var t,n;function a(){return e.apply(this,arguments)||this}n=e,(t=a).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,a.peek=function(){return u},a.rewind=function(){if(a.canUseDOM)throw new Error("You may only call rewind() on the server. Call peek() to read the current state.");var e=u;return u=void 0,s=[],e};var i=a.prototype;return i.UNSAFE_componentWillMount=function(){s.push(this),c()},i.componentDidUpdate=function(){c()},i.componentWillUnmount=function(){var e=s.indexOf(this);s.splice(e,1),c()},i.render=function(){return o.createElement(r,this.props)},a}(a.PureComponent);return i(f,"displayName","SideEffect("+function(e){return e.displayName||e.name||"Component"}(r)+")"),i(f,"canUseDOM",l),f}}},function(e,t){var n="undefined"!=typeof Element,r="function"==typeof Map,a="function"==typeof Set,o="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function i(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor!==t.constructor)return!1;var l,u,s,c;if(Array.isArray(e)){if((l=e.length)!=t.length)return!1;for(u=l;0!=u--;)if(!i(e[u],t[u]))return!1;return!0}if(r&&e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(c=e.entries();!(u=c.next()).done;)if(!t.has(u.value[0]))return!1;for(c=e.entries();!(u=c.next()).done;)if(!i(u.value[1],t.get(u.value[0])))return!1;return!0}if(a&&e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(c=e.entries();!(u=c.next()).done;)if(!t.has(u.value[0]))return!1;return!0}if(o&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(t)){if((l=e.length)!=t.length)return!1;for(u=l;0!=u--;)if(e[u]!==t[u])return!1;return!0}if(e.constructor===RegExp)return e.source===t.source&&e.flags===t.flags;if(e.valueOf!==Object.prototype.valueOf)return e.valueOf()===t.valueOf();if(e.toString!==Object.prototype.toString)return e.toString()===t.toString();if((l=(s=Object.keys(e)).length)!==Object.keys(t).length)return!1;for(u=l;0!=u--;)if(!Object.prototype.hasOwnProperty.call(t,s[u]))return!1;if(n&&e instanceof Element)return!1;for(u=l;0!=u--;)if(("_owner"!==s[u]&&"__v"!==s[u]&&"__o"!==s[u]||!e.$$typeof)&&!i(e[s[u]],t[s[u]]))return!1;return!0}return e!=e&&t!=t}e.exports=function(e,t){try{return i(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},,function(e,t,n){e.exports=n(53)},function(e,t,n){"use strict";var r=n(12),a="function"==typeof Symbol&&Symbol.for,o=a?Symbol.for("react.element"):60103,i=a?Symbol.for("react.portal"):60106,l=a?Symbol.for("react.fragment"):60107,u=a?Symbol.for("react.strict_mode"):60108,s=a?Symbol.for("react.profiler"):60114,c=a?Symbol.for("react.provider"):60109,f=a?Symbol.for("react.context"):60110,d=a?Symbol.for("react.forward_ref"):60112,p=a?Symbol.for("react.suspense"):60113,m=a?Symbol.for("react.memo"):60115,g=a?Symbol.for("react.lazy"):60116,h="function"==typeof Symbol&&Symbol.iterator;function b(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;nA.length&&A.push(e)}function I(e,t,n,r){var a=typeof e;"undefined"!==a&&"boolean"!==a||(e=null);var l=!1;if(null===e)l=!0;else switch(a){case"string":case"number":l=!0;break;case"object":switch(e.$$typeof){case o:case i:l=!0}}if(l)return n(r,e,""===t?"."+F(e,0):t),1;if(l=0,t=""===t?".":t+":",Array.isArray(e))for(var u=0;u