├── .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 | --------------------------------------------------------------------------------