nuvoc

High Performance Serialization for Scala Types

Advanced Serialization Framework

nuvoc is an advanced serialization framework that allows you to define the types exhanged by your applications using Scalacase classes. As such nuvoc provides support for both simple types as well algebraic data types. Currently, the types handled by nuvoc are a subset of legal Scala case classes, yet even with this limitation the flexibility and the elegance of the framework stands out when compared to similar (in spirit) framework such as protobuf.

Simple Type

Simple case types, meaning a case type declaration with an arbitrary number of attributes is supported. Some restriction apply on the types of the attribute, since those are supposed to be one of the following types:

  • Primitive Type
  • java.nio.ByteBuffer
  • A valid nuvoc type
  • An array of legal attribute types
  • A list of legal attribute types
  • An Option type for a valid attribute type
Below are a few examples of some simple nuvoc types.

// Type with only primitive attributes
case class StockQuote(symbol: String, xchange: String, value: Float)

// Type with a list of primitive types
case class StockDigest(symbol: String, xchange: String, valueWindow: List[Float])

// Type with a list of primitive types
case class BatchOrder(batch: List[StockQuote])

Algebraic Data Type

Scala supports algebraic data types via the combinations of case classes and pattern matching. nuvoc supports the serialization and deserialization of algebraic data types. Below is an example of algebraic data types support in nuvoc.

case class Bounds(w: Int, h: Int)	

case class Vector2D(x: Float, y: Float)
 
sealed abstract class Shape(val p: Vector2D, val b: Bounds)

case class Circle(override val p: Vector2D, r: Float) extends Shape(p, Bounds((2*r), (2*r)))

case class Rectangle(override val p: Vector2D, w: Float, h: Float) extends Shape(x, y, Bounds(w, h))

Keyed Type

Finally, nuvoc provide support for types that define a key. A valid key is a tuple of attributes as shown in the examples below.

case class Vehicle(vid: Long, pos: Vector2D, speed: Vector2D) {
	lazy val key = vid
}	

case class Order(s: String, xch: String, q: Float) {
	lazy val key = (s, xch)
}

Serializing and Deserializing Nuvo Types

The nuvoc compiler generates some code that is used by the serialization/deserialization framework. Serializing a nuvo type is pretty straightfoward and it is as simple as writing any other type on a nuvo.nio.ByteBuffer . On the other hand to deserializing an object is as simple as getting it out of a nuvo.nio.ByteBuffer . The example below shows how this can be done.

val buf = nuvo.nio.RawBuffer.allocateDirect(1024)
val sq = StockQuote("ACME", "NYSE", "123.45")

// Serializing is as simple as writing the object on the stream 
buf.putObject(sq)

// To read back the serialized object let's flip the buffer
buf.flip()

// Now the object can be taken out the buffer
buf.getObject[StockQuote] 

Serialization Formats

The nuvo serialization framework is designed to supports multiple formats. The current version only supports the Nuvo Serialization Format (NuvoSF) and the Java Serialization Format (JavaSF). The next release will also add support for the JSON Serialization Format (JsonSF). The NuvoSF is designed to otmimize time and space, yet can only serialize nuvo types. The format to use when serializing an object can be controlled as shown in the example below. When not explicitely defined, the serialization format used is NuvoSF.

val buf = nuvo.nio.RawBuffer.allocateDirect(1024)
val sq = StockQuote("ACME", "NYSE", "123.45")

// The serialization format can be specified as a command line argument 
buf.putObject(sq, NuvoSF)
buf.putObject(sq, JsonSF)

// To read back the serialized object let's flip the buffer
buf.flip()

// Now the objects can be taken out the buffer
buf.getObject[StockQuote](NuvoSF)
buf.getObject[StockQuote](JsonSF)