Permalink
Browse files

SCALA-66 - New non-global, saner & more performant Encoding / Decodin…

…g for custom types

* Extending into the basic structures for core type conversions, ala "Pseudo" Type Classes.
  • Loading branch information...
1 parent 891c604 commit a24ffe8361a02293627f1b7f6c4bc10ab9ec0105 @bwmcadams bwmcadams committed Nov 22, 2011
@@ -14,88 +14,98 @@
* limitations under the License.
*
*/
-
package com.mongodb.casbah.util.bson
+package primitive
/**
* A Container for BSON Primitive types
*
*/
-sealed trait BSONPrimitive {
+sealed trait BSONPrimitive[Raw] {
/**
* The "container" type for this...
* basically the Scala side primitives
* represented.
- * For example, a BSONDatePrimitive's ContainerType
+ * For example, a BSONDatePrimitive's Primitive
* is a Long , holding the milliseconds
*
* This is, essentially, the MOST RAW type representation
* rather than a specific instantiation.
*/
- type ContainerType <: Any
+ type Primitive <: Any
/**
* The type represented by this primitive
*/
def typeCode: BSONType.TypeCode
/**
- * The "container" value
+ * The bson "container" value, from the raw type
+ *
+ * e.g. Int -> BSON Representation of an Int
+ *
*/
- def bsonValue: ContainerType
+ def bsonValue(raw: Raw): Primitive
+
+ /**
+ * The "raw" type, read from the BSON Primitive
+ *
+ * e.g. BSON Integer -> JVM Int
+ */
+ def rawValue(bson: Primitive): Raw
}
// EOO is not a valid type container ;)
-trait BSONDoublePrimitive extends BSONPrimitive {
- type ContainerType = Double
+trait BSONDoublePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Double
val typeCode = BSONType.Double
}
-trait BSONStringPrimitive extends BSONPrimitive {
- type ContainerType = String
+trait BSONStringPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = String
val typeCode = BSONType.String
}
-trait BSONObjectPrimitive extends BSONPrimitive {
+trait BSONObjectPrimitive[Raw] extends BSONPrimitive[Raw] {
// TODO - Hmm... this could be a Map[String, Any], no?
- type ContainerType = org.bson.BSONObject
+ type Primitive = org.bson.BSONObject
val typeCode = BSONType.Object
}
-trait BSONArrayPrimitive extends BSONPrimitive {
- type ContainerType = Seq[Any]
+trait BSONArrayPrimitive[T, Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Seq[T]
val typeCode = BSONType.Array
}
-sealed trait BSONBinaryPrimitive extends BSONPrimitive {
+sealed trait BSONBinaryPrimitive[Raw] extends BSONPrimitive[Raw] {
val typeCode = BSONType.Binary
def subtypeCode: BSONBinarySubtype.SubtypeCode
}
-trait BSONGenericBinaryPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte]
+trait BSONGenericBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte]
val subtypeCode = BSONBinarySubtype.Generic
}
-trait BSONBinaryFunctionPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte] // TODO - Better type repr?
+trait BSONBinaryFunctionPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte] // TODO - Better type repr?
val subtypeCode = BSONBinarySubtype.Function
}
-trait BSONOldBinaryPrimitive extends BSONBinaryPrimitive {
- type ContainerType = Array[Byte]
+trait BSONOldBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = Array[Byte]
val subtypeCode = BSONBinarySubtype.OldBinary
}
-trait BSONUUIDPrimitive extends BSONBinaryPrimitive {
- type ContainerType = (Long /* most sig bits */, Long /* least sig bits */)
+trait BSONUUIDPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = (Long /* most sig bits */, Long /* least sig bits */)
val subtypeCode = BSONBinarySubtype.UUID
}
-trait BSONNewUUIDPrimitive extends BSONBinaryPrimitive {
- type ContainerType = (Long /* most sig bits */, Long /* least sig bits */)
+trait BSONNewUUIDPrimitive[Raw] extends BSONBinaryPrimitive[Raw] {
+ type Primitive = (Long /* most sig bits */, Long /* least sig bits */)
val subtypeCode = BSONBinarySubtype.NewUUID
}
@@ -107,24 +117,24 @@ trait BSONNewUUIDPrimitive extends BSONBinaryPrimitive {
* Use this for your own custom binarys, BSONBinaryPrimitive is
* sealed for safety/sanity
*/
-trait BSONCustomBinaryPrimitive extends BSONBinaryPrimitive
+trait BSONCustomBinaryPrimitive[Raw] extends BSONBinaryPrimitive[Raw]
-trait BSONObjectIdPrimitive extends BSONPrimitive {
- type ContainerType = (Int /* time */, Int /* machineID */, Int /* Increment */)
+trait BSONObjectIdPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (Int /* time */, Int /* machineID */, Int /* Increment */)
val typeCode = BSONType.ObjectId
}
-trait BSONBooleanPrimitive extends BSONPrimitive {
- type ContainerType = Boolean
+trait BSONBooleanPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Boolean
val typeCode = BSONType.Boolean
}
-trait BSONDatePrimitive extends BSONPrimitive {
- type ContainerType = Long /* the UTC milliseconds since the Unix Epoch. */
+trait BSONDatePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Long /* the UTC milliseconds since the Unix Epoch. */
val typeCode = BSONType.Date
}
-trait BSONRegexPrimitive extends BSONPrimitive {
+trait BSONRegexPrimitive[Raw] extends BSONPrimitive[Raw] {
val typeCode = BSONType.RegEx
/**
* [Regular expression]
@@ -143,41 +153,41 @@ trait BSONRegexPrimitive extends BSONPrimitive {
* 's' for dotall mode ('.' matches everything),
* 'u' to make \w, \W, etc. match unicode.
*/
- type ContainerType = (String /* pattern */, String /* flags */)
+ type Primitive = (String /* pattern */, String /* flags */)
}
/**
* Skip support for the deprecated DBPointer
*/
-trait BSONCodePrimitive extends BSONPrimitive {
- type ContainerType = String
+trait BSONCodePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = String
val typeCode = BSONType.Code
}
-trait BSONSymbolPrimitive extends BSONPrimitive {
+trait BSONSymbolPrimitive[Raw] extends BSONPrimitive[Raw] {
/** Stored as a string */
- type ContainerType = String
+ type Primitive = String
val typeCode = BSONType.Symbol
}
-trait BSONScopedCodePrimitive extends BSONPrimitive {
- type ContainerType = (String /* code */, org.bson.BSONObject /* Scope */)
+trait BSONScopedCodePrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (String /* code */, org.bson.BSONObject /* Scope */)
val typeCode = BSONType.ScopedCode
}
-trait BSONInt32Primitive extends BSONPrimitive {
- type ContainerType = Int
+trait BSONInt32Primitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Int
val typeCode = BSONType.Int32
}
-trait BSONTimestampPrimitive extends BSONPrimitive {
- type ContainerType = (Int /* Time */, Int /* Increment */)
+trait BSONTimestampPrimitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = (Int /* Time */, Int /* Increment */)
val typeCode = BSONType.Timestamp
}
-trait BSONInt64Primitive extends BSONPrimitive {
- type ContainerType = Long /* Yes, Billy. We represent Longs as Longs! */
+trait BSONInt64Primitive[Raw] extends BSONPrimitive[Raw] {
+ type Primitive = Long /* Yes, Billy. We represent Longs as Longs! */
val typeCode = BSONType.Int64
}
@@ -14,8 +14,8 @@
* limitations under the License.
*
*/
-
package com.mongodb.casbah.util.bson
+package primitive
/**
* Enumerative lookup for BSON Types, as defined in the spec
@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2008 - 2011 10gen, Inc. <http://10gen.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.mongodb.casbah.util.bson.primitive
+
+import scala.util.matching.Regex
+import java.util.regex.Pattern
+import org.scala_tools.time.Imports._
+import org.bson.BSON
+
+trait Builtins {
+
+ /**
+ * Scala RegEx
+ */
+ trait ScalaRegexPrimitive extends BSONRegexPrimitive[Regex] {
+ def rawValue(bson: (String /* pattern */, String /* flags */)): scala.util.matching.Regex = {
+ // Construct a RegEx
+ "(?%s)%s".format(bson._2, bson._1).r
+ }
+
+ def bsonValue(raw: Regex): (String /* pattern */, String /* flags */) = {
+ // Reduce a Scala Regex to a raw BSON tuple
+ val jPat = raw.pattern
+ (jPat.pattern, BSON.regexFlags(jPat.flags))
+ }
+ }
+
+ /**
+ * Java Regex
+ */
+ trait JavaRegexPrimitive extends BSONRegexPrimitive[java.util.regex.Pattern] {
+ def rawValue(bson: (String /* pattern */, String /* flags */)): java.util.regex.Pattern = {
+ // Construct a RegEx
+ Pattern.compile("(?%s)%s".format(bson._2, bson._1))
+ }
+
+ def bsonValue(raw: Regex): (String /* pattern */, String /* flags */) = {
+ // Reduce a Scala Regex to a raw BSON tuple
+ (raw.pattern.pattern, BSON.regexFlags(raw.pattern.flags))
+ }
+ }
+
+ /**
+ * 'Option' can't be done ... normally. Might need special logic
+ */
+
+ /**
+ * Some Scala collections for fun and profit.
+ *
+ * TODO - Immutable versions
+ */
+ def typedMutableBufferPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Buffer[A]] = new MutableBufferPrimitive[A] {}
+
+ trait MutableBufferPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Buffer[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Buffer[A] = {
+ bson.toBuffer
+/* // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Buffer(bson: _*)*/
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Buffer[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedMutableSeqPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Seq[A]] = new MutableSeqPrimitive[A] {}
+
+ trait MutableSeqPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Seq[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Seq[A] = {
+ // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Seq(bson: _*)
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Seq[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedMutableSetPrimitive[A]: BSONArrayPrimitive[A, scala.collection.mutable.Set[A]] = new MutableSetPrimitive[A] {}
+
+ trait MutableSetPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.mutable.Set[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.mutable.Set[A] = {
+ // TODO - This is mostly utterly useless and a bit wasteful, ya?
+ scala.collection.mutable.Set(bson: _*)
+ }
+
+ def bsonValue(raw: scala.collection.mutable.Set[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedIterablePrimitive[A]: BSONArrayPrimitive[A, scala.collection.Iterable[A]] = new IterablePrimitive[A] {}
+
+ trait IterablePrimitive[A] extends BSONArrayPrimitive[A, scala.collection.Iterable[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.Iterable[A] = {
+ bson.toIterable
+ }
+
+ def bsonValue(raw: scala.collection.Iterable[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ def typedIteratorPrimitive[A]: BSONArrayPrimitive[A, scala.collection.Iterator[A]] = new IteratorPrimitive[A] {}
+
+ trait IteratorPrimitive[A] extends BSONArrayPrimitive[A, scala.collection.Iterator[A]] {
+ def rawValue(bson: Seq[A]): scala.collection.Iterator[A] = {
+ bson.iterator
+ }
+
+ def bsonValue(raw: scala.collection.Iterator[A]): Seq[A] = {
+ raw.toSeq
+ }
+ }
+
+ trait JodaDateTimePrimitive extends BSONDatePrimitive[DateTime] {
+ def rawValue(bson: Long): DateTime = {
+ new DateTime(bson)
+ }
+
+ def bsonValue(raw: DateTime): Long = {
+ raw.getMillis
+ }
+ }
+
+ trait JDKDatePrimitive extends BSONDatePrimitive[java.util.Date] {
+ def rawValue(bson: Long): java.util.Date = {
+ new java.util.Date(bson)
+ }
+
+ def bsonValue(raw: java.util.Date): Long = {
+ raw.getTime
+ }
+ }
+
+
+
+}
+
+

0 comments on commit a24ffe8

Please sign in to comment.