77 lines
2.5 KiB
Scala
77 lines
2.5 KiB
Scala
package net.okennedy.cells
|
|
|
|
import scala.collection.mutable
|
|
import play.api.libs.json.Json
|
|
import play.api.libs.json.Format
|
|
import play.api.libs.json.JsResult
|
|
import play.api.libs.json.JsValue
|
|
import play.api.libs.json.JsSuccess
|
|
import play.api.libs.json.JsObject
|
|
import play.api.libs.json.JsString
|
|
|
|
sealed trait SeqOp[T]
|
|
{
|
|
def apply(seq: Seq[T]): Seq[T]
|
|
def map[B](op: T => B): SeqOp[B]
|
|
def bufferApply(seq: mutable.Buffer[T]): Unit
|
|
}
|
|
|
|
|
|
case class SeqInsert[T](position: Int, value: T) extends SeqOp[T]
|
|
{
|
|
def apply(seq: Seq[T]): Seq[T] =
|
|
{
|
|
val (before, after) = seq.splitAt(position)
|
|
(before :+ value) ++ after
|
|
}
|
|
def map[B](op: T => B): SeqOp[B] = SeqInsert[B](position, op(value))
|
|
def bufferApply(seq: mutable.Buffer[T]): Unit =
|
|
seq.insert(position, value)
|
|
}
|
|
case class SeqDelete[T](position: Int) extends SeqOp[T]
|
|
{
|
|
def apply(seq: Seq[T]): Seq[T] =
|
|
{
|
|
val (before, after) = seq.splitAt(position)
|
|
before ++ after.drop(1)
|
|
}
|
|
def map[B](op: T => B): SeqOp[B] = SeqDelete(position)
|
|
def bufferApply(seq: mutable.Buffer[T]): Unit =
|
|
seq.remove(position)
|
|
}
|
|
case class SeqReplace[T](position: Int, value: T) extends SeqOp[T]
|
|
{
|
|
def apply(seq: Seq[T]): Seq[T] =
|
|
{
|
|
val (before, after) = seq.splitAt(position)
|
|
(before :+ value) ++ after.drop(1)
|
|
}
|
|
def map[B](op: T => B): SeqOp[B] = SeqReplace[B](position, op(value))
|
|
def bufferApply(seq: mutable.Buffer[T]): Unit =
|
|
seq(position) = value
|
|
}
|
|
|
|
object SeqOp
|
|
{
|
|
implicit def SeqInsertFormat[T](implicit format: Format[T]): Format[SeqInsert[T]] = Json.format
|
|
implicit def SeqDeleteFormat[T](implicit format: Format[T]): Format[SeqDelete[T]] = Json.format
|
|
implicit def SeqReplaceFormat[T](implicit format: Format[T]): Format[SeqReplace[T]] = Json.format
|
|
implicit def SeqOpFormat[T](implicit format: Format[T]): Format[SeqOp[T]] =
|
|
new Format[SeqOp[T]]{
|
|
def reads(json: JsValue): JsResult[SeqOp[T]] =
|
|
(json \ "op").as[String] match {
|
|
case "insert" => JsSuccess(json.as[SeqInsert[T]])
|
|
case "delete" => JsSuccess(json.as[SeqDelete[T]])
|
|
case "replace" => JsSuccess(json.as[SeqReplace[T]])
|
|
}
|
|
|
|
def writes(o: SeqOp[T]): JsValue =
|
|
JsObject(
|
|
o match {
|
|
case x:SeqInsert[T] => Json.toJson(x).as[Map[String,JsValue]] ++ Map("op" -> JsString("insert"))
|
|
case x:SeqDelete[T] => Json.toJson(x).as[Map[String,JsValue]] ++ Map("op" -> JsString("delete"))
|
|
case x:SeqReplace[T] => Json.toJson(x).as[Map[String,JsValue]] ++ Map("op" -> JsString("replace"))
|
|
}
|
|
)
|
|
}
|
|
} |