Writing With Typeclasses
Details on how output is converted to bytes and how the design can be extended and used
Custom Data Types
Declaring custom converters.
Naturally being able to write objects other than those defined by Scala IO can be beneficial and it is a simple process. All that is needed is a new implementation of a OutputConverter which is imported into scopoe.
The examples below show two design patterns.
import scalax.io._
import Resource._
import OutputConverter._
val out = fromFileString("out")
// Simplest design pattern is to create a new implicit object in scope
implicit object DateConverter extends OutputConverter[Date] {
def sizeInBytes = 8
def toBytes(data: Date) = LongConverter.toBytes(data.getTime)
}
out.write(new Date(2012,01,01))
// write, append, patch and insert all follow the same pattern
out.append(3)
// The second (an more reusable design pattern) is to create an object
// that contains the converters that you want to use and then they can be
// reused through out the code base.
object CustomConverters {
case class User(name:String,id:Int)
// first you need converter for a collection of your type
implicit object UserTraversableConverter extends OutputConverter[TraversableOnce[User]] {
def sizeInBytes = 2
def toBytes(users: TraversableOnce[User]):TraversableOnce[Byte] = {
// Create a single instance of a buffer for encoding the id value.
val idBuffer = new OutputConverter.Buffer[Int](4,(byteBuffer,data) => {byteBuffer.putInt(data)})
users.toIterator.flatMap{
user =>
user.name.getBytes("ASCII").toIterator ++ idBuffer.put(user.id)
}
}
}
// next you need converters for the basic type and arrays
implicit object UserConverter extends NonTraversableAdapter(UserTraversableConverter)
implicit object UserArrayConverter extends ArrayAdapter(UserTraversableConverter)
}
// finally you can import the definitions into scope and write away
import CustomConverters._
out.write(User("Jesse Eichar",888888))
out.insert(2,User("Jesse",23421))