├── .gitignore
├── License.md
├── Readme.md
├── build.sbt
├── compiler
└── src
│ └── main
│ └── scala-2.11
│ └── org
│ └── katis
│ └── capnproto
│ └── compiler
│ ├── Compiler.scala
│ ├── FormattedText.scala
│ ├── Generator.scala
│ ├── package.scala
│ └── schema.scala
├── compilerTest
└── shared
│ └── src
│ └── test
│ └── scala-2.11
│ └── org
│ └── katis
│ └── capnproto
│ └── compiler
│ ├── ListList.capnp
│ ├── ListList.capnp.scala
│ ├── ListListSpec.scala
│ ├── SimpleGeneric.capnp
│ ├── SimpleGeneric.capnp.scala
│ ├── SimpleGenericSpec.scala
│ └── multifile
│ ├── MultifileSpec.scala
│ ├── customer.capnp
│ ├── customer.capnp.scala
│ ├── order.capnp
│ ├── order.capnp.scala
│ └── util
│ ├── uuid.capnp
│ └── uuid.capnp.scala
├── example
├── index.html
├── js
│ └── src
│ │ └── main
│ │ └── scala-2.11
│ │ └── org
│ │ └── katis
│ │ └── capnproto
│ │ └── example
│ │ └── client
│ │ └── Client.scala
├── jvm
│ └── src
│ │ └── main
│ │ └── scala-2.11
│ │ └── org
│ │ └── katis
│ │ └── capnproto
│ │ └── example
│ │ └── server
│ │ └── Server.scala
├── shared
│ └── src
│ │ └── main
│ │ └── scala-2.11
│ │ └── org
│ │ └── katis
│ │ └── capnproto
│ │ └── example
│ │ └── todo.capnp.scala
└── todo.capnp
├── project
├── build.properties
└── plugins.sbt
├── runtime
└── shared
│ └── src
│ ├── main
│ └── scala-2.11
│ │ └── org
│ │ └── katis
│ │ └── capnproto
│ │ └── runtime
│ │ ├── AnyPointer.scala
│ │ ├── Arena.scala
│ │ ├── ArrayInputStream.scala
│ │ ├── ArrayOutputStream.scala
│ │ ├── BufferedInputStream.scala
│ │ ├── BufferedInputStreamWrapper.scala
│ │ ├── BufferedOutputStream.scala
│ │ ├── BufferedOutputStreamWrapper.scala
│ │ ├── BuilderArena.scala
│ │ ├── ByteBufferList.scala
│ │ ├── Constants.scala
│ │ ├── Data.scala
│ │ ├── DataList.scala
│ │ ├── DecodeException.scala
│ │ ├── ElementSize.scala
│ │ ├── Enum.scala
│ │ ├── EnumList.scala
│ │ ├── FarPointer.scala
│ │ ├── GeneratedClassSupport.scala
│ │ ├── List.scala
│ │ ├── ListBuilder.scala
│ │ ├── ListList.scala
│ │ ├── ListPointer.scala
│ │ ├── ListReader.scala
│ │ ├── MessageBuilder.scala
│ │ ├── MessageReader.scala
│ │ ├── MessageStreamParser.scala
│ │ ├── NotInSchema.scala
│ │ ├── PackedInputStream.scala
│ │ ├── PackedOutputStream.scala
│ │ ├── PrimitiveList.scala
│ │ ├── ReaderArena.scala
│ │ ├── ReaderOptions.scala
│ │ ├── SegmentBuilder.scala
│ │ ├── SegmentReader.scala
│ │ ├── Serialize.scala
│ │ ├── SerializePacked.scala
│ │ ├── Struct.scala
│ │ ├── StructBuilder.scala
│ │ ├── StructList.scala
│ │ ├── StructPointer.scala
│ │ ├── StructReader.scala
│ │ ├── StructSize.scala
│ │ ├── Text.scala
│ │ ├── TextList.scala
│ │ ├── Void.scala
│ │ ├── WireHelpers.scala
│ │ ├── WirePointer.scala
│ │ ├── implicits.scala
│ │ └── pointer_traits.scala
│ └── test
│ └── scala-2.11
│ └── org
│ └── katis
│ └── capnproto
│ └── runtime
│ └── ByteBufferListSpec.scala
├── scala.capnp
└── schema.capnp
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .idea
3 |
--------------------------------------------------------------------------------
/License.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Joni Katajamäki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
8 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
14 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Cap'n Proto serialization for Scala & Scala.js
2 |
3 | See [Cap'n Proto homepage](https://capnproto.org/index.html) for more details about the data format.
4 |
5 | ## Compiler
6 |
7 | The compiler requires the [capnp tool](https://capnproto.org/install.html) in your PATH.
8 |
9 | It can be run with:
10 |
11 | java -jar capnpc-scala.jar file1.capnp file2.capnp
12 |
13 | You need to add the package and module annotations from scala.capnp to your schema.
14 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | name := "capnproto"
2 |
3 | scalaVersion in ThisBuild := "2.11.8"
4 |
5 | lazy val root = project.in(file(".")).
6 | aggregate(runtimeJS, runtimeJVM, capnpcScala, compilerTestJS, compilerTestJVM).
7 | settings(
8 | publish := {},
9 | publishLocal := {}
10 | )
11 |
12 | lazy val runtime = crossProject.in(file("./runtime")).
13 | settings(
14 | name := "capnproto",
15 | version := "0.1-SNAPSHOT",
16 | libraryDependencies += "org.scalactic" %%% "scalactic" % "3.0.0",
17 | libraryDependencies += "org.scalatest" %%% "scalatest" % "3.0.0" % "test"
18 | ).
19 | jvmSettings().
20 | jsSettings()
21 |
22 | lazy val runtimeJVM = runtime.jvm
23 | lazy val runtimeJS = runtime.js
24 |
25 | lazy val capnpcScala = project.in(file("./compiler")).dependsOn(runtimeJVM)
26 | mainClass in capnpcScala := Some("org.katis.capnproto.compiler.Compiler")
27 |
28 | lazy val sample = project.in(file("./example"))
29 | .aggregate(exampleJS, exampleJVM)
30 |
31 | lazy val compilerTest = crossProject.in(file("./compilerTest"))
32 | .settings(
33 | libraryDependencies += "org.scalactic" %%% "scalactic" % "3.0.0",
34 | libraryDependencies += "org.scalatest" %%% "scalatest" % "3.0.0" % "test"
35 | )
36 |
37 | lazy val compilerTestJS = compilerTest.js.dependsOn(runtimeJS)
38 | lazy val compilerTestJVM = compilerTest.jvm.dependsOn(runtimeJVM)
39 |
40 | lazy val example = crossProject.in(file("./example"))
41 | .settings(
42 | name := "Cap'n Proto example",
43 | version := "0.1-SNAPSHOT",
44 | libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "0.9.6"
45 | ).jvmSettings(
46 | libraryDependencies += "com.typesafe.akka" %% "akka-http-experimental" % "2.4.11"
47 | )
48 | .jsSettings(
49 | libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.0",
50 | libraryDependencies += "io.monix" %%% "monix" % "2.0.3"
51 | )
52 |
53 | lazy val exampleJS = example.js.dependsOn(runtimeJS)
54 | lazy val exampleJVM = example.jvm.dependsOn(runtimeJVM)
55 |
56 | lazy val testschemas = taskKey[Unit]("Compiles test cap'n proto files")
57 |
58 | testschemas := {
59 | val v = (assembly in capnpcScala).value
60 |
61 | def listFiles(f: File): Seq[String] = f match {
62 | case dir if dir.isDirectory =>
63 | dir.listFiles().flatMap(listFiles)
64 | case file if file.getAbsolutePath.endsWith(".capnp") =>
65 | Seq(file.getAbsolutePath)
66 | case _ =>
67 | Seq.empty
68 | }
69 |
70 | val d = new File("compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler")
71 | if (d.exists() && d.isDirectory) {
72 | val files = listFiles(d)
73 | val args = Seq("java", "-jar", v.getAbsolutePath) ++ files
74 | val compiler = new java.lang.ProcessBuilder(args:_*)
75 | compiler.redirectOutput(ProcessBuilder.Redirect.INHERIT)
76 | compiler.redirectError(ProcessBuilder.Redirect.INHERIT)
77 | val p = compiler.start()
78 | p.waitFor()
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/compiler/src/main/scala-2.11/org/katis/capnproto/compiler/Compiler.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.compiler
2 |
3 | import java.lang.ProcessBuilder
4 | import java.nio.channels.{Channels, ReadableByteChannel}
5 | import java.nio.file.{Files, Path, Paths}
6 |
7 | import org.katis.capnproto.compiler.schema._
8 | import org.katis.capnproto.runtime.implicits._
9 | import org.katis.capnproto.runtime.Serialize
10 |
11 | import scala.collection.JavaConverters._
12 | import scala.language.postfixOps
13 | import scala.sys.process._
14 |
15 | object Compiler {
16 |
17 | def main(args: Array[String]): Unit = {
18 | val outDir = Paths.get(System.getenv().getOrDefault("OUT_DIR", "."))
19 |
20 | if (args.length > 0) {
21 | val capnpc = compiler(args:_*)
22 | val proc = capnpc.start()
23 | val input = Channels.newChannel(proc.getInputStream)
24 | run(input, outDir)
25 | input.close()
26 | } else {
27 | println("Running as a plugin, waiting for input.")
28 | val input = Channels.newChannel(stdin)
29 | run(input, outDir)
30 | }
31 | }
32 |
33 | def compiler(files: String*): ProcessBuilder = {
34 | val params = Seq("capnp", "compile", "-o", "-") ++ files
35 | val capnpc = new ProcessBuilder(params:_*)
36 | capnpc.redirectError(ProcessBuilder.Redirect.INHERIT)
37 | capnpc
38 | }
39 |
40 | def fileGenerator(file: String): Generator = {
41 | val capnpc = compiler(file)
42 | val proc = capnpc.start()
43 | val input = Channels.newChannel(proc.getInputStream)
44 |
45 | val messageReader = Serialize.read(input)
46 | val request = messageReader.getRoot[CodeGeneratorRequest]
47 | new Generator(request)
48 | }
49 |
50 | def run(chan: ReadableByteChannel, outputDirectory: Path): Unit = {
51 | val messageReader = Serialize.read(chan)
52 |
53 | val request = messageReader.getRoot[CodeGeneratorRequest]
54 | val generator = new Generator(request)
55 |
56 | for (requestedFile <- request.requestedFiles) {
57 | val filePath = outputDirectory.resolve(requestedFile.filename.toString + ".scala")
58 | val output = generator.generateOutput(requestedFile.id)
59 |
60 | Files.write(filePath, output.asJava)
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/compiler/src/main/scala-2.11/org/katis/capnproto/compiler/FormattedText.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.compiler
2 |
3 | import scala.compat.Platform
4 |
5 | sealed trait FormattedText {
6 | def lines(indent: Int = 0): Vector[String]
7 |
8 | def stringify() =
9 | lines()
10 | .foldLeft(new StringBuilder)((a, b) => a.append(b).append(Platform.EOL))
11 | .toString()
12 | }
13 |
14 | case class Indent(text: FormattedText) extends FormattedText {
15 | override def lines(indent: Int): Vector[String] = text.lines(indent+1)
16 | }
17 | case class Branch(texts: FormattedText*) extends FormattedText {
18 | override def lines(indent: Int): Vector[String] = {
19 | (for (text <- texts;
20 | line <- text.lines(indent))
21 | yield line).toVector
22 | }
23 | }
24 | case class Line(line: String) extends FormattedText {
25 | override def lines(indent: Int): Vector[String] =
26 | Vector(" " * (indent * 2) + line)
27 | }
28 | object BlankLine extends FormattedText {
29 | override def lines(indent: Int): Vector[String] = Vector("")
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/compiler/src/main/scala-2.11/org/katis/capnproto/compiler/package.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto
2 |
3 | import org.katis.capnproto.runtime.{HasStructSize, HasTypeId}
4 |
5 | import org.katis.capnproto.compiler.schema._
6 |
7 | package object compiler {
8 | val PackageNameAnnotationId = 0xee44ce11f43e05d7L
9 | val ModuleAnnotationId = 0xfd7b105ce99a1686L
10 |
11 | val reservedClasses = Seq(
12 | "List",
13 | "Reader",
14 | "Builder",
15 | "ReaderImpl",
16 | "BuilderImpl",
17 | "ReaderBase",
18 | "BuilderBase"
19 | )
20 |
21 | val keywords = Seq(
22 | "case",
23 | "catch",
24 | "class",
25 | "def",
26 | "do",
27 | "else",
28 | "extends",
29 | "false",
30 | "final",
31 | "for",
32 | "if",
33 | "implicit",
34 | "import",
35 | "match",
36 | "new",
37 | "null",
38 | "object",
39 | "compiler",
40 | "print",
41 | "printf",
42 | "println",
43 | "private",
44 | "protected",
45 | "this",
46 | "throw",
47 | "to",
48 | "trait",
49 | "true",
50 | "try",
51 | "type",
52 | "until",
53 | "val",
54 | "var",
55 | "while",
56 | "with",
57 | "yield"
58 | ) ++ reservedClasses
59 |
60 | def booleanMatch[A, B](value: A)(fn: PartialFunction[A, B]): Boolean = fn.isDefinedAt(value)
61 |
62 | case class TypeParameterTexts(expandedList: Seq[String],
63 | params: String)
64 |
65 | implicit class TypeInfo(val typ: Type#Reader) extends AnyVal {
66 | def isParameter: Boolean = {
67 | typ match {
68 | case Type.AnyPointer(ptr) =>
69 | ptr match {
70 | case Type.AnyPointer.Parameter(_) => true
71 | case _ => false
72 | }
73 | case _ => false
74 | }
75 | }
76 |
77 | def isBranded: Boolean = {
78 | typ match {
79 | case Type.Struct(struct) =>
80 | struct.brand.scopes.size > 0
81 | case _ => false
82 | }
83 | }
84 |
85 | def isPrimitive: Boolean = {
86 | import Type._
87 | typ match {
88 | case Int8() | Int16() | Int32() | Int64() | Uint8() | Uint16() | Uint32() | Uint64() | Float32() | Float64() | Void() | Bool() => true
89 | case _ => false
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/ListList.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../../../../../../../../../scala.capnp";
2 |
3 | @0xd965c23221c9c77c;
4 |
5 | $Scala.package("org.katis.capnproto.compiler");
6 | $Scala.module("contents");
7 |
8 | struct Contents {
9 | entries @0 :List(List(Text));
10 | }
11 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/ListList.capnp.scala:
--------------------------------------------------------------------------------
1 | // GENERATED CAP'N PROTO FILE, DO NOT EDIT
2 | package org.katis.capnproto.compiler
3 |
4 | import org.katis.capnproto.runtime.implicits._
5 |
6 | object contents {
7 | // START Contents implicits
8 | implicit val Contents$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[Contents] {
9 | def typeId: Long = -3160189064124843233L
10 | }
11 | implicit val Contents$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[Contents] {
12 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 1)
13 | }
14 | implicit val Contents$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[Contents] {
15 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): Contents#Reader = {
16 | Contents.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
17 | }
18 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): Contents#Builder = {
19 | Contents.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
20 | }
21 | }
22 | // END Contents implicits
23 |
24 | object Contents extends Contents
25 | sealed class Contents private() extends org.katis.capnproto.runtime.Struct {
26 | val typeId: Long = -3160189064124843233L
27 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 1)
28 |
29 | override type Reader = ReaderImpl
30 | override type Builder = BuilderImpl
31 |
32 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
33 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
34 |
35 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
36 | def entries: org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]#Reader = {
37 | _getPointerField[org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]](0)
38 | }
39 | object has {
40 | def entries: Boolean = {
41 | _pointerFieldIsNull(0)
42 | }
43 | }
44 | }
45 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
46 | def entries: org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]#Builder = {
47 | _getPointerField[org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]](0)
48 | }
49 | def entries_=(value: org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]#Reader): Unit = {
50 | _setPointerField[org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]](0, value)
51 | }
52 | object has {
53 | def entries: Boolean = {
54 | _pointerFieldIsNull(0)
55 | }
56 | }
57 | object init {
58 | def entries(size: Int): org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]#Builder = {
59 | _initPointerField[org.katis.capnproto.runtime.ListList[org.katis.capnproto.runtime.TextList]](0, size)
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/ListListSpec.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.compiler
2 |
3 | import org.scalatest.{FlatSpec, Matchers}
4 | import contents._
5 | import org.katis.capnproto.runtime.implicits._
6 | import org.katis.capnproto.runtime.MessageBuilder
7 |
8 | class ListListSpec extends FlatSpec with Matchers {
9 | "A ListList" should "allow reading and writing" in {
10 | val builder = new MessageBuilder()
11 | val msg = builder.getRoot[Contents]
12 |
13 | val entries = msg.init.entries(2)
14 | val texts0 = entries.init(0, 4)
15 | val texts1 = entries.init(1, 5)
16 |
17 | texts0(0) = "World"
18 | texts0(1) = "Hello"
19 | texts1(0) = "Bar"
20 | texts1(1) = "Foo"
21 |
22 | val reader = msg.asReader
23 |
24 | val rEntries = reader.entries
25 | val rEntries0 = rEntries(0)
26 | val rEntries1 = rEntries(1)
27 | assert(rEntries0(0).toString == "World")
28 | assert(rEntries0(1).toString == "Hello")
29 | assert(rEntries1(0).toString == "Bar")
30 | assert(rEntries1(1).toString == "Foo")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/SimpleGeneric.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../../../../../../../../../scala.capnp";
2 |
3 | @0xb14f277ff320a8c5;
4 |
5 | $Scala.package("org.katis.capnproto.compiler");
6 | $Scala.module("SimpleGeneric");
7 |
8 | struct GenericMap(Key, Value) {
9 | entries @0 :List(Entry);
10 | struct Entry {
11 | key @0 :Key;
12 | value @1 :Value;
13 | }
14 | }
15 |
16 | struct User {
17 | name @0 :Text;
18 | age @1 :Int8;
19 | }
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/SimpleGeneric.capnp.scala:
--------------------------------------------------------------------------------
1 | // GENERATED CAP'N PROTO FILE, DO NOT EDIT
2 | package org.katis.capnproto.compiler
3 |
4 | import org.katis.capnproto.runtime.implicits._
5 |
6 | object SimpleGeneric {
7 | // START GenericMap#Entry implicits
8 | implicit def GenericMap$Entry$$HasTypeId[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.HasTypeId[GenericMap[Key, Value]#Entry] {
9 | def typeId: Long = -4562728721940766169L
10 | }
11 | implicit def GenericMap$Entry$$HasStructSize[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.HasStructSize[GenericMap[Key, Value]#Entry] {
12 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 2)
13 | }
14 | implicit def GenericMap$Entry$$StructFromSegment[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.StructFromSegment[GenericMap[Key, Value]#Entry] {
15 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): GenericMap[Key, Value]#Entry#Reader = {
16 | GenericMap[Key, Value].Entry.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
17 | }
18 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): GenericMap[Key, Value]#Entry#Builder = {
19 | GenericMap[Key, Value].Entry.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
20 | }
21 | }
22 | // END GenericMap#Entry implicits
23 | // START GenericMap implicits
24 | implicit def GenericMap$$HasTypeId[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.HasTypeId[GenericMap[Key, Value]] {
25 | def typeId: Long = -4648576583519501999L
26 | }
27 | implicit def GenericMap$$HasStructSize[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.HasStructSize[GenericMap[Key, Value]] {
28 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 1)
29 | }
30 | implicit def GenericMap$$StructFromSegment[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] = new org.katis.capnproto.runtime.StructFromSegment[GenericMap[Key, Value]] {
31 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): GenericMap[Key, Value]#Reader = {
32 | GenericMap[Key, Value].Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
33 | }
34 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): GenericMap[Key, Value]#Builder = {
35 | GenericMap[Key, Value].Builder(segment, dataOffset, pointers, dataSize, pointerCount)
36 | }
37 | }
38 | // END GenericMap implicits
39 | // START User implicits
40 | implicit val User$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[User] {
41 | def typeId: Long = -6754264410935672481L
42 | }
43 | implicit val User$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[User] {
44 | val structSize = new org.katis.capnproto.runtime.StructSize(1, 1)
45 | }
46 | implicit val User$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[User] {
47 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): User#Reader = {
48 | User.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
49 | }
50 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): User#Builder = {
51 | User.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
52 | }
53 | }
54 | // END User implicits
55 |
56 | object GenericMap {
57 | def apply[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder]: GenericMap[Key, Value] = new GenericMap[Key, Value]
58 | }
59 | sealed class GenericMap[Key <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder, Value <: org.katis.capnproto.runtime.PointerFamily : org.katis.capnproto.runtime.FromPointer : org.katis.capnproto.runtime.SetPointerBuilder] private() extends org.katis.capnproto.runtime.Struct {
60 | val typeId: Long = -4648576583519501999L
61 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 1)
62 |
63 | override type Reader = ReaderImpl
64 | override type Builder = BuilderImpl
65 |
66 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
67 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
68 |
69 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
70 | def entries: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]#Reader = {
71 | _getPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]](0)
72 | }
73 | object has {
74 | def entries: Boolean = {
75 | _pointerFieldIsNull(0)
76 | }
77 | }
78 | }
79 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
80 | def entries: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]#Builder = {
81 | _getPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]](0)
82 | }
83 | def entries_=(value: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]#Reader): Unit = {
84 | _setPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]](0, value)
85 | }
86 | object has {
87 | def entries: Boolean = {
88 | _pointerFieldIsNull(0)
89 | }
90 | }
91 | object init {
92 | def entries(size: Int): org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]#Builder = {
93 | _initPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.SimpleGeneric.GenericMap[Key, Value]#Entry]](0, size)
94 | }
95 | }
96 | }
97 |
98 | object Entry extends Entry
99 | sealed class Entry private() extends org.katis.capnproto.runtime.Struct {
100 | val typeId: Long = -4562728721940766169L
101 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 2)
102 |
103 | override type Reader = ReaderImpl
104 | override type Builder = BuilderImpl
105 |
106 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
107 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
108 |
109 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
110 | def key: Key#Reader = {
111 | _getPointerField[Key](0)
112 | }
113 | def value: Value#Reader = {
114 | _getPointerField[Value](1)
115 | }
116 | object has {
117 | def key: Boolean = {
118 | _pointerFieldIsNull(0)
119 | }
120 | def value: Boolean = {
121 | _pointerFieldIsNull(1)
122 | }
123 | }
124 | }
125 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
126 | def key: Key#Builder = {
127 | _getPointerField[Key](0)
128 | }
129 | def key_=(value: Key#Reader): Unit = {
130 | _setPointerField[Key](0, value)
131 | }
132 | def value: Value#Builder = {
133 | _getPointerField[Value](1)
134 | }
135 | def value_=(value: Value#Reader): Unit = {
136 | _setPointerField[Value](1, value)
137 | }
138 | object has {
139 | def key: Boolean = {
140 | _pointerFieldIsNull(0)
141 | }
142 | def value: Boolean = {
143 | _pointerFieldIsNull(1)
144 | }
145 | }
146 | object init {
147 | def key(size: Int = 0): Key#Builder = {
148 | _initPointerField[Key](1, size)
149 | }
150 | def value(size: Int = 0): Value#Builder = {
151 | _initPointerField[Value](1, size)
152 | }
153 | }
154 | }
155 | }
156 | }
157 |
158 | object User extends User
159 | sealed class User private() extends org.katis.capnproto.runtime.Struct {
160 | val typeId: Long = -6754264410935672481L
161 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(1, 1)
162 |
163 | override type Reader = ReaderImpl
164 | override type Builder = BuilderImpl
165 |
166 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
167 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
168 |
169 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
170 | def name: org.katis.capnproto.runtime.Text#Reader = {
171 | _getPointerField[org.katis.capnproto.runtime.Text](0)
172 | }
173 | def age: Byte = {
174 | this._getByteField(0)
175 | }
176 | object has {
177 | def name: Boolean = {
178 | _pointerFieldIsNull(0)
179 | }
180 | }
181 | }
182 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
183 | def name: org.katis.capnproto.runtime.Text#Builder = {
184 | _getPointerField[org.katis.capnproto.runtime.Text](0)
185 | }
186 | def name_=(value: org.katis.capnproto.runtime.Text#Reader): Unit = {
187 | _setPointerField[org.katis.capnproto.runtime.Text](0, value)
188 | }
189 | def name_=(value: String): Unit = {
190 | _setPointerField[org.katis.capnproto.runtime.Text](0, org.katis.capnproto.runtime.Text.Reader(value))
191 | }
192 | def age: Byte = {
193 | this._getByteField(0)
194 | }
195 | def age_=(value: Byte): Unit = {
196 | _setByteField(0, value)
197 | }
198 | object has {
199 | def name: Boolean = {
200 | _pointerFieldIsNull(0)
201 | }
202 | }
203 | object init {
204 | def name(size: Int): org.katis.capnproto.runtime.Text#Builder = {
205 | _initPointerField[org.katis.capnproto.runtime.Text](0, size)
206 | }
207 | }
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/SimpleGenericSpec.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.compiler
2 |
3 | import org.katis.capnproto.runtime.implicits._
4 | import org.katis.capnproto.runtime.{MessageBuilder, Text}
5 | import org.scalatest._
6 | import SimpleGeneric._
7 |
8 | class SimpleGenericSpec extends FlatSpec with Matchers {
9 | "A GenericMap" should "be able to read & write Text entries" in {
10 | val builder = new MessageBuilder()
11 | val map = builder.getRoot[GenericMap[Text, Text]]
12 |
13 | var i = 1
14 | for (entry <- map.init.entries(2)) {
15 | entry.key = s"key $i".text
16 | entry.value = s"value $i".text
17 | i += 1
18 | }
19 |
20 | val reader = map.asReader
21 | val entries = reader.entries
22 |
23 | assert(entries(0).key.toString == "key 1")
24 | assert(entries(0).value.toString == "value 1")
25 |
26 | assert(entries(1).key.toString == "key 2")
27 | assert(entries(1).value.toString == "value 2")
28 | }
29 |
30 | it should "be able to read & write struct Entries" in {
31 | val builder = new MessageBuilder()
32 | val map = builder.getRoot[GenericMap[Text, User]]
33 | val values = Vector(("Jane", 36), ("John", 18))
34 | for (((name, age), entry) <- values.zip(map.init.entries(2).toSeq)) {
35 | entry.key = name.text
36 |
37 | val user = entry.init.value()
38 | user.name = name.text
39 | user.age = age.toByte
40 | }
41 |
42 | val reader = map.asReader
43 | val entries = reader.entries
44 |
45 | def checkEntry(i: Int, name: String, age: Int) = {
46 | val entry = entries(i)
47 | assert(entry.key.toString == name)
48 | val user = entry.value
49 | assert(user.name.toString == name)
50 | assert(user.age == age.toByte)
51 | }
52 |
53 | checkEntry(0, "Jane", 36)
54 | checkEntry(1, "John", 18)
55 | }
56 |
57 | it should "be able to read & write entries with nested generics" in {
58 | val builder = new MessageBuilder()
59 | val map = builder.getRoot[GenericMap[Text, GenericMap[Text, Text]]]
60 |
61 | var (i, j) = (0, 0)
62 | for (innerMap <- map.init.entries(2)) {
63 | innerMap.key = s"entry$i".text
64 | for (entry <- innerMap.init.value().init.entries(2)) {
65 | entry.key = s"innerEntry$j".text
66 | entry.value = s"value$j".text
67 | j += 1
68 | }
69 | i += 1
70 | }
71 |
72 | val reader = map.asReader
73 | val entries = reader.entries
74 |
75 | def checkEntry(idx: Int, key: String, innerIdx: Int, innerKey: String, value: String): Unit = {
76 | val e = entries(idx)
77 | assert(e.key.toString == key)
78 | val innerEntries = e.value.entries(innerIdx)
79 | assert(innerEntries.key.toString == innerKey)
80 | assert(innerEntries.value.toString == value)
81 | }
82 |
83 | checkEntry(0, "entry0", 0, "innerEntry0", "value0")
84 | checkEntry(0, "entry0", 1, "innerEntry1", "value1")
85 | checkEntry(1, "entry1", 0, "innerEntry2", "value2")
86 | checkEntry(1, "entry1", 1, "innerEntry3", "value3")
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/MultifileSpec.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.compiler.multifile
2 |
3 | import java.util.{UUID => JavaUUID}
4 |
5 | import order._
6 | import org.katis.capnproto.runtime.MessageBuilder
7 | import org.katis.capnproto.runtime.implicits._
8 | import org.scalatest.{FlatSpec, Matchers}
9 | import util.uuid._
10 |
11 | class MultifileSpec extends FlatSpec with Matchers {
12 | "A multi-file schema" should "work normally" in {
13 | val builder = new MessageBuilder()
14 | val order = builder.getRoot[Order]
15 | val orderId = JavaUUID.randomUUID()
16 | order.init.id().put(orderId)
17 |
18 | val customerId = JavaUUID.randomUUID()
19 | val customer = order.init.customer()
20 | customer.init.id().put(customerId)
21 | customer.name = "Vin Diesel"
22 |
23 | val items = Vector(
24 | ("Carrots", JavaUUID.randomUUID()),
25 | ("Milk", JavaUUID.randomUUID()),
26 | ("Dogfood", JavaUUID.randomUUID())
27 | )
28 | for ((item, (name, id)) <- order.init.items(items.size).zip(items)) {
29 | item.init.id().put(id)
30 | item.name = name
31 | }
32 |
33 | val reader = order.asReader
34 |
35 | reader.id.toJava == orderId
36 | assert(reader.customer.id.toJava == customerId)
37 | assert(reader.customer.name.toString == "Vin Diesel")
38 |
39 | for ((item, (name, id)) <- reader.items.zip(items)) {
40 | assert(item.id.toJava == id)
41 | assert(item.name.toString == name)
42 | }
43 | }
44 |
45 | implicit class UUIDBuilderExt(val uuid: UUID#Builder) {
46 | def put(id: JavaUUID) = {
47 | uuid.lsb = id.getLeastSignificantBits
48 | uuid.msb = id.getMostSignificantBits
49 | }
50 | }
51 |
52 | implicit class UUIDExt(val uuid: UUID#Reader) {
53 | def toJava: JavaUUID = new JavaUUID(uuid.msb, uuid.lsb)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/customer.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../../../../../../../../../../scala.capnp";
2 |
3 | using import "util/uuid.capnp".UUID;
4 |
5 | @0xb9bea4c26be48feb;
6 |
7 | $Scala.package("org.katis.capnproto.compiler.multifile");
8 | $Scala.module("customer");
9 |
10 | struct Customer {
11 | id @0 :UUID;
12 | name @1 :Text;
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/customer.capnp.scala:
--------------------------------------------------------------------------------
1 | // GENERATED CAP'N PROTO FILE, DO NOT EDIT
2 | package org.katis.capnproto.compiler.multifile
3 |
4 | import org.katis.capnproto.runtime.implicits._
5 |
6 | object customer {
7 | // START Customer implicits
8 | implicit val Customer$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[Customer] {
9 | def typeId: Long = -1898055877036248516L
10 | }
11 | implicit val Customer$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[Customer] {
12 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 2)
13 | }
14 | implicit val Customer$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[Customer] {
15 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): Customer#Reader = {
16 | Customer.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
17 | }
18 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): Customer#Builder = {
19 | Customer.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
20 | }
21 | }
22 | // END Customer implicits
23 |
24 | object Customer extends Customer
25 | sealed class Customer private() extends org.katis.capnproto.runtime.Struct {
26 | val typeId: Long = -1898055877036248516L
27 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 2)
28 |
29 | override type Reader = ReaderImpl
30 | override type Builder = BuilderImpl
31 |
32 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
33 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
34 |
35 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
36 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader = {
37 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
38 | }
39 | def name: org.katis.capnproto.runtime.Text#Reader = {
40 | _getPointerField[org.katis.capnproto.runtime.Text](1)
41 | }
42 | object has {
43 | def id: Boolean = {
44 | _pointerFieldIsNull(0)
45 | }
46 | def name: Boolean = {
47 | _pointerFieldIsNull(1)
48 | }
49 | }
50 | }
51 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
52 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
53 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
54 | }
55 | def id_=(value: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader): Unit = {
56 | _setPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, value)
57 | }
58 | def name: org.katis.capnproto.runtime.Text#Builder = {
59 | _getPointerField[org.katis.capnproto.runtime.Text](1)
60 | }
61 | def name_=(value: org.katis.capnproto.runtime.Text#Reader): Unit = {
62 | _setPointerField[org.katis.capnproto.runtime.Text](1, value)
63 | }
64 | def name_=(value: String): Unit = {
65 | _setPointerField[org.katis.capnproto.runtime.Text](1, org.katis.capnproto.runtime.Text.Reader(value))
66 | }
67 | object has {
68 | def id: Boolean = {
69 | _pointerFieldIsNull(0)
70 | }
71 | def name: Boolean = {
72 | _pointerFieldIsNull(1)
73 | }
74 | }
75 | object init {
76 | def id(): org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
77 | _initPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, 0)
78 | }
79 | def name(size: Int): org.katis.capnproto.runtime.Text#Builder = {
80 | _initPointerField[org.katis.capnproto.runtime.Text](1, size)
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/order.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../../../../../../../../../../scala.capnp";
2 |
3 | @0x91eddc4a25fb62b3;
4 |
5 | $Scala.package("org.katis.capnproto.compiler.multifile");
6 | $Scala.module("order");
7 |
8 | using import "customer.capnp".Customer;
9 | using import "util/uuid.capnp".UUID;
10 |
11 | struct Order {
12 | id @0 :UUID;
13 | customer @1 :Customer;
14 | items @2 :List(Item);
15 | }
16 |
17 | struct Item {
18 | id @0 :UUID;
19 | name @1 :Text;
20 | }
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/order.capnp.scala:
--------------------------------------------------------------------------------
1 | // GENERATED CAP'N PROTO FILE, DO NOT EDIT
2 | package org.katis.capnproto.compiler.multifile
3 |
4 | import org.katis.capnproto.runtime.implicits._
5 |
6 | object order {
7 | // START Order implicits
8 | implicit val Order$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[Order] {
9 | def typeId: Long = -7521475027206739292L
10 | }
11 | implicit val Order$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[Order] {
12 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 3)
13 | }
14 | implicit val Order$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[Order] {
15 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): Order#Reader = {
16 | Order.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
17 | }
18 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): Order#Builder = {
19 | Order.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
20 | }
21 | }
22 | // END Order implicits
23 | // START Item implicits
24 | implicit val Item$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[Item] {
25 | def typeId: Long = -1770797472075033903L
26 | }
27 | implicit val Item$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[Item] {
28 | val structSize = new org.katis.capnproto.runtime.StructSize(0, 2)
29 | }
30 | implicit val Item$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[Item] {
31 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): Item#Reader = {
32 | Item.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
33 | }
34 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): Item#Builder = {
35 | Item.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
36 | }
37 | }
38 | // END Item implicits
39 |
40 | object Order extends Order
41 | sealed class Order private() extends org.katis.capnproto.runtime.Struct {
42 | val typeId: Long = -7521475027206739292L
43 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 3)
44 |
45 | override type Reader = ReaderImpl
46 | override type Builder = BuilderImpl
47 |
48 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
49 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
50 |
51 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
52 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader = {
53 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
54 | }
55 | def customer: org.katis.capnproto.compiler.multifile.customer.Customer#Reader = {
56 | _getPointerField[org.katis.capnproto.compiler.multifile.customer.Customer](1)
57 | }
58 | def items: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]#Reader = {
59 | _getPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]](2)
60 | }
61 | object has {
62 | def id: Boolean = {
63 | _pointerFieldIsNull(0)
64 | }
65 | def customer: Boolean = {
66 | _pointerFieldIsNull(1)
67 | }
68 | def items: Boolean = {
69 | _pointerFieldIsNull(2)
70 | }
71 | }
72 | }
73 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
74 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
75 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
76 | }
77 | def id_=(value: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader): Unit = {
78 | _setPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, value)
79 | }
80 | def customer: org.katis.capnproto.compiler.multifile.customer.Customer#Builder = {
81 | _getPointerField[org.katis.capnproto.compiler.multifile.customer.Customer](1)
82 | }
83 | def customer_=(value: org.katis.capnproto.compiler.multifile.customer.Customer#Reader): Unit = {
84 | _setPointerField[org.katis.capnproto.compiler.multifile.customer.Customer](1, value)
85 | }
86 | def items: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]#Builder = {
87 | _getPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]](2)
88 | }
89 | def items_=(value: org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]#Reader): Unit = {
90 | _setPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]](2, value)
91 | }
92 | object has {
93 | def id: Boolean = {
94 | _pointerFieldIsNull(0)
95 | }
96 | def customer: Boolean = {
97 | _pointerFieldIsNull(1)
98 | }
99 | def items: Boolean = {
100 | _pointerFieldIsNull(2)
101 | }
102 | }
103 | object init {
104 | def id(): org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
105 | _initPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, 0)
106 | }
107 | def customer(): org.katis.capnproto.compiler.multifile.customer.Customer#Builder = {
108 | _initPointerField[org.katis.capnproto.compiler.multifile.customer.Customer](1, 0)
109 | }
110 | def items(size: Int): org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]#Builder = {
111 | _initPointerField[org.katis.capnproto.runtime.StructList[org.katis.capnproto.compiler.multifile.order.Item]](2, size)
112 | }
113 | }
114 | }
115 | }
116 |
117 | object Item extends Item
118 | sealed class Item private() extends org.katis.capnproto.runtime.Struct {
119 | val typeId: Long = -1770797472075033903L
120 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(0, 2)
121 |
122 | override type Reader = ReaderImpl
123 | override type Builder = BuilderImpl
124 |
125 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
126 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
127 |
128 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
129 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader = {
130 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
131 | }
132 | def name: org.katis.capnproto.runtime.Text#Reader = {
133 | _getPointerField[org.katis.capnproto.runtime.Text](1)
134 | }
135 | object has {
136 | def id: Boolean = {
137 | _pointerFieldIsNull(0)
138 | }
139 | def name: Boolean = {
140 | _pointerFieldIsNull(1)
141 | }
142 | }
143 | }
144 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
145 | def id: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
146 | _getPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0)
147 | }
148 | def id_=(value: org.katis.capnproto.compiler.multifile.util.uuid.UUID#Reader): Unit = {
149 | _setPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, value)
150 | }
151 | def name: org.katis.capnproto.runtime.Text#Builder = {
152 | _getPointerField[org.katis.capnproto.runtime.Text](1)
153 | }
154 | def name_=(value: org.katis.capnproto.runtime.Text#Reader): Unit = {
155 | _setPointerField[org.katis.capnproto.runtime.Text](1, value)
156 | }
157 | def name_=(value: String): Unit = {
158 | _setPointerField[org.katis.capnproto.runtime.Text](1, org.katis.capnproto.runtime.Text.Reader(value))
159 | }
160 | object has {
161 | def id: Boolean = {
162 | _pointerFieldIsNull(0)
163 | }
164 | def name: Boolean = {
165 | _pointerFieldIsNull(1)
166 | }
167 | }
168 | object init {
169 | def id(): org.katis.capnproto.compiler.multifile.util.uuid.UUID#Builder = {
170 | _initPointerField[org.katis.capnproto.compiler.multifile.util.uuid.UUID](0, 0)
171 | }
172 | def name(size: Int): org.katis.capnproto.runtime.Text#Builder = {
173 | _initPointerField[org.katis.capnproto.runtime.Text](1, size)
174 | }
175 | }
176 | }
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/util/uuid.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../../../../../../../../../../../scala.capnp";
2 |
3 | @0xd7604d0b8d98ed8a;
4 |
5 | $Scala.package("org.katis.capnproto.compiler.multifile.util");
6 | $Scala.module("uuid");
7 |
8 | struct UUID {
9 | lsb @0 :Int64;
10 | msb @1 :Int64;
11 | }
--------------------------------------------------------------------------------
/compilerTest/shared/src/test/scala-2.11/org/katis/capnproto/compiler/multifile/util/uuid.capnp.scala:
--------------------------------------------------------------------------------
1 | // GENERATED CAP'N PROTO FILE, DO NOT EDIT
2 | package org.katis.capnproto.compiler.multifile.util
3 |
4 | import org.katis.capnproto.runtime.implicits._
5 |
6 | object uuid {
7 | // START UUID implicits
8 | implicit val UUID$$HasTypeId = new org.katis.capnproto.runtime.HasTypeId[UUID] {
9 | def typeId: Long = -5078097983031366160L
10 | }
11 | implicit val UUID$$HasStructSize = new org.katis.capnproto.runtime.HasStructSize[UUID] {
12 | val structSize = new org.katis.capnproto.runtime.StructSize(2, 0)
13 | }
14 | implicit val UUID$$StructFromSegment = new org.katis.capnproto.runtime.StructFromSegment[UUID] {
15 | def readerFromSegment(segment: org.katis.capnproto.runtime.SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): UUID#Reader = {
16 | UUID.Reader(segment, dataOffset, pointers, dataSize, pointerCount, nestingLimit)
17 | }
18 | def builderFromSegment(segment: org.katis.capnproto.runtime.SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): UUID#Builder = {
19 | UUID.Builder(segment, dataOffset, pointers, dataSize, pointerCount)
20 | }
21 | }
22 | // END UUID implicits
23 |
24 | object UUID extends UUID
25 | sealed class UUID private() extends org.katis.capnproto.runtime.Struct {
26 | val typeId: Long = -5078097983031366160L
27 | override val structSize: org.katis.capnproto.runtime.StructSize = new org.katis.capnproto.runtime.StructSize(2, 0)
28 |
29 | override type Reader = ReaderImpl
30 | override type Builder = BuilderImpl
31 |
32 | override val Builder: (org.katis.capnproto.runtime.SegmentBuilder, Int, Int, Int, Short) => Builder = new BuilderImpl(_, _, _, _, _)
33 | override val Reader: (org.katis.capnproto.runtime.SegmentReader, Int, Int, Int, Short, Int) => Reader = new ReaderImpl(_, _, _, _, _, _)
34 |
35 | class ReaderImpl(_segment: org.katis.capnproto.runtime.SegmentReader, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short, _nestingLimit: Int) extends super.ReaderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount, _nestingLimit) {
36 | def lsb: Long = {
37 | this._getLongField(0)
38 | }
39 | def msb: Long = {
40 | this._getLongField(1)
41 | }
42 | }
43 | class BuilderImpl(_segment: org.katis.capnproto.runtime.SegmentBuilder, _dataOffset: Int, _pointers: Int, _dataSize: Int, _pointerCount: Short) extends super.BuilderBase(_segment, _dataOffset, _pointers, _dataSize, _pointerCount) {
44 | def lsb: Long = {
45 | this._getLongField(0)
46 | }
47 | def lsb_=(value: Long): Unit = {
48 | _setLongField(0, value)
49 | }
50 | def msb: Long = {
51 | this._getLongField(1)
52 | }
53 | def msb_=(value: Long): Unit = {
54 | _setLongField(1, value)
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Cap'n Proto To-Do example
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/example/js/src/main/scala-2.11/org/katis/capnproto/example/client/Client.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.example.client
2 |
3 | import java.nio.ByteBuffer
4 |
5 | import monix.execution.Cancelable
6 | import monix.execution.Scheduler.Implicits.global
7 | import monix.reactive.Observable
8 | import monix.reactive.observers.Subscriber
9 | import org.katis.capnproto.example.todo._
10 | import org.katis.capnproto.example.todo.ClientMessage._
11 | import org.katis.capnproto.example.todo.{ClientMessage, ServerMessage, Todo}
12 | import org.katis.capnproto.runtime.implicits._
13 | import org.katis.capnproto.runtime._
14 | import org.scalajs.dom._
15 | import org.scalajs.dom.raw.{HTMLButtonElement, HTMLInputElement, WebSocket}
16 |
17 | import scala.collection.mutable
18 | import scala.scalajs.js.JSApp
19 | import scala.scalajs.js.typedarray.TypedArrayBufferOps._
20 | import scala.scalajs.js.typedarray.{ArrayBuffer, TypedArrayBuffer}
21 |
22 | object Client extends JSApp {
23 | implicit class ElementExt(val el: Element) extends AnyVal {
24 | def removeChildren(): Unit = {
25 | while (el.lastChild != null) {
26 | el.removeChild(el.lastChild)
27 | }
28 | }
29 | }
30 |
31 | override def main(): Unit = {
32 | val todoService = new TodoService(s"ws://${window.location.host}/ws")
33 |
34 | var todoText = ""
35 | val input = document.getElementById("todoText").asInstanceOf[HTMLInputElement]
36 | input.oninput = (ev: Event) => {
37 | todoText = input.value
38 | println(todoText)
39 | }
40 |
41 | val btn = document.getElementById("send").asInstanceOf[HTMLButtonElement]
42 | btn.textContent = "Add"
43 | btn.onclick = (ev: MouseEvent) => {
44 | todoService.send(msg => {
45 | msg.init.add().contents = todoText
46 | })
47 | }
48 |
49 | var clientId = 0L
50 | var todos = mutable.ArrayBuffer[Todo#Reader]()
51 |
52 | def redrawTodos(): Unit = {
53 | val todoContainer = document.getElementById("todos")
54 | todoContainer.removeChildren()
55 |
56 | for (todo <- todos) {
57 | val contents = todo.contents.toString
58 | val li = document.createElement("li")
59 | li.appendChild(document.createTextNode(contents))
60 | todoContainer.appendChild(li)
61 | }
62 | }
63 |
64 | todoService.messages.foreach {
65 | case Initial(init) =>
66 | println("Initial message")
67 | clientId = init.clientId
68 | todos.clear()
69 | init.todos.foreach(todo => {
70 | todos += todo
71 | })
72 | redrawTodos()
73 | case Added(todo) =>
74 | println(s"Added message ${todo.contents}")
75 | todos += todo
76 | redrawTodos()
77 | case Removed(todo) =>
78 | println("Removed message")
79 | todos.indexWhere(t => t.id == todo.id) match {
80 | case -1 =>
81 | case n => todos.remove(n)
82 | }
83 | redrawTodos()
84 | case Modified(todo) =>
85 | println("Modified message")
86 | todos.lastIndexWhere(_.id == todo.id) match {
87 | case -1 =>
88 | case n => todos(n) = todo
89 | }
90 | redrawTodos()
91 | case AddFailed(todo) =>
92 | println(s"Failed to add todo")
93 | case RemovalFailed(todo) =>
94 | println(s"Failed to remove todo ${todo.id}")
95 | case ModifyFailed(todo) =>
96 | println(s"Failed to modify todo ${todo.id}")
97 | }
98 | }
99 | }
100 |
101 | class TodoService(address: String) {
102 | private val subscribers = mutable.ArrayBuffer[Subscriber[ByteBuffer]]()
103 | private val bytes = Observable.unsafeCreate[ByteBuffer](subscriber => {
104 | subscribers += subscriber
105 |
106 | new Cancelable {
107 | override def cancel(): Unit = {
108 | subscribers.indexOf(subscriber) match {
109 | case -1 =>
110 | case i => subscribers.remove(i)
111 | }
112 | }
113 | }
114 | })
115 |
116 | private val parser = new MessageStreamParser()
117 |
118 | private def parseStream(bb: ByteBuffer): Observable[MessageReader] = {
119 | parser.update(bb) match {
120 | case Some(msg) => Observable(msg)
121 | case None => Observable.empty
122 | }
123 | }
124 |
125 | val messages = bytes.flatMap(parseStream).map(_.getRoot[ClientMessage])
126 |
127 | private val ws = new WebSocket(address)
128 | ws.binaryType = "arraybuffer"
129 |
130 | ws.onopen = (ev: Event) => {
131 | println("WS opened")
132 | }
133 |
134 | ws.onerror = (ev: ErrorEvent) => {
135 | println(s"WS error: ${ev.message}")
136 | }
137 |
138 | ws.onclose = (ev: CloseEvent) => {
139 | println("WS closed")
140 | }
141 |
142 | ws.onmessage = (ev: MessageEvent) => {
143 | window.console.log("", ev)
144 | val data = ev.data.asInstanceOf[ArrayBuffer]
145 | val bb = TypedArrayBuffer.wrap(data)
146 | subscribers.foreach(_.onNext(bb))
147 | }
148 |
149 | def send(messageInit: (ServerMessage#Builder) => Unit): Unit = {
150 | val builder = new MessageBuilder()
151 | val msg = builder.getRoot[ServerMessage]
152 | messageInit(msg)
153 | val response = Serialize.writeToByteBuffer(builder)
154 | ws.send(response.arrayBuffer())
155 | }
156 | }
--------------------------------------------------------------------------------
/example/jvm/src/main/scala-2.11/org/katis/capnproto/example/server/Server.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.example.server
2 |
3 | import java.time.LocalDateTime
4 | import java.time.format.DateTimeFormatter
5 |
6 | import akka.actor.{Actor, ActorRef, ActorSystem, Props}
7 | import akka.http.scaladsl.Http
8 | import akka.http.scaladsl.model.ws.{BinaryMessage, Message}
9 | import akka.http.scaladsl.server.Directives._
10 | import akka.stream.scaladsl.{Flow, Sink, Source}
11 | import akka.stream.{ActorMaterializer, OverflowStrategy}
12 | import akka.util.ByteString
13 | import org.katis.capnproto.example.server.CapnProtoExts._
14 | import org.katis.capnproto.example.todo.ServerMessage.{Add, Modify, Remove}
15 | import org.katis.capnproto.example.todo._
16 | import org.katis.capnproto.runtime.implicits._
17 | import org.katis.capnproto.runtime.{MessageBuilder, MessageStreamParser, Serialize}
18 |
19 | import scala.collection.{immutable, mutable}
20 | import scala.io.StdIn
21 |
22 | sealed trait WsMessage
23 | case class NewSession(actor: ActorRef) extends WsMessage
24 | case class Disconnected(actor: ActorRef) extends WsMessage
25 |
26 | object CapnProtoExts {
27 | implicit class IterableExt[A](val iterable: Traversable[A]) extends AnyVal {
28 | def zipSameSize[B](makeSizedIterable: (Int) => Traversable[B]): Traversable[(A, B)] = {
29 | val bs = makeSizedIterable(iterable.size)
30 | iterable.toVector.zip(bs.toVector)
31 | }
32 | }
33 | }
34 |
35 | class TodoService(system: ActorSystem) {
36 | private val todoActor = system.actorOf(Props(new TodoActor), "TodoService")
37 |
38 | def todoFlow(): Flow[ByteString, ByteString, Any] = {
39 | val sink = Sink.actorRef[ServerMessage#Reader](todoActor, NewSession(todoActor))
40 |
41 | val in = Flow[ByteString]
42 | .map(_.asByteBuffer)
43 | .statefulMapConcat(() => {
44 | val parser = new MessageStreamParser()
45 | bytes => parser.update(bytes) match {
46 | case Some(msg) => immutable.Iterable(msg)
47 | case None => immutable.Iterable.empty
48 | }
49 | })
50 | .map(_.getRoot[ServerMessage])
51 | .to(sink)
52 |
53 | val out = Source.actorRef[ByteString](1, OverflowStrategy.fail)
54 | .mapMaterializedValue(todoActor ! NewSession(_))
55 |
56 | Flow.fromSinkAndSource(in, out)
57 | }
58 |
59 | case class TodoData(contents: String, created: String)
60 |
61 | private class TodoActor extends Actor {
62 | private val subscribers = mutable.HashMap[Long, ActorRef]()
63 |
64 | def now = DateTimeFormatter.ofPattern("uuuu-MM-dd HH.mm.ss").format(LocalDateTime.now())
65 |
66 | private val nextId = {
67 | var i = 0L
68 | () => { i += 1; i }
69 | }
70 |
71 | private val nextClientId = {
72 | var i = 0L
73 | () => { i += 1; i }
74 | }
75 |
76 | private val todos = mutable.HashMap[Long, TodoData](
77 | (nextId(), TodoData("Hello, world", now))
78 | )
79 |
80 | override def receive = {
81 | case msg: WsMessage =>
82 | msg match {
83 | case NewSession(actor) =>
84 | println("New session")
85 | val clientId = nextClientId()
86 | subscribers(clientId) = actor
87 | sendClientMessage(c => {
88 | val initial = c.init.initial()
89 | initial.clientId = clientId
90 | for (((id, data), todo) <- todos.zipSameSize(initial.init.todos)) {
91 | todo.id = id
92 | todo.contents = data.contents
93 | todo.created = data.created
94 | }
95 | }, Seq(actor))
96 | case Disconnected(actor) =>
97 | subscribers.find(_._2 == actor) match {
98 | case Some((key, _)) => subscribers.remove(key)
99 | case None => println("Could not find subscriber to remove")
100 | }
101 | }
102 | case msg: ServerMessage.Reader =>
103 | msg match {
104 | case Add(todo) =>
105 | val ts = now
106 | val id = nextId()
107 | val data = TodoData(todo.contents.toString, ts)
108 | todos(id) = data
109 | sendClientMessage(c => {
110 | val added = c.init.added()
111 | added.id = id
112 | added.contents = data.contents
113 | added.created = ts
114 | }, subscribers.values)
115 | case Remove(removal) =>
116 | todos.remove(removal.id) match {
117 | case Some(removed) =>
118 | sendClientMessage(_.init.removed().id = removal.id, subscribers.values)
119 | case None =>
120 | sendClientMessage(_.init.removalFailed().id = removal.id, subscribers.get(msg.clientId))
121 | }
122 | case Modify(modified) => todos.get(modified.id) match {
123 | case Some(existing) =>
124 | todos(modified.id) = existing.copy(
125 | contents = modified.contents.toString
126 | )
127 | sendClientMessage(_.init.modified().id = modified.id, subscribers.values)
128 | case None =>
129 | sendClientMessage(_.init.modifyFailed().id = modified.id, subscribers.get(msg.clientId))
130 | }
131 | }
132 | }
133 |
134 | def sendClientMessage(init: (ClientMessage#Builder) => Unit, targets: Iterable[ActorRef] = Seq(sender)): Unit = {
135 | val messageBuilder = new MessageBuilder()
136 | val msg: ClientMessage#Builder = messageBuilder.getRoot[ClientMessage]
137 | init(msg)
138 |
139 | val response = ByteString(Serialize.writeToByteBuffer(messageBuilder))
140 |
141 | targets.foreach(_.tell(response, self))
142 | }
143 | }
144 | }
145 |
146 | object Server {
147 | def main(args: Array[String]): Unit = {
148 | implicit val system = ActorSystem("capnp-example")
149 | implicit val materializer = ActorMaterializer()
150 | implicit val executionContext = system.dispatcher
151 |
152 | val service = new TodoService(system)
153 |
154 | val wsMessage = Flow[Message]
155 | .flatMapConcat{
156 | case BinaryMessage.Strict(bytes) => Source(immutable.Iterable(bytes))
157 | case BinaryMessage.Streamed(bytes) => bytes
158 | }
159 | .via(service.todoFlow())
160 | .map(BinaryMessage.Strict)
161 |
162 | val route = get {
163 | pathSingleSlash {
164 | getFromFile("index.html")
165 | } ~ path("ws") {
166 | handleWebSocketMessages(wsMessage)
167 | } ~
168 | path("index.html")(getFromFile("index.html")) ~
169 | getFromDirectory(".")
170 | }
171 |
172 | val port = 8087
173 | val bindingFuture = Http().bindAndHandle(route, "localhost", port)
174 | println(s"Server online at http://localhost:$port")
175 | println("Press RETURN to stop")
176 |
177 | StdIn.readLine()
178 | bindingFuture
179 | .flatMap(_.unbind())
180 | .onComplete(_ => system.terminate())
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/example/todo.capnp:
--------------------------------------------------------------------------------
1 | using Scala = import "../scala.capnp";
2 |
3 | @0xbba67e30383fe749;
4 | $Scala.package("org.katis.capnproto.example");
5 | $Scala.module("todo");
6 |
7 | struct ClientMessage {
8 | union {
9 | initial :group {
10 | clientId @0 :UInt64;
11 | todos @1 :List(Todo);
12 | }
13 | added @2 :Todo;
14 | removed @3 :Todo;
15 | modified @4 :Todo;
16 |
17 | addFailed @5 :Todo;
18 | removalFailed @6 :Todo;
19 | modifyFailed @7 :Todo;
20 | }
21 | }
22 |
23 | struct ServerMessage {
24 | clientId @0 :UInt64;
25 | union {
26 | add @1 :Todo;
27 | remove @2 :Todo;
28 | modify @3 :Todo;
29 | }
30 | }
31 |
32 | struct Todo {
33 | id @0 :UInt64;
34 | contents @1 :Text;
35 | created @2 :Text;
36 | }
37 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 0.13.8
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | logLevel := Level.Warn
2 |
3 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.12")
4 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3")
5 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/AnyPointer.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object AnyPointer extends AnyPointer
4 | sealed class AnyPointer private() extends PointerFamily {
5 | type Builder = BuilderImpl
6 | type Reader = ReaderImpl
7 |
8 | class ReaderImpl(val segment: SegmentReader, val pointer: Int, val nestingLimit: Int) {
9 | def isNull: Boolean = {
10 | WirePointer.isNull(this.segment.buffer.getLong(this.pointer * Constants.BYTES_PER_WORD))
11 | }
12 |
13 | def getAs[T <: PointerFamily : FromPointer]: T#Reader = {
14 | val factory = implicitly[FromPointer[T]]
15 | factory.fromPointerReader(this.segment, this.pointer, this.nestingLimit)
16 | }
17 | }
18 |
19 | class BuilderImpl(val segment: SegmentBuilder, val pointer: Int) {
20 |
21 | def isNull: Boolean = {
22 | WirePointer.isNull(this.segment.buffer.getLong(this.pointer * Constants.BYTES_PER_WORD))
23 | }
24 |
25 | def getAs[T <: PointerFamily : FromPointer]: T#Builder = {
26 | val factory = implicitly[FromPointer[T]]
27 | factory.fromPointerBuilder(this.segment, this.pointer)
28 | }
29 |
30 | def initAs[T <: PointerFamily : FromPointer]: T#Builder = {
31 | val factory = implicitly[FromPointer[T]]
32 | factory.initFromPointerBuilder(this.segment, this.pointer, 0)
33 | }
34 |
35 | def initAs[T <: PointerFamily : FromPointer](elementCount: Int): T#Builder = {
36 | val factory = implicitly[FromPointer[T]]
37 | factory.initFromPointerBuilder(this.segment, this.pointer, elementCount)
38 | }
39 |
40 | def setAs[T <: PointerFamily : SetPointerBuilder](reader: T#Reader) {
41 | implicitly[SetPointerBuilder[T]].setPointerBuilder(this.segment, this.pointer, reader)
42 | }
43 |
44 | def asReader(): Reader = {
45 | new Reader(segment, pointer, 0x7fffffff)
46 | }
47 |
48 | def clear() {
49 | WireHelpers.zeroObject(this.segment, this.pointer)
50 | this.segment.buffer.putLong(this.pointer * 8, 0L)
51 | }
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Arena.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | trait Arena {
4 |
5 | def tryGetSegment(id: Int): SegmentReader
6 |
7 | def checkReadLimit(numBytes: Int): Unit
8 | }
9 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ArrayInputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | class ArrayInputStream(buffer: ByteBuffer) extends BufferedInputStream {
6 |
7 | val buf = buffer.asReadOnlyBuffer()
8 |
9 | def read(dst: ByteBuffer): Int = {
10 | val size = dst.remaining()
11 | val slice = this.buf.slice()
12 | slice.limit(size)
13 | dst.put(slice)
14 | this.buf.position(this.buf.position() + size)
15 | size
16 | }
17 |
18 | def getReadBuffer(): ByteBuffer = this.buf
19 |
20 | def close() {
21 | return
22 | }
23 |
24 | def isOpen(): Boolean = true
25 | }
26 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ArrayOutputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.io.IOException
4 | import java.nio.ByteBuffer
5 |
6 | class ArrayOutputStream(buffer: ByteBuffer) extends BufferedOutputStream {
7 |
8 | val buf = buffer.duplicate()
9 |
10 | def write(src: ByteBuffer): Int = {
11 | val available = this.buf.remaining()
12 | val size = src.remaining()
13 | if (available < size) {
14 | throw new IOException("backing buffer was not large enough")
15 | }
16 | this.buf.put(src)
17 | size
18 | }
19 |
20 | def writeBuffer: ByteBuffer = this.buf
21 |
22 | def close() {}
23 |
24 | def isOpen: Boolean = true
25 |
26 | def flush() {}
27 | }
28 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/BufferedInputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.ReadableByteChannel
5 |
6 | trait BufferedInputStream extends ReadableByteChannel {
7 |
8 | def getReadBuffer(): ByteBuffer
9 | }
10 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/BufferedInputStreamWrapper.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.ReadableByteChannel
5 |
6 | import BufferedInputStreamWrapper._
7 |
8 | object BufferedInputStreamWrapper {
9 |
10 | def readAtLeast(reader: ReadableByteChannel, buf: ByteBuffer, minBytes: Int): Int = {
11 | var numRead = 0
12 | while (numRead < minBytes) {
13 | val res = reader.read(buf)
14 | if (res < 0) {
15 | throw new Error("premature EOF")
16 | }
17 | numRead += res
18 | }
19 | numRead
20 | }
21 | }
22 |
23 | class BufferedInputStreamWrapper(chan: ReadableByteChannel) extends BufferedInputStream {
24 |
25 | private val inner = chan
26 |
27 | private val buf = ByteBuffer.allocate(8192)
28 |
29 | this.buf.limit(0)
30 |
31 | def read(dst: ByteBuffer): Int = {
32 | var numBytes = dst.remaining()
33 | if (numBytes < this.buf.remaining()) {
34 | val slice = this.buf.slice()
35 | slice.limit(numBytes)
36 | dst.put(slice)
37 | this.buf.position(this.buf.position() + numBytes)
38 | numBytes
39 | } else {
40 | val fromFirstBuffer = this.buf.remaining()
41 | val slice = this.buf.slice()
42 | slice.limit(fromFirstBuffer)
43 | dst.put(slice)
44 | numBytes -= fromFirstBuffer
45 | if (numBytes <= this.buf.capacity()) {
46 | this.buf.clear()
47 | val n = readAtLeast(this.inner, this.buf, numBytes)
48 | this.buf.rewind()
49 | val slice = this.buf.slice()
50 | slice.limit(numBytes)
51 | dst.put(slice)
52 | this.buf.limit(n)
53 | this.buf.position(numBytes)
54 | fromFirstBuffer + numBytes
55 | } else {
56 | this.buf.clear()
57 | this.buf.limit(0)
58 | fromFirstBuffer + readAtLeast(this.inner, dst, numBytes)
59 | }
60 | }
61 | }
62 |
63 | def getReadBuffer(): ByteBuffer = {
64 | if (this.buf.remaining() == 0) {
65 | this.buf.clear()
66 | val n = readAtLeast(this.inner, this.buf, 1)
67 | this.buf.rewind()
68 | this.buf.limit(n)
69 | }
70 | this.buf
71 | }
72 |
73 | def close() {
74 | this.inner.close()
75 | }
76 |
77 | def isOpen(): Boolean = this.inner.isOpen
78 | }
79 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/BufferedOutputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.WritableByteChannel
5 |
6 | trait BufferedOutputStream extends WritableByteChannel {
7 |
8 | def writeBuffer: ByteBuffer
9 |
10 | def flush(): Unit
11 | }
12 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/BufferedOutputStreamWrapper.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.WritableByteChannel
5 |
6 | class BufferedOutputStreamWrapper(w: WritableByteChannel) extends BufferedOutputStream {
7 |
8 | private val inner = w
9 |
10 | private val buf = ByteBuffer.allocate(8192)
11 |
12 | def write(src: ByteBuffer): Int = {
13 | val available = this.buf.remaining()
14 | val size = src.remaining()
15 | if (size <= available) {
16 | this.buf.put(src)
17 | } else if (size <= this.buf.capacity()) {
18 | val slice = src.slice()
19 | slice.limit(available)
20 | this.buf.put(slice)
21 | this.buf.rewind()
22 | while (this.buf.hasRemaining()) {
23 | this.inner.write(this.buf)
24 | }
25 | this.buf.rewind()
26 | src.position(src.position() + available)
27 | this.buf.put(src)
28 | } else {
29 | val pos = this.buf.position()
30 | this.buf.rewind()
31 | val slice = this.buf.slice()
32 | slice.limit(pos)
33 | while (slice.hasRemaining()) {
34 | this.inner.write(slice)
35 | }
36 | while (src.hasRemaining()) {
37 | this.inner.write(src)
38 | }
39 | }
40 | size
41 | }
42 |
43 | def writeBuffer(): ByteBuffer = this.buf
44 |
45 | def close() {
46 | this.inner.close()
47 | }
48 |
49 | def isOpen(): Boolean = this.inner.isOpen
50 |
51 | def flush() {
52 | val pos = this.buf.position()
53 | this.buf.rewind()
54 | this.buf.limit(pos)
55 | this.inner.write(this.buf)
56 | this.buf.clear()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/BuilderArena.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.{ByteBuffer, ByteOrder}
4 | import java.util
5 |
6 | import BuilderArena._
7 |
8 | object BuilderArena {
9 |
10 | object AllocationStrategy extends Enumeration {
11 | type AllocationStrategy = Value
12 |
13 | val FIXED_SIZE = Value
14 |
15 | val GROW_HEURISTICALLY = Value
16 | }
17 |
18 | val SUGGESTED_FIRST_SEGMENT_WORDS = 1024
19 |
20 | val SUGGESTED_ALLOCATION_STRATEGY = AllocationStrategy.GROW_HEURISTICALLY
21 |
22 | class AllocateResult(val segment: SegmentBuilder, val offset: Int)
23 | }
24 |
25 | class BuilderArena(firstSegmentSizeWords: Int, val allocationStrategy: AllocationStrategy.Value)
26 | extends Arena {
27 |
28 | val segments = new util.ArrayList[SegmentBuilder]()
29 |
30 | var nextSize: Int = firstSegmentSizeWords
31 |
32 | val segment0 = new SegmentBuilder(ByteBuffer.allocate(firstSegmentSizeWords * Constants.BYTES_PER_WORD),
33 | this)
34 |
35 | segment0.buffer.order(ByteOrder.LITTLE_ENDIAN)
36 |
37 | this.segments.add(segment0)
38 |
39 | def tryGetSegment(id: Int): SegmentReader = this.segments.get(id)
40 |
41 | def getSegment(id: Int): SegmentBuilder = this.segments.get(id)
42 |
43 | def checkReadLimit(numBytes: Int) {
44 | }
45 |
46 | def allocate(amount: Int): AllocateResult = {
47 | val len = this.segments.size
48 | val result = this.segments.get(len - 1).allocate(amount)
49 | if (result != SegmentBuilder.FAILED_ALLOCATION) {
50 | return new AllocateResult(this.segments.get(len - 1), result)
51 | }
52 | val size = Math.max(amount, this.nextSize)
53 | val newSegment = new SegmentBuilder(ByteBuffer.allocate(size * Constants.BYTES_PER_WORD), this)
54 | this.allocationStrategy match {
55 | case AllocationStrategy.GROW_HEURISTICALLY => this.nextSize += size
56 | case _ => //break
57 | }
58 | newSegment.buffer.order(ByteOrder.LITTLE_ENDIAN)
59 | newSegment.id = len
60 | this.segments.add(newSegment)
61 | new AllocateResult(newSegment, newSegment.allocate(amount))
62 | }
63 |
64 | def getSegmentsForOutput(): Array[ByteBuffer] = {
65 | val result = Array.ofDim[ByteBuffer](this.segments.size)
66 | for (ii <- 0 until this.segments.size) {
67 | val segment = segments.get(ii)
68 | segment.buffer.rewind()
69 | val slice = segment.buffer.slice()
70 | slice.limit(segment.currentSize() * Constants.BYTES_PER_WORD)
71 | slice.order(ByteOrder.LITTLE_ENDIAN)
72 | result(ii) = slice
73 | }
74 | result
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ByteBufferList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | import scala.annotation.tailrec
6 | import scala.collection.mutable
7 |
8 | class ByteBufferList() {
9 | private[runtime] val buffers = mutable.ArrayBuffer[ByteBuffer]()
10 |
11 | def add(bb: ByteBuffer): Unit = {
12 | buffers += bb
13 | }
14 |
15 | @tailrec
16 | final def read(sink: ByteBuffer): Boolean = {
17 | if (buffers.isEmpty) return false
18 |
19 | val bb = buffers(0)
20 | val bs = if (bb.remaining() > sink.remaining()) {
21 | val slice = bb.slice()
22 | slice.limit(sink.remaining())
23 | bb.position(bb.position() + sink.remaining())
24 | slice
25 | } else {
26 | bb
27 | }
28 |
29 | sink.put(bs)
30 | if (!bb.hasRemaining) {
31 | buffers.remove(0)
32 | }
33 |
34 | if (sink.hasRemaining) {
35 | read(sink)
36 | } else {
37 | sink.flip()
38 | true
39 | }
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Constants.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object Constants {
4 |
5 | val BITS_PER_BYTE = 8
6 |
7 | val BITS_PER_POINTER = 64
8 |
9 | val BITS_PER_WORD = 64
10 |
11 | val BYTES_PER_WORD = 8
12 |
13 | val POINTER_SIZE_IN_WORDS = 1
14 |
15 | val WORDS_PER_POINTER = 1
16 | }
17 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Data.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | object Data extends Data
6 | class Data private() extends PointerFamily {
7 | data =>
8 |
9 | type Builder = DataBuilder
10 | type Reader = DataReader
11 | }
12 |
13 | class DataReader(val buffer: ByteBuffer = ByteBuffer.allocate(0),
14 | val offset: Int = 0,
15 | val size: Int = 0) {
16 | def this(bytes: Array[Byte]) {
17 | this(ByteBuffer.wrap(bytes), 0, bytes.length)
18 | }
19 |
20 | def asByteBuffer(): ByteBuffer = {
21 | val dup = this.buffer.asReadOnlyBuffer()
22 | dup.position(this.offset)
23 | val result = dup.slice()
24 | result.limit(this.size)
25 | result
26 | }
27 |
28 | def toArray: Array[Byte] = {
29 | val dup = this.buffer.duplicate()
30 | val result = Array.ofDim[Byte](this.size)
31 | dup.position(this.offset)
32 | dup.get(result, 0, this.size)
33 | result
34 | }
35 | }
36 |
37 | class DataBuilder(val buffer: ByteBuffer = ByteBuffer.allocate(0),
38 | val offset: Int = 0,
39 | val size: Int = 0) {
40 | def asByteBuffer(): ByteBuffer = {
41 | val dup = this.buffer.duplicate()
42 | dup.position(this.offset)
43 | val result = dup.slice()
44 | result.limit(this.size)
45 | result
46 | }
47 |
48 | def toArray: Array[Byte] = {
49 | val dup = this.buffer.duplicate()
50 | val result = Array.ofDim[Byte](this.size)
51 | dup.position(this.offset)
52 | dup.get(result, 0, this.size)
53 | result
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/DataList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import implicits._
4 |
5 | object DataList extends DataList
6 | sealed class DataList private() extends List[Data#Builder, Data#Reader](ElementSize.POINTER.toByte) {
7 | type Builder = BuilderImpl
8 | type Reader = ReaderImpl
9 |
10 | def Reader(segment: SegmentReader,
11 | ptr: Int,
12 | elementCount: Int,
13 | step: Int,
14 | structDataSize: Int,
15 | structPointerCount: Short,
16 | nestingLimit: Int): Reader = {
17 | new Reader(segment, ptr, elementCount, step, structDataSize, structPointerCount, nestingLimit)
18 | }
19 |
20 | def Builder(segment: SegmentBuilder,
21 | ptr: Int,
22 | elementCount: Int,
23 | step: Int,
24 | structDataSize: Int,
25 | structPointerCount: Short): Builder = {
26 | new Builder(segment, ptr, elementCount, step, structDataSize, structPointerCount)
27 | }
28 |
29 | class ReaderImpl(segment: SegmentReader,
30 | ptr: Int,
31 | elementCount: Int,
32 | step: Int,
33 | structDataSize: Int,
34 | structPointerCount: Short,
35 | nestingLimit: Int) extends ReaderBase(segment, ptr, elementCount, step, structDataSize, structPointerCount,
36 | nestingLimit) {
37 |
38 | def apply(idx: Int): Data.Reader = _getPointerElement[Data](idx)
39 |
40 | def get(idx: Int): DataReader = _getPointerElement[Data](idx)
41 | }
42 |
43 | class BuilderImpl(segment: SegmentBuilder,
44 | ptr: Int,
45 | elementCount: Int,
46 | step: Int,
47 | structDataSize: Int,
48 | structPointerCount: Short) extends BuilderBase(segment, ptr, elementCount, step, structDataSize,
49 | structPointerCount) {
50 |
51 | def apply(idx: Int): Data.Builder = _getPointerElement[Data](idx)
52 |
53 | def get(idx: Int): Data.Builder = _getPointerElement[Data](idx)
54 |
55 | def update(index: Int, value: Data.Reader) {
56 | _setPointerElement[Data](index, value)
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/DecodeException.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | class DecodeException(message: String) extends RuntimeException(message)
4 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ElementSize.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object ElementSize {
4 |
5 | val VOID: Byte = 0
6 |
7 | val BIT: Byte = 1
8 |
9 | val BYTE: Byte = 2
10 |
11 | val TWO_BYTES: Byte = 3
12 |
13 | val FOUR_BYTES: Byte = 4
14 |
15 | val EIGHT_BYTES: Byte = 5
16 |
17 | val POINTER: Byte = 6
18 |
19 | val INLINE_COMPOSITE: Byte = 7
20 |
21 | def dataBitsPerElement(size: Byte): Int = size match {
22 | case VOID => 0
23 | case BIT => 1
24 | case BYTE => 8
25 | case TWO_BYTES => 16
26 | case FOUR_BYTES => 32
27 | case EIGHT_BYTES => 64
28 | case POINTER => 0
29 | case INLINE_COMPOSITE => 0
30 | case _ => throw new Error("impossible field size: " + size)
31 | }
32 |
33 | def pointersPerElement(size: Byte): Short = size match {
34 | case POINTER => 1
35 | case _ => 0
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Enum.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | trait FromShort[T] {
4 | def fromShort(short: Short): Option[T]
5 | }
6 |
7 | trait HasEnumValues[T <: Enum] {
8 | def enumValues: Seq[T]
9 | }
10 |
11 | abstract class Enum(val index: Short)
12 |
13 | trait EnumModule[T <: Enum] {
14 | def apply(value: Short): Option[T]
15 | def enumValues: Seq[T]
16 |
17 | object List extends List
18 | class List private() extends org.katis.capnproto.runtime.List[T, T](ElementSize.TWO_BYTES.toByte) {
19 | override type Builder = this.BuilderImpl
20 | override type Reader = this.ReaderImpl
21 |
22 | private def clampOrdinal[A](values: Seq[A], ordinal: Short): A = {
23 | var index = ordinal
24 | if (ordinal < 0 || ordinal >= values.size) {
25 | index = (values.size - 1).toShort
26 | }
27 | values(index)
28 | }
29 |
30 | class ReaderImpl(segment: SegmentReader,
31 | ptr: Int,
32 | elementCount: Int,
33 | step: Int,
34 | structDataSize: Int,
35 | structPointerCount: Short,
36 | nestingLimit: Int)
37 | extends ReaderBase(segment,
38 | ptr,
39 | elementCount,
40 | step,
41 | structDataSize,
42 | structPointerCount,
43 | nestingLimit) {
44 |
45 | reader =>
46 |
47 | def apply(idx: Int): T = clampOrdinal(enumValues, _getShortElement(idx))
48 | }
49 |
50 | class BuilderImpl(segment: SegmentBuilder,
51 | ptr: Int,
52 | elementCount: Int,
53 | step: Int,
54 | structDataSize: Int,
55 | structPointerCount: Short)
56 | extends BuilderBase(segment,
57 | ptr,
58 | elementCount,
59 | step,
60 | structDataSize,
61 | structPointerCount) {
62 |
63 | builder =>
64 |
65 | def update(index: Int, value: T) {
66 | _setShortElement(index, value.index)
67 | }
68 |
69 | override def apply(idx: Int): T = clampOrdinal(enumValues, _getShortElement(idx))
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/EnumList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | class EnumList[T <: Enum : HasEnumValues] extends List[T, T](ElementSize.TWO_BYTES) {
4 | override type Builder = this.BuilderImpl
5 | override type Reader = this.ReaderImpl
6 |
7 | private val enumValues = implicitly[HasEnumValues[T]].enumValues
8 |
9 | private def clampOrdinal[A](values: Seq[A], ordinal: Short): A = {
10 | var index = ordinal
11 | if (ordinal < 0 || ordinal >= values.size) {
12 | index = (values.size - 1).toShort
13 | }
14 | values(index)
15 | }
16 |
17 | class ReaderImpl(segment: SegmentReader,
18 | ptr: Int,
19 | elementCount: Int,
20 | step: Int,
21 | structDataSize: Int,
22 | structPointerCount: Short,
23 | nestingLimit: Int)
24 | extends ReaderBase(segment,
25 | ptr,
26 | elementCount,
27 | step,
28 | structDataSize,
29 | structPointerCount,
30 | nestingLimit) {
31 |
32 | reader =>
33 |
34 | def apply(idx: Int): T = clampOrdinal(enumValues, _getShortElement(idx))
35 |
36 | def get(idx: Int): T = clampOrdinal(enumValues, _getShortElement(idx))
37 | }
38 |
39 | class BuilderImpl(segment: SegmentBuilder,
40 | ptr: Int,
41 | elementCount: Int,
42 | step: Int,
43 | structDataSize: Int,
44 | structPointerCount: Short)
45 | extends BuilderBase(segment,
46 | ptr,
47 | elementCount,
48 | step,
49 | structDataSize,
50 | structPointerCount) {
51 |
52 | builder =>
53 |
54 | def update(index: Int, value: T) {
55 | _setShortElement(index, value.index)
56 | }
57 |
58 | override def apply(idx: Int): T = clampOrdinal(enumValues, _getShortElement(idx))
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/FarPointer.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | object FarPointer {
6 |
7 | def getSegmentId(ref: Long): Int = WirePointer.upper32Bits(ref)
8 |
9 | def positionInSegment(ref: Long): Int = WirePointer.offsetAndKind(ref) >>> 3
10 |
11 | def isDoubleFar(ref: Long): Boolean = {
12 | ((WirePointer.offsetAndKind(ref) >>> 2) & 1) != 0
13 | }
14 |
15 | def setSegmentId(buffer: ByteBuffer, offset: Int, segmentId: Int) {
16 | buffer.putInt(8 * offset + 4, segmentId)
17 | }
18 |
19 | def set(buffer: ByteBuffer,
20 | offset: Int,
21 | isDoubleFar: Boolean,
22 | pos: Int) {
23 | val idf = if (isDoubleFar) 1 else 0
24 | WirePointer.setOffsetAndKind(buffer, offset, (pos << 3) | (idf << 2) | WirePointer.FAR)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/GeneratedClassSupport.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object GeneratedClassSupport {
4 |
5 | def decodeRawBytes(s: String): SegmentReader = {
6 | val buffer = java.nio.ByteBuffer.wrap(s.getBytes("ISO_8859-1")).asReadOnlyBuffer()
7 | buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN)
8 | new SegmentReader(buffer, new ReaderArena(Array.ofDim[java.nio.ByteBuffer](0), 0x7fffffffffffffffL))
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/List.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | trait HasElementSize[T] {
4 | def elementSize: Byte
5 | }
6 |
7 | trait ListFromSegment[T <: PointerFamily] extends ListReader.Factory[T#Reader] with ListBuilder.Factory[T#Builder]
8 |
9 | abstract class List[ElementBuilder, ElementReader](val elementSize: Byte) extends PointerFamily {
10 |
11 | type Builder <: BuilderBase
12 | type Reader <: ReaderBase
13 |
14 | abstract class BuilderBase(
15 | segment: SegmentBuilder,
16 | ptr: Int,
17 | elementCount: Int,
18 | step: Int,
19 | structDataSize: Int,
20 | structPointerCount: Short
21 | ) extends ListBuilder(segment,
22 | ptr,
23 | elementCount,
24 | step,
25 | structDataSize,
26 | structPointerCount) with Seq[ElementBuilder] with Traversable[ElementBuilder] with IndexedSeq[ElementBuilder] {
27 |
28 | builder =>
29 |
30 | override def length: Int = super[ListBuilder].size()
31 |
32 | override def size: Int = super[ListBuilder].size()
33 |
34 | override def foreach[U](f: (ElementBuilder) => U): Unit = {
35 | for (i <- 0 until size) {
36 | f(apply(i))
37 | }
38 | }
39 |
40 | override def iterator: Iterator[ElementBuilder] = new Iterator[ElementBuilder] {
41 | var i = 0
42 | override def hasNext: Boolean = i < builder.length
43 |
44 | override def next(): ElementBuilder = {
45 | val v = apply(i)
46 | i += 1
47 | v
48 | }
49 | }
50 | }
51 |
52 | abstract class ReaderBase(
53 | segment: SegmentReader,
54 | ptr: Int,
55 | elementCount: Int,
56 | step: Int,
57 | structDataSize: Int,
58 | structPointerCount: Short,
59 | nestingLimit: Int
60 | ) extends ListReader(segment,
61 | ptr,
62 | elementCount,
63 | step,
64 | structDataSize,
65 | structPointerCount,
66 | nestingLimit) with Seq[ElementReader] with Traversable[ElementReader] with IndexedSeq[ElementReader] {
67 | reader =>
68 |
69 | override def length: Int = super[ListReader].size
70 |
71 | override def size: Int = super[ListReader].size
72 |
73 | override def foreach[U](f: (ElementReader) => U): Unit = {
74 | for (i <- 0 until size) {
75 | f(apply(i))
76 | }
77 | }
78 |
79 | override def iterator: Iterator[ElementReader] = new Iterator[ElementReader] {
80 | var i = 0
81 | override def hasNext: Boolean = i < reader.length
82 |
83 | override def next(): ElementReader = {
84 | val v = apply(i)
85 | i += 1
86 | v
87 | }
88 | }
89 | }
90 | }
91 |
92 |
93 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ListBuilder.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object ListBuilder {
4 | trait Factory[Builder] {
5 | def Builder(segment: SegmentBuilder,
6 | ptr: Int,
7 | elementCount: Int,
8 | step: Int,
9 | structDataSize: Int,
10 | structPointerCount: Short): Builder
11 | }
12 | }
13 |
14 | class ListBuilder(val segment: SegmentBuilder,
15 | val ptr: Int,
16 | val elementCount: Int,
17 | val step: Int,
18 | val structDataSize: Int,
19 | val structPointerCount: Short) {
20 |
21 | def size(): Int = this.elementCount
22 |
23 | protected def _getBooleanElement(index: Int): Boolean = {
24 | val bindex = index.toLong * this.step
25 | val b = this.segment.buffer.get(this.ptr + (bindex / Constants.BITS_PER_BYTE).toInt)
26 | (b & (1 << (bindex % 8))) != 0
27 | }
28 |
29 | protected def _getByteElement(index: Int): Byte = {
30 | this.segment.buffer.get(this.ptr +
31 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
32 | }
33 |
34 | protected def _getShortElement(index: Int): Short = {
35 | this.segment.buffer.getShort(this.ptr +
36 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
37 | }
38 |
39 | protected def _getIntElement(index: Int): Int = {
40 | this.segment.buffer.getInt(this.ptr +
41 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
42 | }
43 |
44 | protected def _getLongElement(index: Int): Long = {
45 | this.segment.buffer.getLong(this.ptr +
46 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
47 | }
48 |
49 | protected def _getFloatElement(index: Int): Float = {
50 | this.segment.buffer.getFloat(this.ptr +
51 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
52 | }
53 |
54 | protected def _getDoubleElement(index: Int): Double = {
55 | this.segment.buffer.getDouble(this.ptr +
56 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
57 | }
58 |
59 | protected def _setBooleanElement(index: Int, value: Boolean) {
60 | val bitOffset = index * this.step
61 | val bitnum = (bitOffset % 8).toByte
62 | val position = (this.ptr + (bitOffset / 8)).toInt
63 | val oldValue = this.segment.buffer.get(position)
64 | this.segment.buffer.put(position, ((oldValue & (~(1 << bitnum))) | ((if (value) 1 else 0) << bitnum)).toByte)
65 | }
66 |
67 | protected def _setByteElement(index: Int, value: Byte) {
68 | this.segment.buffer.put(this.ptr +
69 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
70 | }
71 |
72 | protected def _setShortElement(index: Int, value: Short) {
73 | this.segment.buffer.putShort(this.ptr +
74 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
75 | }
76 |
77 | protected def _setIntElement(index: Int, value: Int) {
78 | this.segment.buffer.putInt(this.ptr +
79 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
80 | }
81 |
82 | protected def _setLongElement(index: Int, value: Long) {
83 | this.segment.buffer.putLong(this.ptr +
84 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
85 | }
86 |
87 | protected def _setFloatElement(index: Int, value: Float) {
88 | this.segment.buffer.putFloat(this.ptr +
89 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
90 | }
91 |
92 | protected def _setDoubleElement(index: Int, value: Double) {
93 | this.segment.buffer.putDouble(this.ptr +
94 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt, value)
95 | }
96 |
97 | protected def _getStructElement[T <: Struct : StructFromSegment](index: Int): T#Builder = {
98 | val indexBit = index.toLong * this.step
99 | val structData = this.ptr + (indexBit / Constants.BITS_PER_BYTE).toInt
100 | val structPointers = (structData + (this.structDataSize / 8)) / 8
101 | implicitly[StructFromSegment[T]].builderFromSegment(this.segment, structData, structPointers, this.structDataSize, this.structPointerCount)
102 | }
103 |
104 | protected def _getPointerElement[T <: PointerFamily : FromPointer](index: Int): T#Builder = {
105 | implicitly[FromPointer[T]].fromPointerBuilder(this.segment, (this.ptr +
106 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt) /
107 | Constants.BYTES_PER_WORD)
108 | }
109 |
110 | protected def _initPointerElement[T <: PointerFamily : FromPointer](index: Int, elementCount: Int): T#Builder = {
111 | implicitly[FromPointer[T]].initFromPointerBuilder(this.segment, (this.ptr +
112 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt) /
113 | Constants.BYTES_PER_WORD, elementCount)
114 | }
115 |
116 | protected def _setPointerElement[T <: PointerFamily : SetPointerBuilder](index: Int, value: T#Reader) {
117 | implicitly[SetPointerBuilder[T]].setPointerBuilder(this.segment, (this.ptr +
118 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt) /
119 | Constants.BYTES_PER_WORD, value)
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ListList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object ListList {
4 | def apply[L <: PointerFamily : ListFromSegment : FromPointer]: ListList[L] = new ListList[L]
5 | }
6 |
7 | class ListList[L <: PointerFamily : ListFromSegment : FromPointer]
8 | extends List[L#Builder, L#Reader](ElementSize.POINTER) {
9 | type Builder = BuilderImpl
10 | type Reader = ReaderImpl
11 |
12 | def Reader(segment: SegmentReader,
13 | ptr: Int,
14 | elementCount: Int,
15 | step: Int,
16 | structDataSize: Int,
17 | structPointerCount: Short,
18 | nestingLimit: Int): Reader = {
19 | new ReaderImpl(segment, ptr, elementCount, step, structDataSize, structPointerCount, nestingLimit)
20 | }
21 |
22 | def Builder(segment: SegmentBuilder,
23 | ptr: Int,
24 | elementCount: Int,
25 | step: Int,
26 | structDataSize: Int,
27 | structPointerCount: Short): Builder = {
28 | new BuilderImpl(segment, ptr, elementCount, step, structDataSize, structPointerCount)
29 | }
30 |
31 | class ReaderImpl(segment: SegmentReader,
32 | ptr: Int,
33 | elementCount: Int,
34 | step: Int,
35 | structDataSize: Int,
36 | structPointerCount: Short,
37 | nestingLimit: Int) extends ReaderBase(segment, ptr, elementCount, step, structDataSize, structPointerCount, nestingLimit) {
38 |
39 | override def apply(idx: Int): L#Reader = _getPointerElement[L](idx)
40 | }
41 |
42 | class BuilderImpl(segment: SegmentBuilder,
43 | ptr: Int,
44 | elementCount: Int,
45 | step: Int,
46 | structDataSize: Int,
47 | structPointerCount: Short) extends BuilderBase(segment, ptr, elementCount, step, structDataSize, structPointerCount) {
48 |
49 | def init(index: Int, size: Int): L#Builder = {
50 | _initPointerElement[L](index, size)
51 | }
52 |
53 | def apply(idx: Int): L#Builder = _getPointerElement[L](idx)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ListPointer.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | object ListPointer {
6 |
7 | def elementSize(ref: Long): Byte = {
8 | (WirePointer.upper32Bits(ref) & 7).toByte
9 | }
10 |
11 | def elementCount(ref: Long): Int = WirePointer.upper32Bits(ref) >>> 3
12 |
13 | def inlineCompositeWordCount(ref: Long): Int = elementCount(ref)
14 |
15 | def set(buffer: ByteBuffer,
16 | offset: Int,
17 | elementSize: Byte,
18 | elementCount: Int) {
19 | buffer.putInt(8 * offset + 4, (elementCount << 3) | elementSize)
20 | }
21 |
22 | def setInlineComposite(buffer: ByteBuffer, offset: Int, wordCount: Int) {
23 | buffer.putInt(8 * offset + 4, (wordCount << 3) | ElementSize.INLINE_COMPOSITE)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ListReader.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object ListReader {
4 | trait Factory[Reader] {
5 | def Reader(segment: SegmentReader,
6 | ptr: Int,
7 | elementCount: Int,
8 | step: Int,
9 | structDataSize: Int,
10 | structPointerCount: Short,
11 | nestingLimit: Int): Reader
12 | }
13 | }
14 |
15 | class ListReader(
16 | val segment: SegmentReader = null,
17 | val ptr: Int = 0,
18 | val elementCount: Int = 0,
19 | val step: Int = 0,
20 | val structDataSize: Int = 0,
21 | val structPointerCount: Short = 0,
22 | val nestingLimit: Int = 0x7fffffff) {
23 |
24 | def size: Int = this.elementCount
25 |
26 | protected def _getBooleanElement(index: Int): Boolean = {
27 | val bindex = index.toLong * this.step
28 | val b = this.segment.buffer.get(this.ptr + (bindex / Constants.BITS_PER_BYTE).toInt)
29 | (b & (1 << (bindex % 8))) != 0
30 | }
31 |
32 | protected def _getByteElement(index: Int): Byte = {
33 | this.segment.buffer.get(this.ptr +
34 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
35 | }
36 |
37 | protected def _getShortElement(index: Int): Short = {
38 | this.segment.buffer.getShort(this.ptr +
39 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
40 | }
41 |
42 | protected def _getIntElement(index: Int): Int = {
43 | this.segment.buffer.getInt(this.ptr +
44 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
45 | }
46 |
47 | protected def _getLongElement(index: Int): Long = {
48 | this.segment.buffer.getLong(this.ptr +
49 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
50 | }
51 |
52 | protected def _getFloatElement(index: Int): Float = {
53 | this.segment.buffer.getFloat(this.ptr +
54 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
55 | }
56 |
57 | protected def _getDoubleElement(index: Int): Double = {
58 | this.segment.buffer.getDouble(this.ptr +
59 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt)
60 | }
61 |
62 | protected def _getStructElement[T <: Struct : StructFromSegment](index: Int): T#Reader = {
63 | val indexBit = index.toLong * this.step
64 | val structData = this.ptr + (indexBit / Constants.BITS_PER_BYTE).toInt
65 | val structPointers = structData + (this.structDataSize / Constants.BITS_PER_BYTE)
66 | implicitly[StructFromSegment[T]].readerFromSegment(this.segment, structData, structPointers / 8, this.structDataSize, this.structPointerCount,
67 | this.nestingLimit - 1)
68 | }
69 |
70 | protected def _getStructElement(factory: Struct, index: Int): factory.Reader = {
71 | val indexBit = index.toLong * this.step
72 | val structData = this.ptr + (indexBit / Constants.BITS_PER_BYTE).toInt
73 | val structPointers = structData + (this.structDataSize / Constants.BITS_PER_BYTE)
74 | factory.Reader(this.segment, structData, structPointers / 8, this.structDataSize, this.structPointerCount,
75 | this.nestingLimit - 1)
76 | }
77 |
78 | protected def _getPointerElement[T <: PointerFamily : FromPointer](index: Int): T#Reader = {
79 | implicitly[FromPointer[T]].fromPointerReader(this.segment, (this.ptr +
80 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt) /
81 | Constants.BYTES_PER_WORD, this.nestingLimit)
82 | }
83 |
84 | protected def _getPointerElement[T <: PointerFamily : FromPointerBlobDefault](index: Int,
85 | defaultBuffer: java.nio.ByteBuffer,
86 | defaultOffset: Int,
87 | defaultSize: Int): T#Reader = {
88 | val factory = implicitly[FromPointerBlobDefault[T]]
89 | factory.fromPointerReaderBlobDefault(this.segment, (this.ptr +
90 | (index.toLong * this.step / Constants.BITS_PER_BYTE).toInt) /
91 | Constants.BYTES_PER_WORD, defaultBuffer, defaultOffset, defaultSize)
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/MessageBuilder.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | class MessageBuilder(val arena: BuilderArena = new BuilderArena(BuilderArena.SUGGESTED_FIRST_SEGMENT_WORDS, BuilderArena.SUGGESTED_ALLOCATION_STRATEGY)) {
4 |
5 | def this(firstSegmentWords: Int) {
6 | this(new BuilderArena(firstSegmentWords, BuilderArena.SUGGESTED_ALLOCATION_STRATEGY))
7 | }
8 |
9 | def this(firstSegmentWords: Int, allocationStrategy: BuilderArena.AllocationStrategy.Value) {
10 | this(new BuilderArena(firstSegmentWords, allocationStrategy))
11 | }
12 |
13 | private def internalRoot: AnyPointer.Builder = {
14 | val rootSegment = this.arena.segments.get(0)
15 | if (rootSegment.currentSize() == 0) {
16 | val location = rootSegment.allocate(1)
17 | if (location == SegmentBuilder.FAILED_ALLOCATION) {
18 | throw new Error("could not allocate root pointer")
19 | }
20 | if (location != 0) {
21 | throw new Error("First allocated word of new segment was not at offset 0")
22 | }
23 | new AnyPointer.Builder(rootSegment, location)
24 | } else {
25 | new AnyPointer.Builder(rootSegment, 0)
26 | }
27 | }
28 |
29 | def getRoot[T <: PointerFamily : FromPointer]: T#Builder = this.internalRoot.getAs[T]
30 |
31 | def setRoot[T <: PointerFamily : SetPointerBuilder](reader: T#Reader) {
32 | internalRoot.setAs[T](reader)
33 | }
34 |
35 | def initRoot[T <: PointerFamily : FromPointer]: T#Builder = internalRoot.initAs[T]
36 |
37 | def getSegmentsForOutput(): Array[java.nio.ByteBuffer] = this.arena.getSegmentsForOutput
38 | }
39 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/MessageReader.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | class MessageReader(segmentSlices: Array[ByteBuffer], options: ReaderOptions) {
6 |
7 | val arena = new ReaderArena(segmentSlices, options.traversalLimitInWords)
8 |
9 | val nestingLimit = options.nestingLimit
10 |
11 | def getRoot[T <: PointerFamily : FromPointer]: T#Reader = {
12 | val segment = this.arena.tryGetSegment(0)
13 | val any = new AnyPointer.Reader(segment, 0, this.nestingLimit)
14 | any.getAs[T]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/MessageStreamParser.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.{ByteBuffer, ByteOrder}
4 |
5 | import scala.annotation.tailrec
6 | import scala.collection.mutable
7 |
8 | class MessageStreamParser(options: ReaderOptions = ReaderOptions.DEFAULT_READER_OPTIONS) {
9 | private val bufs = new ByteBufferList
10 |
11 | def update(buffer: ByteBuffer): Option[MessageReader] = {
12 | bufs.add(buffer)
13 | next()
14 | }
15 |
16 | private var segmentCount = -1
17 | private var segment0Size = -1
18 | private var totalWords = -1
19 | private val firstWord = makeByteBuffer(Constants.BYTES_PER_WORD)
20 | private val moreSizes = mutable.ArrayBuffer[Integer]()
21 | private var moreSizesRaw: ByteBuffer = _
22 | private var allSegments: ByteBuffer = _
23 |
24 | val Init = 0
25 | val Segments = 1
26 | val FillExtraSegmentSizes = 2
27 | val InitAllSegments = 3
28 | val FillAllSegments = 4
29 | private var state = Init
30 |
31 | @tailrec
32 | private def next(): Option[MessageReader] = {
33 | state match {
34 | case Init =>
35 | if (bufs.read(firstWord)) {
36 | segmentCount = firstWord.getInt(0) + 1
37 | segment0Size = if (segmentCount > 0) firstWord.getInt(4) else 0
38 | totalWords = segment0Size
39 | if (segmentCount > 512) {
40 | throw new Error("too many segments")
41 | }
42 | if (segmentCount > 1) {
43 | moreSizesRaw = makeByteBuffer(4 * (segmentCount & ~1))
44 | state = FillExtraSegmentSizes
45 | } else {
46 | state = InitAllSegments
47 | }
48 | next()
49 | } else {
50 | None
51 | }
52 | case FillExtraSegmentSizes =>
53 | if (bufs.read(moreSizesRaw)) {
54 | var i = 0
55 | while (i < segmentCount) {
56 | val size = moreSizesRaw.getInt(i * 4)
57 | moreSizes += size
58 | totalWords += size
59 | i += 1
60 | }
61 | state = InitAllSegments
62 | next()
63 | } else {
64 | None
65 | }
66 | case InitAllSegments =>
67 | if (totalWords > options.traversalLimitInWords) {
68 | throw new DecodeException("Message size exceeds traversal limit.")
69 | }
70 | allSegments = makeByteBuffer(totalWords * Constants.BYTES_PER_WORD)
71 | state = FillAllSegments
72 | next()
73 | case FillAllSegments =>
74 | if (bufs.read(allSegments)) {
75 | val segmentSlices = Array.ofDim[ByteBuffer](segmentCount)
76 | allSegments.rewind()
77 | segmentSlices(0) = allSegments.slice()
78 | segmentSlices(0).limit(segment0Size * Constants.BYTES_PER_WORD)
79 | segmentSlices(0).order(ByteOrder.LITTLE_ENDIAN)
80 | var offset = segment0Size
81 | var i = 1
82 | while (i < segmentCount) {
83 | allSegments.position(offset * Constants.BYTES_PER_WORD)
84 | segmentSlices(i) = allSegments.slice()
85 | segmentSlices(i).limit(moreSizes(i - 1) * Constants.BYTES_PER_WORD)
86 | segmentSlices(i).order(ByteOrder.LITTLE_ENDIAN)
87 | offset += moreSizes(i - 1)
88 | i += 1
89 | }
90 | reset()
91 | Some(new MessageReader(segmentSlices, options))
92 | } else {
93 | None
94 | }
95 | }
96 | }
97 |
98 | private def reset(): Unit = {
99 | segmentCount = -1
100 | segment0Size = -1
101 | totalWords = -1
102 | firstWord.clear()
103 | moreSizes.clear()
104 | moreSizesRaw = null
105 | allSegments = null
106 | state = Init
107 | }
108 |
109 | private def makeByteBuffer(bytes: Int): ByteBuffer = {
110 | val result = ByteBuffer.allocate(bytes)
111 | result.order(ByteOrder.LITTLE_ENDIAN)
112 | result.mark()
113 | result
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/NotInSchema.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object NotInSchema {
4 | def which(index: Short): NotInSchema = new NotInSchema(s"Invalid union member with index $index")
5 | }
6 |
7 | class NotInSchema(message: String, throwable: Throwable = null) extends Exception(message, throwable)
8 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/PackedInputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.ReadableByteChannel
5 |
6 | class PackedInputStream(input: BufferedInputStream) extends ReadableByteChannel {
7 |
8 | val inner = input
9 |
10 | def read(outBuf: ByteBuffer): Int = {
11 | val len = outBuf.remaining()
12 | if (len == 0) {
13 | return 0
14 | }
15 | if (len % 8 != 0) {
16 | throw new Error("PackedInputStream reads must be word-aligned")
17 | }
18 | val outPtr = outBuf.position()
19 | val outEnd = outPtr + len
20 | var inBuf = this.inner.getReadBuffer
21 | while (true) {
22 | var tag: Byte = 0
23 | if (inBuf.remaining() < 10) {
24 | if (outBuf.remaining() == 0) {
25 | return len
26 | }
27 | if (inBuf.remaining() == 0) {
28 | inBuf = this.inner.getReadBuffer
29 | //continue
30 | }
31 | tag = inBuf.get
32 | for (i <- 0.until(8)) {
33 | if ((tag & (1 << i)) != 0) {
34 | if (inBuf.remaining() == 0) {
35 | inBuf = this.inner.getReadBuffer
36 | }
37 | outBuf.put(inBuf.get)
38 | } else {
39 | outBuf.put(0.toByte)
40 | }
41 | }
42 | if (inBuf.remaining() == 0 && (tag == 0 || tag == 0xff.toByte)) {
43 | inBuf = this.inner.getReadBuffer
44 | }
45 | } else {
46 | tag = inBuf.get
47 | for (n <- 0.until(8)) {
48 | val isNonzero = (tag & (1 << n)) != 0
49 | outBuf.put((inBuf.get & (if (isNonzero) -1 else 0)).toByte)
50 | inBuf.position(inBuf.position() + (if (isNonzero) 0 else -1))
51 | }
52 | }
53 | if (tag == 0) {
54 | if (inBuf.remaining() == 0) {
55 | throw new Error("Should always have non-empty buffer here.")
56 | }
57 | val runLength = (0xff & inBuf.get.toInt) * 8
58 | if (runLength > outEnd - outPtr) {
59 | throw new Error("Packed input did not end cleanly on a segment boundary")
60 | }
61 | for (i <- 0 until runLength) {
62 | outBuf.put(0.toByte)
63 | }
64 | } else if (tag == 0xff.toByte) {
65 | var runLength = (0xff & inBuf.get.toInt) * 8
66 | if (inBuf.remaining() >= runLength) {
67 | val slice = inBuf.slice()
68 | slice.limit(runLength)
69 | outBuf.put(slice)
70 | inBuf.position(inBuf.position() + runLength)
71 | } else {
72 | runLength -= inBuf.remaining()
73 | outBuf.put(inBuf)
74 | val slice = outBuf.slice()
75 | slice.limit(runLength)
76 | this.inner.read(slice)
77 | outBuf.position(outBuf.position() + runLength)
78 | if (outBuf.remaining() == 0) {
79 | return len
80 | } else {
81 | inBuf = this.inner.getReadBuffer
82 | //continue
83 | }
84 | }
85 | }
86 | if (outBuf.remaining() == 0) {
87 | len
88 | }
89 | }
90 | throw new Error("Should never happen")
91 | }
92 |
93 | def close() {
94 | inner.close()
95 | }
96 |
97 | def isOpen(): Boolean = inner.isOpen
98 | }
99 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/PackedOutputStream.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | import java.nio.channels.WritableByteChannel
5 |
6 | class PackedOutputStream(output: BufferedOutputStream) extends WritableByteChannel {
7 |
8 | val inner = output
9 |
10 | def write(inBuf: ByteBuffer): Int = {
11 | val length = inBuf.remaining()
12 | var out = this.inner.writeBuffer
13 | val slowBuffer = ByteBuffer.allocate(20)
14 | var inPtr = inBuf.position()
15 | val inEnd = inPtr + length
16 | while (inPtr < inEnd) {
17 | if (out.remaining() < 10) {
18 | if (out == slowBuffer) {
19 | val oldLimit = out.limit()
20 | out.limit(out.position())
21 | out.rewind()
22 | this.inner.write(out)
23 | out.limit(oldLimit)
24 | }
25 | out = slowBuffer
26 | out.rewind()
27 | }
28 | val tagPos = out.position()
29 | out.position(tagPos + 1)
30 | var curByte: Byte = 0
31 | curByte = inBuf.get(inPtr)
32 | val bit0 = if (curByte != 0) 1.toByte else 0.toByte
33 | out.put(curByte)
34 | out.position(out.position() + bit0 - 1)
35 | inPtr += 1
36 | curByte = inBuf.get(inPtr)
37 | val bit1 = if (curByte != 0) 1.toByte else 0.toByte
38 | out.put(curByte)
39 | out.position(out.position() + bit1 - 1)
40 | inPtr += 1
41 | curByte = inBuf.get(inPtr)
42 | val bit2 = if (curByte != 0) 1.toByte else 0.toByte
43 | out.put(curByte)
44 | out.position(out.position() + bit2 - 1)
45 | inPtr += 1
46 | curByte = inBuf.get(inPtr)
47 | val bit3 = if (curByte != 0) 1.toByte else 0.toByte
48 | out.put(curByte)
49 | out.position(out.position() + bit3 - 1)
50 | inPtr += 1
51 | curByte = inBuf.get(inPtr)
52 | val bit4 = if (curByte != 0) 1.toByte else 0.toByte
53 | out.put(curByte)
54 | out.position(out.position() + bit4 - 1)
55 | inPtr += 1
56 | curByte = inBuf.get(inPtr)
57 | val bit5 = if (curByte != 0) 1.toByte else 0.toByte
58 | out.put(curByte)
59 | out.position(out.position() + bit5 - 1)
60 | inPtr += 1
61 | curByte = inBuf.get(inPtr)
62 | val bit6 = if (curByte != 0) 1.toByte else 0.toByte
63 | out.put(curByte)
64 | out.position(out.position() + bit6 - 1)
65 | inPtr += 1
66 | curByte = inBuf.get(inPtr)
67 | val bit7 = if (curByte != 0) 1.toByte else 0.toByte
68 | out.put(curByte)
69 | out.position(out.position() + bit7 - 1)
70 | inPtr += 1
71 | val tag = ((bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3) |
72 | (bit4 << 4) |
73 | (bit5 << 5) |
74 | (bit6 << 6) |
75 | (bit7 << 7)).toByte
76 | out.put(tagPos, tag)
77 | if (tag == 0) {
78 | val runStart = inPtr
79 | var limit = inEnd
80 | if (limit - inPtr > 255 * 8) {
81 | limit = inPtr + 255 * 8
82 | }
83 | while (inPtr < limit && inBuf.getLong(inPtr) == 0) {
84 | inPtr += 8
85 | }
86 | out.put(((inPtr - runStart) / 8).toByte)
87 | } else if (tag == 0xff.toByte) {
88 | val runStart = inPtr
89 | var limit = inEnd
90 | if (limit - inPtr > 255 * 8) {
91 | limit = inPtr + 255 * 8
92 | }
93 | var run = true
94 | while (run && inPtr < limit) {
95 | var c: Byte = 0
96 | for (ii <- 0.until(8)) {
97 | c = (c + (if (inBuf.get(inPtr) == 0) 1 else 0).toByte).toByte
98 | inPtr += 1
99 | }
100 | if (c >= 2) {
101 | inPtr -= 8
102 | run = false
103 | }
104 | }
105 | val count = inPtr - runStart
106 | out.put((count / 8).toByte)
107 | if (count <= out.remaining()) {
108 | inBuf.position(runStart)
109 | val slice = inBuf.slice()
110 | slice.limit(count)
111 | out.put(slice)
112 | } else {
113 | if (out == slowBuffer) {
114 | val oldLimit = out.limit()
115 | out.limit(out.position())
116 | out.rewind()
117 | this.inner.write(out)
118 | out.limit(oldLimit)
119 | }
120 | inBuf.position(runStart)
121 | val slice = inBuf.slice()
122 | slice.limit(count)
123 | while (slice.hasRemaining) {
124 | this.inner.write(slice)
125 | }
126 | out = this.inner.writeBuffer
127 | }
128 | }
129 | }
130 | if (out == slowBuffer) {
131 | out.limit(out.position())
132 | out.rewind()
133 | this.inner.write(out)
134 | }
135 | inBuf.position(inPtr)
136 | length
137 | }
138 |
139 | def close() {
140 | this.inner.close()
141 | }
142 |
143 | def isOpen(): Boolean = this.inner.isOpen
144 | }
145 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/PrimitiveList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import org.katis.capnproto.runtime
4 |
5 | object PrimitiveList {
6 | object Void extends Void
7 | class Void private() extends List[runtime.Void, runtime.Void](ElementSize.VOID.toByte) {
8 | type Reader = ReaderImpl
9 | type Builder = BuilderImpl
10 |
11 | def Reader(segment: SegmentReader,
12 | ptr: scala.Int,
13 | elementCount: scala.Int,
14 | step: scala.Int,
15 | structDataSize: scala.Int,
16 | structPointerCount: scala.Short,
17 | nestingLimit: scala.Int): Reader = {
18 | new ReaderImpl(segment,
19 | ptr,
20 | elementCount,
21 | step,
22 | structDataSize,
23 | structPointerCount,
24 | nestingLimit)
25 | }
26 |
27 | def Builder(segment: SegmentBuilder,
28 | ptr: scala.Int,
29 | elementCount: scala.Int,
30 | step: scala.Int,
31 | structDataSize: scala.Int,
32 | structPointerCount: scala.Short): Builder = {
33 | new BuilderImpl(segment,
34 | ptr,
35 | elementCount,
36 | step,
37 | structDataSize,
38 | structPointerCount)
39 | }
40 |
41 | class ReaderImpl(segment: SegmentReader,
42 | ptr: scala.Int,
43 | elementCount: scala.Int,
44 | step: scala.Int,
45 | structDataSize: scala.Int,
46 | structPointerCount: scala.Short,
47 | nestingLimit: scala.Int)
48 | extends ReaderBase(segment,
49 | ptr,
50 | elementCount,
51 | step,
52 | structDataSize,
53 | structPointerCount,
54 | nestingLimit) {
55 |
56 | def apply(idx: scala.Int): runtime.Void = runtime.Void
57 |
58 | def get(idx: scala.Int): runtime.Void = runtime.Void
59 | }
60 |
61 | class BuilderImpl(segment: SegmentBuilder,
62 | ptr: scala.Int,
63 | elementCount: scala.Int,
64 | step: scala.Int,
65 | structDataSize: scala.Int,
66 | structPointerCount: scala.Short)
67 | extends BuilderBase(segment,
68 | ptr,
69 | elementCount,
70 | step,
71 | structDataSize,
72 | structPointerCount) {
73 | override def apply(idx: scala.Int): runtime.Void = runtime.Void
74 |
75 | def get(idx: scala.Int): runtime.Void = runtime.Void
76 |
77 | def update(idx: scala.Int, elem: runtime.Void): Unit = ()
78 | }
79 | }
80 |
81 | object Boolean extends Boolean
82 | class Boolean private() extends List[scala.Boolean, scala.Boolean](ElementSize.BIT.toByte) {
83 | type Reader = ReaderImpl
84 | type Builder = BuilderImpl
85 |
86 | def Reader(segment: SegmentReader,
87 | ptr: scala.Int,
88 | elementCount: scala.Int,
89 | step: scala.Int,
90 | structDataSize: scala.Int,
91 | structPointerCount: scala.Short,
92 | nestingLimit: scala.Int): Reader = {
93 | new ReaderImpl(segment,
94 | ptr,
95 | elementCount,
96 | step,
97 | structDataSize,
98 | structPointerCount,
99 | nestingLimit)
100 | }
101 |
102 | def Builder(segment: SegmentBuilder,
103 | ptr: scala.Int,
104 | elementCount: scala.Int,
105 | step: scala.Int,
106 | structDataSize: scala.Int,
107 | structPointerCount: scala.Short): Builder = {
108 | new BuilderImpl(segment,
109 | ptr,
110 | elementCount,
111 | step,
112 | structDataSize,
113 | structPointerCount)
114 | }
115 |
116 | class ReaderImpl(segment: SegmentReader,
117 | ptr: scala.Int,
118 | elementCount: scala.Int,
119 | step: scala.Int,
120 | structDataSize: scala.Int,
121 | structPointerCount: scala.Short,
122 | nestingLimit: scala.Int)
123 | extends ReaderBase(segment,
124 | ptr,
125 | elementCount,
126 | step,
127 | structDataSize,
128 | structPointerCount,
129 | nestingLimit) {
130 |
131 | def apply(idx: scala.Int): scala.Boolean = get(idx)
132 |
133 | def get(idx: scala.Int): scala.Boolean = _getBooleanElement(idx)
134 | }
135 |
136 | class BuilderImpl(segment: SegmentBuilder,
137 | ptr: scala.Int,
138 | elementCount: scala.Int,
139 | step: scala.Int,
140 | structDataSize: scala.Int,
141 | structPointerCount: scala.Short)
142 | extends BuilderBase(segment,
143 | ptr,
144 | elementCount,
145 | step,
146 | structDataSize,
147 | structPointerCount) {
148 |
149 | def apply(idx: scala.Int): scala.Boolean = get(idx)
150 |
151 | def get(idx: scala.Int): scala.Boolean = _getBooleanElement(idx)
152 |
153 | def update(idx: scala.Int, value: scala.Boolean) {
154 | _setBooleanElement(idx, value)
155 | }
156 | }
157 | }
158 |
159 | object Byte extends Byte
160 | class Byte private() extends List[scala.Byte, scala.Byte](ElementSize.BYTE.toByte) {
161 | type Builder = BuilderImpl
162 | type Reader = ReaderImpl
163 |
164 | def Reader(segment: SegmentReader,
165 | ptr: scala.Int,
166 | elementCount: scala.Int,
167 | step: scala.Int,
168 | structDataSize: scala.Int,
169 | structPointerCount: scala.Short,
170 | nestingLimit: scala.Int): Reader = {
171 | new ReaderImpl(segment,
172 | ptr,
173 | elementCount,
174 | step,
175 | structDataSize,
176 | structPointerCount,
177 | nestingLimit)
178 | }
179 |
180 | def Builder(segment: SegmentBuilder,
181 | ptr: scala.Int,
182 | elementCount: scala.Int,
183 | step: scala.Int,
184 | structDataSize: scala.Int,
185 | structPointerCount: scala.Short): Builder = {
186 | new BuilderImpl(segment,
187 | ptr,
188 | elementCount,
189 | step,
190 | structDataSize,
191 | structPointerCount)
192 | }
193 |
194 | class ReaderImpl(segment: SegmentReader,
195 | ptr: scala.Int,
196 | elementCount: scala.Int,
197 | step: scala.Int,
198 | structDataSize: scala.Int,
199 | structPointerCount: scala.Short,
200 | nestingLimit: scala.Int)
201 | extends ReaderBase(segment,
202 | ptr,
203 | elementCount,
204 | step,
205 | structDataSize,
206 | structPointerCount,
207 | nestingLimit) {
208 |
209 | def apply(idx: scala.Int): scala.Byte = get(idx)
210 |
211 | def get(idx: scala.Int): scala.Byte = _getByteElement(idx)
212 | }
213 |
214 | class BuilderImpl(segment: SegmentBuilder,
215 | ptr: scala.Int,
216 | elementCount: scala.Int,
217 | step: scala.Int,
218 | structDataSize: scala.Int,
219 | structPointerCount: scala.Short)
220 | extends BuilderBase(segment,
221 | ptr,
222 | elementCount,
223 | step,
224 | structDataSize,
225 | structPointerCount) {
226 |
227 | def apply(idx: scala.Int): scala.Byte = get(idx)
228 |
229 | def get(idx: scala.Int): scala.Byte = _getByteElement(idx)
230 |
231 | def update(idx: scala.Int, value: scala.Byte) {
232 | _setByteElement(idx, value)
233 | }
234 | }
235 | }
236 |
237 | object Short extends Short
238 | class Short private() extends List[scala.Short, scala.Short](ElementSize.TWO_BYTES.toByte) {
239 | type Builder = BuilderImpl
240 | type Reader = ReaderImpl
241 |
242 | def Reader(segment: SegmentReader,
243 | ptr: scala.Int,
244 | elementCount: scala.Int,
245 | step: scala.Int,
246 | structDataSize: scala.Int,
247 | structPointerCount: scala.Short,
248 | nestingLimit: scala.Int): Reader = {
249 | new ReaderImpl(segment,
250 | ptr,
251 | elementCount,
252 | step,
253 | structDataSize,
254 | structPointerCount,
255 | nestingLimit)
256 | }
257 |
258 | def Builder(segment: SegmentBuilder,
259 | ptr: scala.Int,
260 | elementCount: scala.Int,
261 | step: scala.Int,
262 | structDataSize: scala.Int,
263 | structPointerCount: scala.Short): Builder = {
264 | new BuilderImpl(segment,
265 | ptr,
266 | elementCount,
267 | step,
268 | structDataSize,
269 | structPointerCount)
270 | }
271 |
272 | class ReaderImpl(segment: SegmentReader,
273 | ptr: scala.Int,
274 | elementCount: scala.Int,
275 | step: scala.Int,
276 | structDataSize: scala.Int,
277 | structPointerCount: scala.Short,
278 | nestingLimit: scala.Int)
279 | extends ReaderBase(segment,
280 | ptr,
281 | elementCount,
282 | step,
283 | structDataSize,
284 | structPointerCount,
285 | nestingLimit) {
286 |
287 | def apply(idx: scala.Int): scala.Short = get(idx)
288 |
289 | def get(idx: scala.Int): scala.Short = _getShortElement(idx)
290 | }
291 |
292 | class BuilderImpl(segment: SegmentBuilder,
293 | ptr: scala.Int,
294 | elementCount: scala.Int,
295 | step: scala.Int,
296 | structDataSize: scala.Int,
297 | structPointerCount: scala.Short)
298 | extends BuilderBase(segment,
299 | ptr,
300 | elementCount,
301 | step,
302 | structDataSize,
303 | structPointerCount) {
304 |
305 | def apply(idx: scala.Int): scala.Short = get(idx)
306 |
307 | def get(idx: scala.Int): scala.Short = _getShortElement(idx)
308 |
309 | def update(idx: scala.Int, value: scala.Short) {
310 | _setShortElement(idx, value)
311 | }
312 | }
313 | }
314 |
315 | object Int extends Int
316 | class Int private() extends List[scala.Int, scala.Int](ElementSize.FOUR_BYTES.toByte) {
317 | type Builder = BuilderImpl
318 | type Reader = ReaderImpl
319 |
320 | def Reader(segment: SegmentReader,
321 | ptr: scala.Int,
322 | elementCount: scala.Int,
323 | step: scala.Int,
324 | structDataSize: scala.Int,
325 | structPointerCount: scala.Short,
326 | nestingLimit: scala.Int): Reader = {
327 | new ReaderImpl(segment,
328 | ptr,
329 | elementCount,
330 | step,
331 | structDataSize,
332 | structPointerCount,
333 | nestingLimit)
334 | }
335 |
336 | def Builder(segment: SegmentBuilder,
337 | ptr: scala.Int,
338 | elementCount: scala.Int,
339 | step: scala.Int,
340 | structDataSize: scala.Int,
341 | structPointerCount: scala.Short): Builder = {
342 | new BuilderImpl(segment,
343 | ptr,
344 | elementCount,
345 | step,
346 | structDataSize,
347 | structPointerCount)
348 | }
349 |
350 | class ReaderImpl(segment: SegmentReader,
351 | ptr: scala.Int,
352 | elementCount: scala.Int,
353 | step: scala.Int,
354 | structDataSize: scala.Int,
355 | structPointerCount: scala.Short,
356 | nestingLimit: scala.Int)
357 | extends ReaderBase(segment,
358 | ptr,
359 | elementCount,
360 | step,
361 | structDataSize,
362 | structPointerCount,
363 | nestingLimit) {
364 |
365 | def apply(idx: scala.Int): scala.Int = get(idx)
366 |
367 | def get(idx: scala.Int): scala.Int = _getIntElement(idx)
368 | }
369 |
370 | class BuilderImpl(segment: SegmentBuilder,
371 | ptr: scala.Int,
372 | elementCount: scala.Int,
373 | step: scala.Int,
374 | structDataSize: scala.Int,
375 | structPointerCount: scala.Short)
376 | extends BuilderBase(segment,
377 | ptr,
378 | elementCount,
379 | step,
380 | structDataSize,
381 | structPointerCount) {
382 |
383 | def apply(idx: scala.Int): scala.Int = get(idx)
384 |
385 | def get(idx: scala.Int): scala.Int = _getIntElement(idx)
386 |
387 | def update(idx: scala.Int, value: scala.Int) {
388 | _setIntElement(idx, value)
389 | }
390 | }
391 | }
392 |
393 | object Long extends Long
394 | class Long private() extends List[scala.Long, scala.Long](ElementSize.EIGHT_BYTES.toByte) {
395 | type Builder = BuilderImpl
396 | type Reader = ReaderImpl
397 |
398 | def Reader(segment: SegmentReader,
399 | ptr: scala.Int,
400 | elementCount: scala.Int,
401 | step: scala.Int,
402 | structDataSize: scala.Int,
403 | structPointerCount: scala.Short,
404 | nestingLimit: scala.Int): Reader = {
405 | new ReaderImpl(segment,
406 | ptr,
407 | elementCount,
408 | step,
409 | structDataSize,
410 | structPointerCount,
411 | nestingLimit)
412 | }
413 |
414 | def Builder(segment: SegmentBuilder,
415 | ptr: scala.Int,
416 | elementCount: scala.Int,
417 | step: scala.Int,
418 | structDataSize: scala.Int,
419 | structPointerCount: scala.Short): Builder = {
420 | new BuilderImpl(segment,
421 | ptr,
422 | elementCount,
423 | step,
424 | structDataSize,
425 | structPointerCount)
426 | }
427 |
428 | class ReaderImpl(segment: SegmentReader,
429 | ptr: scala.Int,
430 | elementCount: scala.Int,
431 | step: scala.Int,
432 | structDataSize: scala.Int,
433 | structPointerCount: scala.Short,
434 | nestingLimit: scala.Int)
435 | extends ReaderBase(segment,
436 | ptr,
437 | elementCount,
438 | step,
439 | structDataSize,
440 | structPointerCount,
441 | nestingLimit) {
442 |
443 | def apply(idx: scala.Int): scala.Long = get(idx)
444 |
445 | def get(idx: scala.Int): scala.Long = _getLongElement(idx)
446 | }
447 |
448 | class BuilderImpl(segment: SegmentBuilder,
449 | ptr: scala.Int,
450 | elementCount: scala.Int,
451 | step: scala.Int,
452 | structDataSize: scala.Int,
453 | structPointerCount: scala.Short)
454 | extends BuilderBase(segment,
455 | ptr,
456 | elementCount,
457 | step,
458 | structDataSize,
459 | structPointerCount) {
460 |
461 | def apply(idx: scala.Int): scala.Long = get(idx)
462 |
463 | def get(idx: scala.Int): scala.Long = _getLongElement(idx)
464 |
465 | def update(idx: scala.Int, value: scala.Long) {
466 | _setLongElement(idx, value)
467 | }
468 | }
469 | }
470 |
471 | object Float extends Float
472 | class Float private() extends List[scala.Float, scala.Float](ElementSize.FOUR_BYTES.toByte) {
473 | type Builder = BuilderImpl
474 | type Reader = ReaderImpl
475 |
476 | def Reader(segment: SegmentReader,
477 | ptr: scala.Int,
478 | elementCount: scala.Int,
479 | step: scala.Int,
480 | structDataSize: scala.Int,
481 | structPointerCount: scala.Short,
482 | nestingLimit: scala.Int): Reader = {
483 | new ReaderImpl(segment,
484 | ptr,
485 | elementCount,
486 | step,
487 | structDataSize,
488 | structPointerCount,
489 | nestingLimit)
490 | }
491 |
492 | def Builder(segment: SegmentBuilder,
493 | ptr: scala.Int,
494 | elementCount: scala.Int,
495 | step: scala.Int,
496 | structDataSize: scala.Int,
497 | structPointerCount: scala.Short): Builder = {
498 | new BuilderImpl(segment,
499 | ptr,
500 | elementCount,
501 | step,
502 | structDataSize,
503 | structPointerCount)
504 | }
505 |
506 | class ReaderImpl(segment: SegmentReader,
507 | ptr: scala.Int,
508 | elementCount: scala.Int,
509 | step: scala.Int,
510 | structDataSize: scala.Int,
511 | structPointerCount: scala.Short,
512 | nestingLimit: scala.Int)
513 | extends ReaderBase(segment,
514 | ptr,
515 | elementCount,
516 | step,
517 | structDataSize,
518 | structPointerCount,
519 | nestingLimit) {
520 |
521 | def apply(idx: scala.Int): scala.Float = get(idx)
522 |
523 | def get(idx: scala.Int): scala.Float = _getFloatElement(idx)
524 | }
525 |
526 | class BuilderImpl(segment: SegmentBuilder,
527 | ptr: scala.Int,
528 | elementCount: scala.Int,
529 | step: scala.Int,
530 | structDataSize: scala.Int,
531 | structPointerCount: scala.Short)
532 | extends BuilderBase(segment,
533 | ptr,
534 | elementCount,
535 | step,
536 | structDataSize,
537 | structPointerCount) {
538 |
539 | def apply(idx: scala.Int): scala.Float = get(idx)
540 |
541 | def get(idx: scala.Int): scala.Float = _getFloatElement(idx)
542 |
543 | def update(idx: scala.Int, value: scala.Float) {
544 | _setFloatElement(idx, value)
545 | }
546 | }
547 | }
548 |
549 | object Double extends Double
550 | class Double private() extends List[scala.Double, scala.Double](ElementSize.EIGHT_BYTES.toByte) {
551 | type Builder = BuilderImpl
552 | type Reader = ReaderImpl
553 |
554 | def Reader(segment: SegmentReader,
555 | ptr: scala.Int,
556 | elementCount: scala.Int,
557 | step: scala.Int,
558 | structDataSize: scala.Int,
559 | structPointerCount: scala.Short,
560 | nestingLimit: scala.Int): Reader = {
561 | new ReaderImpl(segment,
562 | ptr,
563 | elementCount,
564 | step,
565 | structDataSize,
566 | structPointerCount,
567 | nestingLimit)
568 | }
569 |
570 | def Builder(segment: SegmentBuilder,
571 | ptr: scala.Int,
572 | elementCount: scala.Int,
573 | step: scala.Int,
574 | structDataSize: scala.Int,
575 | structPointerCount: scala.Short): Builder = {
576 | new BuilderImpl(segment,
577 | ptr,
578 | elementCount,
579 | step,
580 | structDataSize,
581 | structPointerCount)
582 | }
583 |
584 | class ReaderImpl(segment: SegmentReader,
585 | ptr: scala.Int,
586 | elementCount: scala.Int,
587 | step: scala.Int,
588 | structDataSize: scala.Int,
589 | structPointerCount: scala.Short,
590 | nestingLimit: scala.Int)
591 | extends ReaderBase(segment,
592 | ptr,
593 | elementCount,
594 | step,
595 | structDataSize,
596 | structPointerCount,
597 | nestingLimit) {
598 |
599 | def apply(idx: scala.Int): scala.Double = get(idx)
600 |
601 | def get(idx: scala.Int): scala.Double = _getDoubleElement(idx)
602 | }
603 |
604 | class BuilderImpl(segment: SegmentBuilder,
605 | ptr: scala.Int,
606 | elementCount: scala.Int,
607 | step: scala.Int,
608 | structDataSize: scala.Int,
609 | structPointerCount: scala.Short)
610 | extends BuilderBase(segment,
611 | ptr,
612 | elementCount,
613 | step,
614 | structDataSize,
615 | structPointerCount) {
616 |
617 | def apply(idx: scala.Int): scala.Double = get(idx)
618 |
619 | def get(idx: scala.Int): scala.Double = _getDoubleElement(idx)
620 |
621 | def update(idx: scala.Int, value: scala.Double) {
622 | _setDoubleElement(idx, value)
623 | }
624 | }
625 | }
626 | }
627 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ReaderArena.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | import scala.collection.mutable
6 |
7 | class ReaderArena(segmentSlices: Array[ByteBuffer], traversalLimitInWords: Long)
8 | extends Arena {
9 |
10 | var limit: Long = traversalLimitInWords
11 |
12 | val segments = new mutable.ArrayBuffer[SegmentReader]()
13 |
14 | for (ii <- segmentSlices.indices) {
15 | segments += new SegmentReader(segmentSlices(ii), this)
16 | }
17 |
18 | def tryGetSegment(id: Int): SegmentReader = segments(id)
19 |
20 | def checkReadLimit(numBytes: Int) {
21 | if (numBytes > limit) {
22 | throw new DecodeException("Read limit exceeded.")
23 | } else {
24 | limit -= numBytes
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/ReaderOptions.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object ReaderOptions {
4 |
5 | val DEFAULT_TRAVERSAL_LIMIT_IN_WORDS = 8 * 1024 * 1024
6 |
7 | val DEFAULT_NESTING_LIMIT = 64
8 |
9 | val DEFAULT_READER_OPTIONS = new ReaderOptions(DEFAULT_TRAVERSAL_LIMIT_IN_WORDS, DEFAULT_NESTING_LIMIT)
10 | }
11 |
12 | class ReaderOptions(val traversalLimitInWords: Long, val nestingLimit: Int)
13 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/SegmentBuilder.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | import SegmentBuilder._
6 |
7 | object SegmentBuilder {
8 |
9 | val FAILED_ALLOCATION = -1
10 | }
11 |
12 | class SegmentBuilder(buf: ByteBuffer, _arena: Arena) extends SegmentReader(buf, _arena) {
13 |
14 | var pos: Int = 0
15 |
16 | var id: Int = 0
17 |
18 | private def capacity(): Int = {
19 | this.buffer.rewind()
20 | this.buffer.remaining() / 8
21 | }
22 |
23 | def currentSize(): Int = this.pos
24 |
25 | def allocate(amount: Int): Int = {
26 | assert(amount >= 0, "tried to allocate a negative number of words")
27 | if (amount > this.capacity() - this.currentSize()) {
28 | FAILED_ALLOCATION
29 | } else {
30 | val result = this.pos
31 | this.pos += amount
32 | result
33 | }
34 | }
35 |
36 | override def arena: BuilderArena = {
37 | super.arena.asInstanceOf[BuilderArena]
38 | }
39 |
40 | def isWritable: Boolean = true
41 |
42 | def put(index: Int, value: Long) {
43 | buffer.putLong(index * Constants.BYTES_PER_WORD, value)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/SegmentReader.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | object SegmentReader {
6 |
7 | val EMPTY = new SegmentReader(ByteBuffer.allocate(8), null)
8 | }
9 |
10 | class SegmentReader(val buffer: ByteBuffer, _arena: Arena) {
11 | def arena: Arena = _arena
12 |
13 | def get(index: Int): Long = {
14 | buffer.getLong(index * Constants.BYTES_PER_WORD)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Serialize.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.io.IOException
4 | import java.nio.{ByteBuffer, ByteOrder}
5 | import java.nio.channels.{ReadableByteChannel, WritableByteChannel}
6 | import java.util
7 |
8 | object Serialize {
9 |
10 | def makeByteBuffer(bytes: Int): ByteBuffer = {
11 | val result = ByteBuffer.allocate(bytes)
12 | result.order(ByteOrder.LITTLE_ENDIAN)
13 | result.mark()
14 | result
15 | }
16 |
17 | def fillBuffer(buffer: ByteBuffer, bc: ReadableByteChannel) {
18 | while (buffer.hasRemaining) {
19 | val r = bc.read(buffer)
20 | if (r < 0) {
21 | throw new IOException("premature EOF")
22 | }
23 | }
24 | }
25 |
26 | def read(bc: ReadableByteChannel): MessageReader = {
27 | read(bc, ReaderOptions.DEFAULT_READER_OPTIONS)
28 | }
29 |
30 | def read(bc: ReadableByteChannel, options: ReaderOptions): MessageReader = {
31 | val firstWord = makeByteBuffer(Constants.BYTES_PER_WORD)
32 | fillBuffer(firstWord, bc)
33 | val segmentCount = 1 + firstWord.getInt(0)
34 | var segment0Size = 0
35 | if (segmentCount > 0) {
36 | segment0Size = firstWord.getInt(4)
37 | }
38 | var totalWords = segment0Size
39 | if (segmentCount > 512) {
40 | throw new IOException("too many segments")
41 | }
42 | val moreSizes = new util.ArrayList[Integer]()
43 | if (segmentCount > 1) {
44 | val moreSizesRaw = makeByteBuffer(4 * (segmentCount & ~1))
45 | fillBuffer(moreSizesRaw, bc)
46 | for (ii <- 0 until segmentCount - 1) {
47 | val size = moreSizesRaw.getInt(ii * 4)
48 | moreSizes.add(size)
49 | totalWords += size
50 | }
51 | }
52 | if (totalWords > options.traversalLimitInWords) {
53 | throw new DecodeException("Message size exceeds traversal limit.")
54 | }
55 | val allSegments = makeByteBuffer(totalWords * Constants.BYTES_PER_WORD)
56 | fillBuffer(allSegments, bc)
57 | val segmentSlices = Array.ofDim[ByteBuffer](segmentCount)
58 | allSegments.rewind()
59 | segmentSlices(0) = allSegments.slice()
60 | segmentSlices(0).limit(segment0Size * Constants.BYTES_PER_WORD)
61 | segmentSlices(0).order(ByteOrder.LITTLE_ENDIAN)
62 | var offset = segment0Size
63 | for (ii <- 1 until segmentCount) {
64 | allSegments.position(offset * Constants.BYTES_PER_WORD)
65 | segmentSlices(ii) = allSegments.slice()
66 | segmentSlices(ii).limit(moreSizes.get(ii - 1) * Constants.BYTES_PER_WORD)
67 | segmentSlices(ii).order(ByteOrder.LITTLE_ENDIAN)
68 | offset += moreSizes.get(ii - 1)
69 | }
70 | new MessageReader(segmentSlices, options)
71 | }
72 |
73 | def read(bb: ByteBuffer): MessageReader = {
74 | read(bb, ReaderOptions.DEFAULT_READER_OPTIONS)
75 | }
76 |
77 | def read(bb: ByteBuffer, options: ReaderOptions): MessageReader = {
78 | bb.order(ByteOrder.LITTLE_ENDIAN)
79 | val segmentCount = 1 + bb.getInt
80 | if (segmentCount > 512) {
81 | throw new IOException("too many segments")
82 | }
83 | val segmentSlices = Array.ofDim[ByteBuffer](segmentCount)
84 | val segmentSizesBase = bb.position()
85 | val segmentSizesSize = segmentCount * 4
86 | val align = Constants.BYTES_PER_WORD - 1
87 | val segmentBase = (segmentSizesBase + segmentSizesSize + align) & ~align
88 | var totalWords = 0
89 | for (ii <- 0 until segmentCount) {
90 | val segmentSize = bb.getInt(segmentSizesBase + ii * 4)
91 | bb.position(segmentBase + totalWords * Constants.BYTES_PER_WORD)
92 | segmentSlices(ii) = bb.slice()
93 | segmentSlices(ii).limit(segmentSize * Constants.BYTES_PER_WORD)
94 | segmentSlices(ii).order(ByteOrder.LITTLE_ENDIAN)
95 | totalWords += segmentSize
96 | }
97 | bb.position(segmentBase + totalWords * Constants.BYTES_PER_WORD)
98 | if (totalWords > options.traversalLimitInWords) {
99 | throw new DecodeException("Message size exceeds traversal limit.")
100 | }
101 | new MessageReader(segmentSlices, options)
102 | }
103 |
104 | def computeSerializedSizeInWords(message: MessageBuilder): Long = {
105 | val segments = message.getSegmentsForOutput()
106 | var bytes: Long = 0
107 | bytes += 4
108 | bytes += segments.length * 4
109 | if (bytes % 8 != 0) {
110 | bytes += 4
111 | }
112 | for (i <- segments.indices) {
113 | val s = segments(i)
114 | bytes += s.limit()
115 | }
116 | bytes / Constants.BYTES_PER_WORD
117 | }
118 |
119 | def writeToByteBuffer(message: MessageBuilder): ByteBuffer = {
120 | val segments = message.getSegmentsForOutput()
121 | val segmentsSize = segments.map(_.remaining()).sum
122 | val tableSize = (segments.length + 2) & (~1)
123 | val table = ByteBuffer.allocateDirect(4 * tableSize + segmentsSize)
124 | table.order(ByteOrder.LITTLE_ENDIAN)
125 | table.putInt(0, segments.length - 1)
126 | for (i <- segments.indices) {
127 | table.putInt(4 * (i + 1), segments(i).limit() / 8)
128 | }
129 | table.position(tableSize * 4)
130 |
131 | for (buffer <- segments) {
132 | while (buffer.hasRemaining) {
133 | table.put(buffer)
134 | }
135 | }
136 |
137 | table.flip()
138 | table
139 | }
140 |
141 | def write(outputChannel: WritableByteChannel, message: MessageBuilder) {
142 | val segments = message.getSegmentsForOutput()
143 | val tableSize = (segments.length + 2) & (~1)
144 | val table = ByteBuffer.allocate(4 * tableSize)
145 | table.order(ByteOrder.LITTLE_ENDIAN)
146 | table.putInt(0, segments.length - 1)
147 | for (i <- segments.indices) {
148 | table.putInt(4 * (i + 1), segments(i).limit() / 8)
149 | }
150 | while (table.hasRemaining) {
151 | outputChannel.write(table)
152 | }
153 | for (buffer <- segments) {
154 | while (buffer.hasRemaining) {
155 | outputChannel.write(buffer)
156 | }
157 | }
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/SerializePacked.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object SerializePacked {
4 |
5 | def read(input: BufferedInputStream): MessageReader = {
6 | read(input, ReaderOptions.DEFAULT_READER_OPTIONS)
7 | }
8 |
9 | def read(input: BufferedInputStream, options: ReaderOptions): MessageReader = {
10 | val packedInput = new PackedInputStream(input)
11 | Serialize.read(packedInput, options)
12 | }
13 |
14 | def readFromUnbuffered(input: java.nio.channels.ReadableByteChannel): MessageReader = {
15 | readFromUnbuffered(input, ReaderOptions.DEFAULT_READER_OPTIONS)
16 | }
17 |
18 | def readFromUnbuffered(input: java.nio.channels.ReadableByteChannel, options: ReaderOptions): MessageReader = {
19 | val packedInput = new PackedInputStream(new BufferedInputStreamWrapper(input))
20 | Serialize.read(packedInput, options)
21 | }
22 |
23 | def write(output: BufferedOutputStream, message: MessageBuilder) {
24 | val packedOutputStream = new PackedOutputStream(output)
25 | Serialize.write(packedOutputStream, message)
26 | }
27 |
28 | def writeToUnbuffered(output: java.nio.channels.WritableByteChannel, message: MessageBuilder) {
29 | val buffered = new BufferedOutputStreamWrapper(output)
30 | write(buffered, message)
31 | buffered.flush()
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Struct.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | trait StructReaderFromSegment[T] {
4 | def readerFromSegment(segment: SegmentReader, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short, nestingLimit: Int): T
5 | }
6 |
7 | trait StructBuilderFromSegment[T] {
8 | def builderFromSegment(segment: SegmentBuilder, dataOffset: Int, pointers: Int, dataSize: Int, pointerCount: Short): T
9 | }
10 |
11 | trait HasStructSize[T] {
12 | def structSize: StructSize
13 | }
14 |
15 | trait HasTypeId[T] {
16 | def typeId: Long
17 | }
18 |
19 | trait StructFromSegment[T <: Struct] extends StructReaderFromSegment[T#Reader] with StructBuilderFromSegment[T#Builder]
20 |
21 | trait Struct
22 | extends PointerFamily
23 | with StructBuilder.Factory
24 | with StructReader.Factory
25 | {
26 |
27 | struct =>
28 |
29 | def typeId: Long
30 | def structSize: StructSize
31 |
32 | type Builder <: BuilderBase
33 | type Reader <: ReaderBase
34 |
35 | abstract class BuilderBase(_segment: SegmentBuilder,
36 | _data: Int,
37 | _pointers: Int,
38 | _dataSize: Int,
39 | _pointerCount: Short) extends StructBuilder(_segment, _data, _pointers, _dataSize, _pointerCount) {
40 | def asReader: Reader = Reader(_segment, _data, _pointers, _dataSize, _pointerCount, 0x7fffffff)
41 | }
42 |
43 | abstract class ReaderBase(_segment: SegmentReader,
44 | _data: Int,
45 | _pointers: Int,
46 | _dataSize: Int,
47 | _pointerCount: Short,
48 | _nestingLimit: Int) extends StructReader(_segment, _data, _pointers, _dataSize, _pointerCount, _nestingLimit) {
49 |
50 | }
51 |
52 | /*
53 | def fromPointerReaderRefDefault(segment: SegmentReader,
54 | pointer: Int,
55 | defaultSegment: SegmentReader,
56 | defaultOffset: Int,
57 | nestingLimit: Int): Reader = {
58 | WireHelpers.readStructPointer(this, segment, pointer, defaultSegment, defaultOffset, nestingLimit)
59 | }
60 |
61 | def fromPointerReader(segment: SegmentReader, pointer: Int, nestingLimit: Int): Reader = {
62 | fromPointerReaderRefDefault(segment, pointer, null, 0, nestingLimit)
63 | }
64 |
65 | def fromPointerBuilderRefDefault(segment: SegmentBuilder,
66 | pointer: Int,
67 | defaultSegment: SegmentReader,
68 | defaultOffset: Int): Builder = {
69 | WireHelpers.getWritableStructPointer(this, pointer, segment, this.structSize, defaultSegment, defaultOffset)
70 | }
71 |
72 | def fromPointerBuilder(segment: SegmentBuilder, pointer: Int): Builder = {
73 | WireHelpers.getWritableStructPointer(this, pointer, segment, this.structSize, null, 0)
74 | }
75 |
76 | def initFromPointerBuilder(segment: SegmentBuilder, pointer: Int, elementCount: Int): Builder = {
77 | WireHelpers.initStructPointer(this, pointer, segment, this.structSize)
78 | }
79 |
80 | def setPointerBuilder(segment: SegmentBuilder, pointer: Int, value: Reader) {
81 | WireHelpers.setStructPointer(segment, pointer, value)
82 | }
83 | */
84 |
85 | def asReader(builder: BuilderBase): Reader = builder.asReader
86 | }
87 |
88 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/StructBuilder.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object StructBuilder {
4 | trait Factory {
5 | type Builder
6 |
7 | def Builder: (SegmentBuilder, Int, Int, Int, Short) => Builder
8 |
9 | def structSize: StructSize
10 | }
11 | }
12 |
13 | class StructBuilder(private val _segment: SegmentBuilder,
14 | private val _dataOffset: Int,
15 | private val _pointers: Int,
16 | private val _dataSize: Int,
17 | private val _pointerCount: Short) {
18 |
19 | protected def _getBooleanField(offset: Int): Boolean = {
20 | val bitOffset = offset
21 | val position = this._dataOffset + (bitOffset / 8)
22 | (this._segment.buffer.get(position) & (1 << (bitOffset % 8))) !=
23 | 0
24 | }
25 |
26 | protected def _getBooleanField(offset: Int, mask: Boolean): Boolean = this._getBooleanField(offset) ^ mask
27 |
28 | protected def _setBooleanField(offset: Int, value: Boolean) {
29 | val bitOffset = offset
30 | val bitnum = (bitOffset % 8).toByte
31 | val position = this._dataOffset + (bitOffset / 8)
32 | val oldValue = this._segment.buffer.get(position)
33 | this._segment.buffer.put(position, ((oldValue & (~(1 << bitnum))) | ((if (value) 1 else 0) << bitnum)).toByte)
34 | }
35 |
36 | protected def _setBooleanField(offset: Int, value: Boolean, mask: Boolean) {
37 | this._setBooleanField(offset, value ^ mask)
38 | }
39 |
40 | protected def _getByteField(offset: Int): Byte = {
41 | this._segment.buffer.get(this._dataOffset + offset)
42 | }
43 |
44 | protected def _getByteField(offset: Int, mask: Byte): Byte = {
45 | (this._getByteField(offset) ^ mask).toByte
46 | }
47 |
48 | protected def _setByteField(offset: Int, value: Byte) {
49 | this._segment.buffer.put(this._dataOffset + offset, value)
50 | }
51 |
52 | protected def _setByteField(offset: Int, value: Byte, mask: Byte) {
53 | this._setByteField(offset, (value ^ mask).toByte)
54 | }
55 |
56 | protected def _getShortField(offset: Int): Short = {
57 | this._segment.buffer.getShort(this._dataOffset + offset * 2)
58 | }
59 |
60 | protected def _getShortField(offset: Int, mask: Short): Short = {
61 | (this._getShortField(offset) ^ mask).toShort
62 | }
63 |
64 | protected def _setShortField(offset: Int, value: Short) {
65 | this._segment.buffer.putShort(this._dataOffset + offset * 2, value)
66 | }
67 |
68 | protected def _setShortField(offset: Int, value: Short, mask: Short) {
69 | this._setShortField(offset, (value ^ mask).toShort)
70 | }
71 |
72 | protected def _getIntField(offset: Int): Int = {
73 | this._segment.buffer.getInt(this._dataOffset + offset * 4)
74 | }
75 |
76 | protected def _getIntField(offset: Int, mask: Int): Int = this._getIntField(offset) ^ mask
77 |
78 | protected def _setIntField(offset: Int, value: Int) {
79 | this._segment.buffer.putInt(this._dataOffset + offset * 4, value)
80 | }
81 |
82 | protected def _setIntField(offset: Int, value: Int, mask: Int) {
83 | this._setIntField(offset, value ^ mask)
84 | }
85 |
86 | protected def _getLongField(offset: Int): Long = {
87 | this._segment.buffer.getLong(this._dataOffset + offset * 8)
88 | }
89 |
90 | protected def _getLongField(offset: Int, mask: Long): Long = this._getLongField(offset) ^ mask
91 |
92 | protected def _setLongField(offset: Int, value: Long) {
93 | this._segment.buffer.putLong(this._dataOffset + offset * 8, value)
94 | }
95 |
96 | protected def _setLongField(offset: Int, value: Long, mask: Long) {
97 | this._setLongField(offset, value ^ mask)
98 | }
99 |
100 | protected def _getFloatField(offset: Int): Float = {
101 | this._segment.buffer.getFloat(this._dataOffset + offset * 4)
102 | }
103 |
104 | protected def _getFloatField(offset: Int, mask: Int): Float = {
105 | java.lang.Float.intBitsToFloat(this._segment.buffer.getInt(this._dataOffset + offset * 4) ^ mask)
106 | }
107 |
108 | protected def _setFloatField(offset: Int, value: Float) {
109 | this._segment.buffer.putFloat(this._dataOffset + offset * 4, value)
110 | }
111 |
112 | protected def _setFloatField(offset: Int, value: Float, mask: Int) {
113 | this._segment.buffer.putInt(this._dataOffset + offset * 4, java.lang.Float.floatToIntBits(value) ^ mask)
114 | }
115 |
116 | protected def _getDoubleField(offset: Int): Double = {
117 | this._segment.buffer.getDouble(this._dataOffset + offset * 8)
118 | }
119 |
120 | protected def _getDoubleField(offset: Int, mask: Long): Double = {
121 | java.lang.Double.longBitsToDouble(this._segment.buffer.getLong(this._dataOffset + offset * 8) ^
122 | mask)
123 | }
124 |
125 | protected def _setDoubleField(offset: Int, value: Double) {
126 | this._segment.buffer.putDouble(this._dataOffset + offset * 8, value)
127 | }
128 |
129 | protected def _setDoubleField(offset: Int, value: Double, mask: Long) {
130 | this._segment.buffer.putLong(this._dataOffset + offset * 8, java.lang.Double.doubleToLongBits(value) ^ mask)
131 | }
132 |
133 | protected def _pointerFieldIsNull(ptrIndex: Int): Boolean = {
134 | this._segment.buffer.getLong((this._pointers + ptrIndex) * Constants.BYTES_PER_WORD) ==
135 | 0
136 | }
137 |
138 | protected def _clearPointerField(ptrIndex: Int) {
139 | val pointer = this._pointers + ptrIndex
140 | WireHelpers.zeroObject(this._segment, pointer)
141 | this._segment.buffer.putLong(pointer * 8, 0L)
142 | }
143 |
144 | protected def _getPointerField[P <: PointerFamily : FromPointer](index: Int): P#Builder = {
145 | implicitly[FromPointer[P]].fromPointerBuilder(_segment, _pointers + index)
146 | }
147 |
148 | protected def _getPointerField[P <: PointerFamily : FromPointerRefDefault](
149 | index: Int,
150 | defaultSegment: SegmentReader,
151 | defaultOffset: Int): P#Builder = {
152 | implicitly[FromPointerRefDefault[P]].fromPointerBuilderRefDefault(_segment, _pointers + index, defaultSegment, defaultOffset)
153 | }
154 |
155 | protected def _getPointerField[P <: PointerFamily : FromPointerBlobDefault](index: Int,
156 | defaultBuffer: java.nio.ByteBuffer,
157 | defaultOffset: Int,
158 | defaultSize: Int): P#Builder = {
159 | implicitly[FromPointerBlobDefault[P]].fromPointerBuilderBlobDefault(_segment, _pointers + index, defaultBuffer, defaultOffset, defaultSize)
160 | }
161 |
162 | protected def _initPointerField[T <: PointerFamily : FromPointer](index: Int, elementCount: Int): T#Builder = {
163 | implicitly[FromPointer[T]].initFromPointerBuilder(this._segment, this._pointers + index, elementCount)
164 | }
165 |
166 | protected def _setPointerField[T <: PointerFamily : SetPointerBuilder](index: Int, value: T#Reader) {
167 | implicitly[SetPointerBuilder[T]].setPointerBuilder(this._segment, this._pointers + index, value)
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/StructList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object StructList {
4 | def apply[S <: Struct : StructFromSegment : HasStructSize : SetPointerBuilder]: StructList[S] = new StructList[S]
5 | }
6 |
7 | class StructList[S <: Struct : StructFromSegment : HasStructSize : SetPointerBuilder] extends org.katis.capnproto.runtime.List[S#Builder, S#Reader](ElementSize.INLINE_COMPOSITE) {
8 | override type Builder = BuilderImpl
9 | override type Reader = ReaderImpl
10 |
11 | class BuilderImpl(_segment: SegmentBuilder,
12 | _ptr: Int,
13 | _elementCount: Int,
14 | _step: Int,
15 | _structDataSize: Int,
16 | _structPointerCount: Short)
17 | extends BuilderBase(_segment, _ptr, _elementCount, _step, _structDataSize, _structPointerCount) {
18 |
19 | builder =>
20 |
21 | def apply(idx: Int): S#Builder = _getStructElement[S](idx)
22 |
23 | def update(idx: Int, value: S#Reader): Unit = _setPointerElement[S](idx, value)
24 |
25 | override def foreach[U](fn: (S#Builder) => U): Unit = {
26 | for (i <- 0 until builder.size) {
27 | val el = _getStructElement[S](i)
28 | fn(el)
29 | }
30 | }
31 | }
32 |
33 | class ReaderImpl(_segment: SegmentReader,
34 | _ptr: Int,
35 | _elementCount: Int,
36 | _step: Int,
37 | _structDataSize: Int,
38 | _structPointerCount: Short,
39 | _nestingLimit: Int)
40 | extends ReaderBase(_segment, _ptr, _elementCount, _step, _structDataSize, _structPointerCount, _nestingLimit) {
41 |
42 | reader =>
43 |
44 | def apply(idx: Int): S#Reader = _getStructElement[S](idx)
45 |
46 | override def foreach[U](fn: (S#Reader) => U): Unit = {
47 | for (i <- 0 until reader.size) {
48 | val el = _getStructElement[S](i)
49 | fn(el)
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/StructPointer.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | //remove if not needed
5 |
6 | object StructPointer {
7 |
8 | def dataSize(ref: Long): Short = {
9 | (WirePointer.upper32Bits(ref) & 0xffff).toShort
10 | }
11 |
12 | def ptrCount(ref: Long): Short = {
13 | (WirePointer.upper32Bits(ref) >>> 16).toShort
14 | }
15 |
16 | def wordSize(ref: Long): Int = {
17 | dataSize(ref).toInt + ptrCount(ref).toInt
18 | }
19 |
20 | def setFromStructSize(buffer: ByteBuffer, offset: Int, size: StructSize) {
21 | buffer.putShort(8 * offset + 4, size.data)
22 | buffer.putShort(8 * offset + 6, size.pointers)
23 | }
24 |
25 | def set(buffer: ByteBuffer,
26 | offset: Int,
27 | dataSize: Short,
28 | pointerCount: Short) {
29 | buffer.putShort(8 * offset + 4, dataSize)
30 | buffer.putShort(8 * offset + 6, pointerCount)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/StructReader.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | object StructReader {
4 | trait Factory {
5 | type Reader
6 |
7 | def Reader: (SegmentReader,
8 | Int,
9 | Int,
10 | Int,
11 | Short,
12 | Int) => Reader
13 | }
14 | }
15 |
16 | class StructReader(private[runtime] val _segment: SegmentReader = SegmentReader.EMPTY,
17 | private[runtime] val _dataOffset: Int = 0,
18 | private[runtime] val _pointers: Int = 0,
19 | private[runtime] val _dataSize: Int = 0,
20 | private[runtime] val _pointerCount: Short = 1,
21 | private[runtime] val _nestingLimit: Int = 0x80000000) {
22 |
23 | protected def _getBooleanField(offset: Int): Boolean = {
24 | if (offset < this._dataSize) {
25 | val b = this._segment.buffer.get(this._dataOffset + offset / 8)
26 | (b & (1 << (offset % 8))) != 0
27 | } else {
28 | false
29 | }
30 | }
31 |
32 | protected def _getBooleanField(offset: Int, mask: Boolean): Boolean = this._getBooleanField(offset) ^ mask
33 |
34 | protected def _getByteField(offset: Int): Byte = {
35 | if ((offset + 1) * 8 <= this._dataSize) {
36 | this._segment.buffer.get(this._dataOffset + offset)
37 | } else {
38 | 0
39 | }
40 | }
41 |
42 | protected def _getByteField(offset: Int, mask: Byte): Byte = {
43 | (this._getByteField(offset) ^ mask).toByte
44 | }
45 |
46 | protected def _getShortField(offset: Int): Short = {
47 | if ((offset + 1) * 16 <= this._dataSize) {
48 | this._segment.buffer.getShort(this._dataOffset + offset * 2)
49 | } else {
50 | 0
51 | }
52 | }
53 |
54 | protected def _getShortField(offset: Int, mask: Short): Short = {
55 | (this._getShortField(offset) ^ mask).toShort
56 | }
57 |
58 | protected def _getIntField(offset: Int): Int = {
59 | if ((offset + 1) * 32 <= this._dataSize) {
60 | this._segment.buffer.getInt(this._dataOffset + offset * 4)
61 | } else {
62 | 0
63 | }
64 | }
65 |
66 | protected def _getIntField(offset: Int, mask: Int): Int = this._getIntField(offset) ^ mask
67 |
68 | protected def _getLongField(offset: Int): Long = {
69 | if ((offset + 1) * 64 <= this._dataSize) {
70 | this._segment.buffer.getLong(this._dataOffset + offset * 8)
71 | } else {
72 | 0
73 | }
74 | }
75 |
76 | protected def _getLongField(offset: Int, mask: Long): Long = this._getLongField(offset) ^ mask
77 |
78 | protected def _getFloatField(offset: Int): Float = {
79 | if ((offset + 1) * 32 <= this._dataSize) {
80 | this._segment.buffer.getFloat(this._dataOffset + offset * 4)
81 | } else {
82 | 0
83 | }
84 | }
85 |
86 | protected def _getFloatField(offset: Int, mask: Int): Float = {
87 | if ((offset + 1) * 32 <= this._dataSize) {
88 | java.lang.Float.intBitsToFloat(this._segment.buffer.getInt(this._dataOffset + offset * 4) ^ mask)
89 | } else {
90 | java.lang.Float.intBitsToFloat(mask)
91 | }
92 | }
93 |
94 | protected def _getDoubleField(offset: Int): Double = {
95 | if ((offset + 1) * 64 <= this._dataSize) {
96 | this._segment.buffer.getDouble(this._dataOffset + offset * 8)
97 | } else {
98 | 0
99 | }
100 | }
101 |
102 | protected def _getDoubleField(offset: Int, mask: Long): Double = {
103 | if ((offset + 1) * 64 <= this._dataSize) {
104 | java.lang.Double.longBitsToDouble(this._segment.buffer.getLong(this._dataOffset + offset * 8) ^
105 | mask)
106 | } else {
107 | java.lang.Double.longBitsToDouble(mask)
108 | }
109 | }
110 |
111 | protected def _pointerFieldIsNull(ptrIndex: Int): Boolean = {
112 | this._segment.buffer.getLong((this._pointers + ptrIndex) * Constants.BYTES_PER_WORD) == 0
113 | }
114 |
115 | protected def _getPointerField[T <: PointerFamily : FromPointer](ptrIndex: Int): T#Reader = {
116 | val factory = implicitly[FromPointer[T]]
117 | if (ptrIndex < this._pointerCount) {
118 | factory.fromPointerReader(this._segment, this._pointers + ptrIndex, this._nestingLimit)
119 | } else {
120 | factory.fromPointerReader(SegmentReader.EMPTY, 0, this._nestingLimit)
121 | }
122 | }
123 |
124 | protected def _getPointerField[T <: PointerFamily : FromPointerRefDefault](ptrIndex: Int,
125 | defaultSegment: SegmentReader,
126 | defaultOffset: Int): T#Reader = {
127 | val factory = implicitly[FromPointerRefDefault[T]]
128 | if (ptrIndex < this._pointerCount) {
129 | factory.fromPointerReaderRefDefault(this._segment, this._pointers + ptrIndex, defaultSegment, defaultOffset,
130 | this._nestingLimit)
131 | } else {
132 | factory.fromPointerReaderRefDefault(SegmentReader.EMPTY, 0, defaultSegment, defaultOffset, this._nestingLimit)
133 | }
134 | }
135 |
136 | protected def _getPointerField[T <: PointerFamily : FromPointerBlobDefault](
137 | ptrIndex: Int,
138 | defaultBuffer: java.nio.ByteBuffer,
139 | defaultOffset: Int,
140 | defaultSize: Int): T#Reader = {
141 | val factory = implicitly[FromPointerBlobDefault[T]]
142 | if (ptrIndex < this._pointerCount) {
143 | factory.fromPointerReaderBlobDefault(this._segment, this._pointers + ptrIndex, defaultBuffer, defaultOffset,
144 | defaultSize)
145 | } else {
146 | factory.fromPointerReaderBlobDefault(SegmentReader.EMPTY, 0, defaultBuffer, defaultOffset, defaultSize)
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/StructSize.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | class StructSize(val data: Short, val pointers: Short) {
4 |
5 | def total(): Int = this.data.toInt + this.pointers.toInt
6 | }
7 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Text.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 |
5 | object Text extends Text
6 | sealed class Text private() extends PointerFamily {
7 |
8 | type Reader = TextReader
9 | type Builder = TextBuilder
10 |
11 | def Reader(value: String): Reader = new TextReader(value)
12 | def Reader(byte: Array[Byte]): Reader = new TextReader(byte)
13 | }
14 |
15 | class TextReader(private[runtime] val buffer: ByteBuffer = ByteBuffer.allocate(0),
16 | _offset: Int = 0,
17 | val size: Int = 0) {
18 | private[runtime] val offset = _offset * 8
19 |
20 | def this(bytes: Array[Byte]) {
21 | this(ByteBuffer.wrap(bytes), 0, bytes.length)
22 | }
23 |
24 | def this(value: String) {
25 | this(value.getBytes("UTF-8"))
26 | }
27 |
28 | def asByteBuffer(): ByteBuffer = {
29 | val dup = this.buffer.asReadOnlyBuffer()
30 | dup.position(this.offset)
31 | val result = dup.slice()
32 | result.limit(this.size)
33 | result
34 | }
35 |
36 | override def toString: String = {
37 | val bytes = Array.ofDim[Byte](this.size)
38 | val dup = this.buffer.duplicate()
39 | dup.position(this.offset)
40 | dup.get(bytes, 0, this.size)
41 | new String(bytes, "UTF-8")
42 | }
43 | }
44 |
45 | class TextBuilder(val buffer: ByteBuffer = ByteBuffer.allocate(0),
46 | val offset: Int = 0,
47 | val size: Int = 0) {
48 | def asByteBuffer(): ByteBuffer = {
49 | val dup = this.buffer.duplicate()
50 | dup.position(this.offset)
51 | val result = dup.slice()
52 | result.limit(this.size)
53 | result
54 | }
55 |
56 | override def toString: String = {
57 | val bytes = Array.ofDim[Byte](this.size)
58 | val dup = this.buffer.duplicate()
59 | dup.position(this.offset)
60 | dup.get(bytes, 0, this.size)
61 | new String(bytes, "UTF-8")
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/TextList.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import implicits._
4 |
5 | object TextList extends TextList
6 | sealed class TextList private() extends List[Text#Builder, Text#Reader](ElementSize.POINTER) {
7 | type Builder = BuilderImpl
8 | type Reader = ReaderImpl
9 |
10 | class ReaderImpl(segment: SegmentReader,
11 | ptr: Int,
12 | elementCount: Int,
13 | step: Int,
14 | structDataSize: Int,
15 | structPointerCount: Short,
16 | nestingLimit: Int) extends ReaderBase(segment, ptr, elementCount, step, structDataSize, structPointerCount,
17 | nestingLimit) {
18 |
19 | def apply(idx: Int): Text#Reader = _getPointerElement[Text](idx)
20 | }
21 |
22 | class BuilderImpl(segment: SegmentBuilder,
23 | ptr: Int,
24 | elementCount: Int,
25 | step: Int,
26 | structDataSize: Int,
27 | structPointerCount: Short) extends BuilderBase(segment, ptr, elementCount, step, structDataSize,
28 | structPointerCount) {
29 | override def apply(idx: Int): Text#Builder = _getPointerElement[Text](idx)
30 |
31 | def update(idx: Int, element: Text.Reader): Unit = _setPointerElement[Text](idx, element)
32 |
33 | def update(idx: Int, element: String): Unit = _setPointerElement[Text](idx, Text.Reader(element))
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/Void.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | class Void
4 |
5 | object Void extends Void {
6 | val VOID = new Void
7 | }
8 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/WirePointer.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio.ByteBuffer
4 | //remove if not needed
5 |
6 | object WirePointer {
7 |
8 | val STRUCT = 0.toByte
9 |
10 | val LIST = 1.toByte
11 |
12 | val FAR = 2.toByte
13 |
14 | val OTHER = 3.toByte
15 |
16 | def isNull(wirePointer: Long): Boolean = wirePointer == 0
17 |
18 | def offsetAndKind(wirePointer: Long): Int = (wirePointer & 0xffffffff).toInt
19 |
20 | def kind(wirePointer: Long): Byte = (offsetAndKind(wirePointer) & 3).toByte
21 |
22 | def target(offset: Int, wirePointer: Long): Int = {
23 | offset + 1 + (offsetAndKind(wirePointer) >>> 2)
24 | }
25 |
26 | def setKindAndTarget(buffer: ByteBuffer,
27 | offset: Int,
28 | kind: Byte,
29 | targetOffset: Int) {
30 | buffer.putInt(offset * 8, (((targetOffset - offset) - 1) << 2) | kind)
31 | }
32 |
33 | def setKindWithZeroOffset(buffer: ByteBuffer, offset: Int, kind: Byte) {
34 | buffer.putInt(offset * Constants.BYTES_PER_WORD, kind)
35 | }
36 |
37 | def setKindAndTargetForEmptyStruct(buffer: ByteBuffer, offset: Int) {
38 | buffer.putInt(offset * 8, 0xfffffffc)
39 | }
40 |
41 | def setOffsetAndKind(buffer: ByteBuffer, offset: Int, offsetAndKind: Int) {
42 | buffer.putInt(offset * 8, offsetAndKind)
43 | }
44 |
45 | def inlineCompositeListElementCount(wirePointer: Long): Int = offsetAndKind(wirePointer) >>> 2
46 |
47 | def setKindAndInlineCompositeListElementCount(buffer: ByteBuffer,
48 | offset: Int,
49 | kind: Byte,
50 | elementCount: Int) {
51 | buffer.putInt(offset * 8, (elementCount << 2) | kind)
52 | }
53 |
54 | def upper32Bits(wirePointer: Long): Int = (wirePointer >>> 32).toInt
55 | }
56 |
--------------------------------------------------------------------------------
/runtime/shared/src/main/scala-2.11/org/katis/capnproto/runtime/pointer_traits.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | trait PointerFamily {
4 | type Builder
5 | type Reader
6 | }
7 |
8 | trait FromPointerBuilder[Builder] {
9 | def fromPointerBuilder(segment: SegmentBuilder, pointer: Int): Builder
10 | def initFromPointerBuilder(segment: SegmentBuilder, pointer: Int, elementCount: Int): Builder
11 | }
12 |
13 | trait FromPointerReader[Reader] {
14 | def fromPointerReader(segment: SegmentReader, pointer: Int, nestingLimit: Int): Reader
15 | }
16 |
17 | trait FromPointerBuilderRefDefault[Builder] {
18 | def fromPointerBuilderRefDefault(segment: SegmentBuilder,
19 | pointer: Int,
20 | defaultSegment: SegmentReader,
21 | defaultOffset: Int): Builder
22 | }
23 |
24 | trait FromPointerReaderRefDefault[Reader] {
25 | def fromPointerReaderRefDefault(segment: SegmentReader,
26 | pointer: Int,
27 | defaultSegment: SegmentReader,
28 | defaultOffset: Int,
29 | nestingLimit: Int): Reader
30 | }
31 |
32 | trait FromPointerRefDefault[T <: PointerFamily] extends FromPointerBuilderRefDefault[T#Builder] with FromPointerReaderRefDefault[T#Reader]{}
33 |
34 | trait FromPointerBuilderBlobDefault[Builder] {
35 | def fromPointerBuilderBlobDefault(segment: SegmentBuilder,
36 | pointer: Int,
37 | defaultBuffer: java.nio.ByteBuffer,
38 | defaultOffset: Int,
39 | defaultSize: Int): Builder
40 | }
41 |
42 | trait FromPointerReaderBlobDefault[Reader] {
43 | def fromPointerReaderBlobDefault(segment: SegmentReader,
44 | pointer: Int,
45 | defaultBuffer: java.nio.ByteBuffer,
46 | defaultOffset: Int,
47 | defaultSize: Int): Reader
48 | }
49 |
50 | trait FromPointerBlobDefault[T <: PointerFamily] extends FromPointerBuilderBlobDefault[T#Builder] with FromPointerReaderBlobDefault[T#Reader]
51 |
52 | trait SetPointerBuilder[T <: PointerFamily] {
53 | def setPointerBuilder(segment: SegmentBuilder, pointer: Int, value: T#Reader): Unit
54 | }
55 |
56 | trait FromPointer[T <: PointerFamily] extends FromPointerBuilder[T#Builder] with FromPointerReader[T#Reader]
57 |
--------------------------------------------------------------------------------
/runtime/shared/src/test/scala-2.11/org/katis/capnproto/runtime/ByteBufferListSpec.scala:
--------------------------------------------------------------------------------
1 | package org.katis.capnproto.runtime
2 |
3 | import java.nio._
4 |
5 | import org.scalatest.{FlatSpec, Matchers}
6 |
7 | class ByteBufferListSpec extends FlatSpec with Matchers {
8 | "A ByteBufferList" should "handle sources larger than sink" in {
9 | val sink1 = ByteBuffer.allocate(2)
10 | val sink2 = ByteBuffer.allocate(2)
11 | val sink3 = ByteBuffer.allocate(3)
12 | val sink4 = ByteBuffer.allocate(2)
13 |
14 | val bufList = bufferList(
15 | byteBuffer(1, 2, 3, 4, 5, 6),
16 | byteBuffer(7, 8, 9, 10)
17 | )
18 |
19 | assert(bufList.read(sink1))
20 | assertRelativeBytes(sink1, 1, 2)
21 |
22 | assert(bufList.read(sink2))
23 | assertRelativeBytes(sink2, 3, 4)
24 |
25 | assert(bufList.read(sink3))
26 | assertRelativeBytes(sink3, 5, 6, 7)
27 |
28 | assert(bufList.read(sink4))
29 | assertRelativeBytes(sink4, 8, 9)
30 |
31 | assert(bufList.buffers.size == 1)
32 | assert(bufList.buffers(0).remaining() == 1)
33 | }
34 |
35 | it should "handle sources smaller than sink" in {
36 | val sink = ByteBuffer.allocate(3)
37 | val source = byteBuffer(1, 2)
38 |
39 | val bufList = bufferList(source)
40 |
41 | assert(!bufList.read(sink))
42 | assertBytes(sink, 1, 2, 0)
43 | }
44 |
45 | it should "handle same size buffers" in {
46 | val sink = ByteBuffer.allocate(2)
47 | val source = byteBuffer(1, 2)
48 |
49 | val bufList = bufferList(source)
50 |
51 | assert(bufList.read(sink))
52 | assertRelativeBytes(sink, 1, 2)
53 | }
54 |
55 | it should "read from multiple buffers when needed" in {
56 | val sink = ByteBuffer.allocate(3)
57 | val source1 = byteBuffer(1, 2)
58 | val source2 = byteBuffer(3, 4)
59 |
60 | val bufList = bufferList(source1, source2)
61 |
62 | assert(bufList.read(sink))
63 | assertRelativeBytes(sink, 1, 2, 3)
64 |
65 | assert(bufList.buffers.size == 1)
66 | assert(bufList.buffers(0).remaining() == 1)
67 | }
68 |
69 | it should "support reading multiple different parts" in {
70 | val sink1 = ByteBuffer.allocate(4)
71 | val sink2 = ByteBuffer.allocate(2)
72 | val sink3 = ByteBuffer.allocate(3)
73 |
74 | val bufList = bufferList(
75 | byteBuffer(1, 2, 3),
76 | byteBuffer(4, 5, 6),
77 | byteBuffer(7, 8, 9)
78 | )
79 |
80 | assert(bufList.read(sink1))
81 | assertRelativeBytes(sink1, 1, 2, 3, 4)
82 | assert(bufList.buffers.size == 2)
83 |
84 | assert(bufList.read(sink2))
85 | assertBytes(sink2, 5, 6)
86 | assert(bufList.buffers.size == 1)
87 |
88 | assert(bufList.read(sink3))
89 | assertBytes(sink3, 7, 8, 9)
90 | assert(bufList.buffers.isEmpty)
91 | }
92 |
93 | def byteBuffer(values: Int*): ByteBuffer = {
94 | val bb = ByteBuffer.allocate(values.size)
95 | for (v <- values) {
96 | bb.put(v.toByte)
97 | }
98 | bb.flip()
99 | bb
100 | }
101 |
102 | def bufferList(buffers: ByteBuffer*): ByteBufferList = {
103 | val bl = new ByteBufferList
104 | for (buf <- buffers) {
105 | bl.add(buf)
106 | }
107 | bl
108 | }
109 |
110 | def assertRelativeBytes(bb: ByteBuffer, values: Int*): Unit = {
111 | for (v <- values) {
112 | assert(bb.get() == v.toByte)
113 | }
114 | }
115 |
116 | def assertBytes(bb: ByteBuffer, values: Int*): Unit = {
117 | for ((v, i) <- values.zipWithIndex) {
118 | assert(bb.get(i) == v.toByte)
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/scala.capnp:
--------------------------------------------------------------------------------
1 | @0xd70a72f78b29ea0d;
2 |
3 | annotation package @0xee44ce11f43e05d7 (file) : Text;
4 | # Name of the package, such as "org.example.foo", in which the generated code will reside.
5 |
6 | annotation module @0xfd7b105ce99a1686 (file) : Text;
7 | # Name of the object containing the generated code.
--------------------------------------------------------------------------------
/schema.capnp:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
2 | # Licensed under the MIT License:
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy
5 | # of this software and associated documentation files (the "Software"), to deal
6 | # in the Software without restriction, including without limitation the rights
7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the Software is
9 | # furnished to do so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in
12 | # all copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | # THE SOFTWARE.
21 |
22 | using Scala = import "scala.capnp";
23 |
24 | @0xa93fc509624c72d9;
25 |
26 | $Scala.package("org.katis.capnproto.compiler");
27 | $Scala.module("schema");
28 |
29 | using Id = UInt64;
30 | # The globally-unique ID of a file, type, or annotation.
31 |
32 | struct Node {
33 | id @0 :Id;
34 |
35 | displayName @1 :Text;
36 | # Name to present to humans to identify this Node. You should not attempt to parse this. Its
37 | # format could change. It is not guaranteed to be unique.
38 | #
39 | # (On Zooko's triangle, this is the node's nickname.)
40 |
41 | displayNamePrefixLength @2 :UInt32;
42 | # If you want a shorter version of `displayName` (just naming this node, without its surrounding
43 | # scope), chop off this many characters from the beginning of `displayName`.
44 |
45 | scopeId @3 :Id;
46 | # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back
47 | # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not
48 | # listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is
49 | # zero if the node has no parent, which is normally only the case with files, but should be
50 | # allowed for any kind of node (in order to make runtime type generation easier).
51 |
52 | parameters @32 :List(Parameter);
53 | # If this node is parameterized (generic), the list of parameters. Empty for non-generic types.
54 |
55 | isGeneric @33 :Bool;
56 | # True if this node is generic, meaning that it or one of its parent scopes has a non-empty
57 | # `parameters`.
58 |
59 | struct Parameter {
60 | # Information about one of the node's parameters.
61 |
62 | name @0 :Text;
63 | }
64 |
65 | nestedNodes @4 :List(NestedNode);
66 | # List of nodes nested within this node, along with the names under which they were declared.
67 |
68 | struct NestedNode {
69 | name @0 :Text;
70 | # Unqualified symbol name. Unlike Node.displayName, this *can* be used programmatically.
71 | #
72 | # (On Zooko's triangle, this is the node's petname according to its parent scope.)
73 |
74 | id @1 :Id;
75 | # ID of the nested node. Typically, the target node's scopeId points back to this node, but
76 | # robust code should avoid relying on this.
77 | }
78 |
79 | annotations @5 :List(Annotation);
80 | # Annotations applied to this node.
81 |
82 | union {
83 | # Info specific to each kind of node.
84 |
85 | file @6 :Void;
86 |
87 | struct :group {
88 | dataWordCount @7 :UInt16;
89 | # Size of the data section, in words.
90 |
91 | pointerCount @8 :UInt16;
92 | # Size of the pointer section, in pointers (which are one word each).
93 |
94 | preferredListEncoding @9 :ElementSize;
95 | # The preferred element size to use when encoding a list of this struct. If this is anything
96 | # other than `inlineComposite` then the struct is one word or less in size and is a candidate
97 | # for list packing optimization.
98 |
99 | isGroup @10 :Bool;
100 | # If true, then this "struct" node is actually not an independent node, but merely represents
101 | # some named union or group within a particular parent struct. This node's scopeId refers
102 | # to the parent struct, which may itself be a union/group in yet another struct.
103 | #
104 | # All group nodes share the same dataWordCount and pointerCount as the top-level
105 | # struct, and their fields live in the same ordinal and offset spaces as all other fields in
106 | # the struct.
107 | #
108 | # Note that a named union is considered a special kind of group -- in fact, a named union
109 | # is exactly equivalent to a group that contains nothing but an unnamed union.
110 |
111 | discriminantCount @11 :UInt16;
112 | # Number of fields in this struct which are members of an anonymous union, and thus may
113 | # overlap. If this is non-zero, then a 16-bit discriminant is present indicating which
114 | # of the overlapping fields is active. This can never be 1 -- if it is non-zero, it must be
115 | # two or more.
116 | #
117 | # Note that the fields of an unnamed union are considered fields of the scope containing the
118 | # union -- an unnamed union is not its own group. So, a top-level struct may contain a
119 | # non-zero discriminant count. Named unions, on the other hand, are equivalent to groups
120 | # containing unnamed unions. So, a named union has its own independent schema node, with
121 | # `isGroup` = true.
122 |
123 | discriminantOffset @12 :UInt32;
124 | # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in
125 | # multiples of 16 bits.
126 |
127 | fields @13 :List(Field);
128 | # Fields defined within this scope (either the struct's top-level fields, or the fields of
129 | # a particular group; see `isGroup`).
130 | #
131 | # The fields are sorted by ordinal number, but note that because groups share the same
132 | # ordinal space, the field's index in this list is not necessarily exactly its ordinal.
133 | # On the other hand, the field's position in this list does remain the same even as the
134 | # protocol evolves, since it is not possible to insert or remove an earlier ordinal.
135 | # Therefore, for most use cases, if you want to identify a field by number, it may make the
136 | # most sense to use the field's index in this list rather than its ordinal.
137 | }
138 |
139 | enum :group {
140 | enumerants@14 :List(Enumerant);
141 | # Enumerants ordered by numeric value (ordinal).
142 | }
143 |
144 | interface :group {
145 | methods @15 :List(Method);
146 | # Methods ordered by ordinal.
147 |
148 | superclasses @31 :List(Superclass);
149 | # Superclasses of this interface.
150 | }
151 |
152 | const :group {
153 | type @16 :Type;
154 | value @17 :Value;
155 | }
156 |
157 | annotation :group {
158 | type @18 :Type;
159 |
160 | targetsFile @19 :Bool;
161 | targetsConst @20 :Bool;
162 | targetsEnum @21 :Bool;
163 | targetsEnumerant @22 :Bool;
164 | targetsStruct @23 :Bool;
165 | targetsField @24 :Bool;
166 | targetsUnion @25 :Bool;
167 | targetsGroup @26 :Bool;
168 | targetsInterface @27 :Bool;
169 | targetsMethod @28 :Bool;
170 | targetsParam @29 :Bool;
171 | targetsAnnotation @30 :Bool;
172 | }
173 | }
174 | }
175 |
176 | struct Field {
177 | # Schema for a field of a struct.
178 |
179 | name @0 :Text;
180 |
181 | codeOrder @1 :UInt16;
182 | # Indicates where this member appeared in the code, relative to other members.
183 | # Code ordering may have semantic relevance -- programmers tend to place related fields
184 | # together. So, using code ordering makes sense in human-readable formats where ordering is
185 | # otherwise irrelevant, like JSON. The values of codeOrder are tightly-packed, so the maximum
186 | # value is count(members) - 1. Fields that are members of a union are only ordered relative to
187 | # the other members of that union, so the maximum value there is count(union.members).
188 |
189 | annotations @2 :List(Annotation);
190 |
191 | const noDiscriminant :UInt16 = 0xffff;
192 |
193 | discriminantValue @3 :UInt16 = Field.noDiscriminant;
194 | # If the field is in a union, this is the value which the union's discriminant should take when
195 | # the field is active. If the field is not in a union, this is 0xffff.
196 |
197 | union {
198 | slot :group {
199 | # A regular, non-group, non-fixed-list field.
200 |
201 | offset @4 :UInt32;
202 | # Offset, in units of the field's size, from the beginning of the section in which the field
203 | # resides. E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the
204 | # beginning of the data section.
205 |
206 | type @5 :Type;
207 | defaultValue @6 :Value;
208 |
209 | hadExplicitDefault @10 :Bool;
210 | # Whether the default value was specified explicitly. Non-explicit default values are always
211 | # zero or empty values. Usually, whether the default value was explicit shouldn't matter.
212 | # The main use case for this flag is for structs representing method parameters:
213 | # explicitly-defaulted parameters may be allowed to be omitted when calling the method.
214 | }
215 |
216 | group :group {
217 | # A group.
218 |
219 | typeId @7 :Id;
220 | # The ID of the group's node.
221 | }
222 | }
223 |
224 | ordinal :union {
225 | implicit @8 :Void;
226 | explicit @9 :UInt16;
227 | # The original ordinal number given to the field. You probably should NOT use this; if you need
228 | # a numeric identifier for a field, use its position within the field array for its scope.
229 | # The ordinal is given here mainly just so that the original schema text can be reproduced given
230 | # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job.
231 | }
232 | }
233 |
234 | struct Enumerant {
235 | # Schema for member of an enum.
236 |
237 | name @0 :Text;
238 |
239 | codeOrder @1 :UInt16;
240 | # Specifies order in which the enumerants were declared in the code.
241 | # Like Struct.Field.codeOrder.
242 |
243 | annotations @2 :List(Annotation);
244 | }
245 |
246 | struct Superclass {
247 | id @0 :Id;
248 | brand @1 :Brand;
249 | }
250 |
251 | struct Method {
252 | # Schema for method of an interface.
253 |
254 | name @0 :Text;
255 |
256 | codeOrder @1 :UInt16;
257 | # Specifies order in which the methods were declared in the code.
258 | # Like Struct.Field.codeOrder.
259 |
260 | implicitParameters @7 :List(Node.Parameter);
261 | # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended
262 | # to be inferred rather than specified explicitly, although not all languages support this.
263 |
264 | paramStructType @2 :Id;
265 | # ID of the parameter struct type. If a named parameter list was specified in the method
266 | # declaration (rather than a single struct parameter type) then a corresponding struct type is
267 | # auto-generated. Such an auto-generated type will not be listed in the interface's
268 | # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace.
269 | # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes
270 | # this a situation where you can't just climb the scope chain to find where a particular
271 | # generic parameter was introduced. Making the `scopeId` zero was a mistake.)
272 |
273 | paramBrand @5 :Brand;
274 | # Brand of param struct type.
275 |
276 | resultStructType @3 :Id;
277 | # ID of the return struct type; similar to `paramStructType`.
278 |
279 | resultBrand @6 :Brand;
280 | # Brand of result struct type.
281 |
282 | annotations @4 :List(Annotation);
283 | }
284 |
285 | struct Type {
286 | # Represents a type expression.
287 |
288 | union {
289 | # The ordinals intentionally match those of Value.
290 |
291 | void @0 :Void;
292 | bool @1 :Void;
293 | int8 @2 :Void;
294 | int16 @3 :Void;
295 | int32 @4 :Void;
296 | int64 @5 :Void;
297 | uint8 @6 :Void;
298 | uint16 @7 :Void;
299 | uint32 @8 :Void;
300 | uint64 @9 :Void;
301 | float32 @10 :Void;
302 | float64 @11 :Void;
303 | text @12 :Void;
304 | data @13 :Void;
305 |
306 | list :group {
307 | elementType @14 :Type;
308 | }
309 |
310 | enum :group {
311 | typeId @15 :Id;
312 | brand @21 :Brand;
313 | }
314 | struct :group {
315 | typeId @16 :Id;
316 | brand @22 :Brand;
317 | }
318 | interface :group {
319 | typeId @17 :Id;
320 | brand @23 :Brand;
321 | }
322 |
323 | anyPointer :union {
324 | unconstrained @18 :Void;
325 | # A regular AnyPointer.
326 |
327 | parameter :group {
328 | # This is actually a reference to a type parameter defined within this scope.
329 |
330 | scopeId @19 :Id;
331 | # ID of the generic type whose parameter we're referencing. This should be a parent of the
332 | # current scope.
333 |
334 | parameterIndex @20 :UInt16;
335 | # Index of the parameter within the generic type's parameter list.
336 | }
337 |
338 | implicitMethodParameter :group {
339 | # This is actually a reference to an implicit (generic) parameter of a method. The only
340 | # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand.
341 |
342 | parameterIndex @24 :UInt16;
343 | }
344 | }
345 | }
346 | }
347 |
348 | struct Brand {
349 | # Specifies bindings for parameters of generics. Since these bindings turn a generic into a
350 | # non-generic, we call it the "brand".
351 |
352 | scopes @0 :List(Scope);
353 | # For each of the target type and each of its parent scopes, a parameterization may be included
354 | # in this list. If no parameterization is included for a particular relevant scope, then either
355 | # that scope has no parameters or all parameters should be considered to be `AnyPointer`.
356 |
357 | struct Scope {
358 | scopeId @0 :Id;
359 | # ID of the scope to which these params apply.
360 |
361 | union {
362 | bind @1 :List(Binding);
363 | # List of parameter bindings.
364 |
365 | inherit @2 :Void;
366 | # The place where this Brand appears is actually within this scope or a sub-scope,
367 | # and the bindings for this scope should be inherited from the reference point.
368 | }
369 | }
370 |
371 | struct Binding {
372 | union {
373 | unbound @0 :Void;
374 | type @1 :Type;
375 |
376 | # TODO(someday): Allow non-type parameters? Unsure if useful.
377 | }
378 | }
379 | }
380 |
381 | struct Value {
382 | # Represents a value, e.g. a field default value, constant value, or annotation value.
383 |
384 | union {
385 | # The ordinals intentionally match those of Type.
386 |
387 | void @0 :Void;
388 | bool @1 :Bool;
389 | int8 @2 :Int8;
390 | int16 @3 :Int16;
391 | int32 @4 :Int32;
392 | int64 @5 :Int64;
393 | uint8 @6 :UInt8;
394 | uint16 @7 :UInt16;
395 | uint32 @8 :UInt32;
396 | uint64 @9 :UInt64;
397 | float32 @10 :Float32;
398 | float64 @11 :Float64;
399 | text @12 :Text;
400 | data @13 :Data;
401 |
402 | list @14 :AnyPointer;
403 |
404 | enum @15 :UInt16;
405 | struct @16 :AnyPointer;
406 |
407 | interface @17 :Void;
408 | # The only interface value that can be represented statically is "null", whose methods always
409 | # throw exceptions.
410 |
411 | anyPointer @18 :AnyPointer;
412 | }
413 | }
414 |
415 | struct Annotation {
416 | # Describes an annotation applied to a declaration. Note AnnotationNode describes the
417 | # annotation's declaration, while this describes a use of the annotation.
418 |
419 | id @0 :Id;
420 | # ID of the annotation node.
421 |
422 | brand @2 :Brand;
423 | # Brand of the annotation.
424 | #
425 | # Note that the annotation itself is not allowed to be parameterized, but its scope might be.
426 |
427 | value @1 :Value;
428 | }
429 |
430 | enum ElementSize {
431 | # Possible element sizes for encoded lists. These correspond exactly to the possible values of
432 | # the 3-bit element size component of a list pointer.
433 |
434 | empty @0; # aka "void", but that's a keyword.
435 | bit @1;
436 | byte @2;
437 | twoBytes @3;
438 | fourBytes @4;
439 | eightBytes @5;
440 | pointer @6;
441 | inlineComposite @7;
442 | }
443 |
444 | struct CodeGeneratorRequest {
445 | nodes @0 :List(Node);
446 | # All nodes parsed by the compiler, including for the files on the command line and their
447 | # imports.
448 |
449 | requestedFiles @1 :List(RequestedFile);
450 | # Files which were listed on the command line.
451 |
452 | struct RequestedFile {
453 | id @0 :Id;
454 | # ID of the file.
455 |
456 | filename @1 :Text;
457 | # Name of the file as it appeared on the command-line (minus the src-prefix). You may use
458 | # this to decide where to write the output.
459 |
460 | imports @2 :List(Import);
461 | # List of all imported paths seen in this file.
462 |
463 | struct Import {
464 | id @0 :Id;
465 | # ID of the imported file.
466 |
467 | name @1 :Text;
468 | # Name which *this* file used to refer to the foreign file. This may be a relative name.
469 | # This information is provided because it might be useful for code generation, e.g. to
470 | # generate #include directives in C++. We don't put this in Node.file because this
471 | # information is only meaningful at compile time anyway.
472 | #
473 | # (On Zooko's triangle, this is the import's petname according to the importing file.)
474 | }
475 | }
476 | }
477 |
--------------------------------------------------------------------------------