11package com .avsystem .commons
22package mongo
33
4- import java .nio .ByteBuffer
5- import com .avsystem .commons .serialization .GenCodec .{ReadFailure , WriteFailure }
6- import com .avsystem .commons .serialization .{GenCodec , GenKeyCodec , TransparentWrapping }
7- import org .bson .codecs .{BsonValueCodec , DecoderContext , EncoderContext }
4+ import com .avsystem .commons .serialization .GenCodec .ReadFailure
5+ import com .avsystem .commons .serialization ._
6+ import org .bson ._
87import org .bson .io .BasicOutputBuffer
98import org .bson .types .{Decimal128 , ObjectId }
10- import org .bson .{BsonArray , BsonBinary , BsonBinaryReader , BsonBinaryWriter , BsonBoolean , BsonDateTime , BsonDecimal128 , BsonDocument , BsonDouble , BsonElement , BsonInt32 , BsonInt64 , BsonNull , BsonObjectId , BsonString , BsonType , BsonValue }
9+
10+ import java .nio .ByteBuffer
1111
1212trait BsonGenCodecs {
1313 implicit def objectIdCodec : GenCodec [ObjectId ] = BsonGenCodecs .objectIdCodec
1414 implicit def objectIdKeyCodec : GenKeyCodec [ObjectId ] = BsonGenCodecs .objectIdKeyCodec
15-
1615 implicit def decimal128Codec : GenCodec [Decimal128 ] = BsonGenCodecs .decimal128Codec
1716
1817 implicit def bsonArrayCodec : GenCodec [BsonArray ] = BsonGenCodecs .bsonArrayCodec
@@ -33,13 +32,13 @@ trait BsonGenCodecs {
3332object BsonGenCodecs {
3433 // needed so that ObjectId can be used as ID type in AutoIdMongoEntity
3534 // (TransparentWrapping is used in EntityIdMode)
36- implicit val objectIdIdentityWrapping : TransparentWrapping [ObjectId , ObjectId ] =
37- TransparentWrapping .identity
35+ implicit val objectIdIdentityWrapping : TransparentWrapping [ObjectId , ObjectId ] = TransparentWrapping .identity
3836
3937 implicit val objectIdCodec : GenCodec [ObjectId ] = GenCodec .nullable(
4038 i => i.readCustom(ObjectIdMarker ).getOrElse(new ObjectId (i.readSimple().readString())),
4139 (o, v) => if (! o.writeCustom(ObjectIdMarker , v)) o.writeSimple().writeString(v.toHexString)
4240 )
41+
4342 implicit val objectIdKeyCodec : GenKeyCodec [ObjectId ] =
4443 GenKeyCodec .create(new ObjectId (_), _.toHexString)
4544
@@ -48,104 +47,43 @@ object BsonGenCodecs {
4847 (o, v) => if (! o.writeCustom(Decimal128Marker , v)) o.writeSimple().writeBigDecimal(v.bigDecimalValue())
4948 )
5049
51- implicit val bsonArrayCodec : GenCodec [BsonArray ] = GenCodec .nullableList(
52- li => new BsonArray (li.iterator(bsonValueCodec.read).to(JList )),
53- (lo, ba) => ba.asScala.foreach(bsonValueCodec.write(lo.writeElement(), _))
54- )
55-
56- implicit val bsonBinaryCodec : GenCodec [BsonBinary ] =
57- GenCodec .ByteArrayCodec .transform[BsonBinary ](_.getData, new BsonBinary (_))
58-
59- implicit val bsonBooleanCodec : GenCodec [BsonBoolean ] =
60- GenCodec .BooleanCodec .transform[BsonBoolean ](_.getValue, new BsonBoolean (_))
61-
62- implicit val bsonDateTimeCodec : GenCodec [BsonDateTime ] = GenCodec .nullableSimple(
63- i => new BsonDateTime (i.readTimestamp()),
64- (o, v) => o.writeTimestamp(v.getValue)
65- )
66-
67- implicit val bsonDocumentCodec : GenCodec [BsonDocument ] = GenCodec .nullableObject(
68- oi => new BsonDocument (oi.iterator(bsonValueCodec.read).map {
69- case (k, v) => new BsonElement (k, v)
70- }.to(JList )),
71- (oo, bd) => bd.asScala.foreach { case (key, value) =>
72- bsonValueCodec.write(oo.writeField(key), value)
50+ implicit val bsonValueCodec : GenCodec [BsonValue ] = GenCodec .create(
51+ i => i.readCustom(BsonValueMarker ).getOrElse {
52+ val reader = new BsonBinaryReader (ByteBuffer .wrap(i.readSimple().readBinary()))
53+ BsonValueUtils .decode(reader)
54+ },
55+ (o, bv) => if (! o.writeCustom(BsonValueMarker , bv)) {
56+ val buffer = new BasicOutputBuffer ()
57+ val writer = new BsonBinaryWriter (buffer)
58+ BsonValueUtils .encode(writer, bv)
59+ writer.flush()
60+ writer.close()
61+ o.writeSimple().writeBinary(buffer.toByteArray)
7362 }
7463 )
7564
76- implicit val bsonDecimal128Codec : GenCodec [BsonDecimal128 ] =
77- decimal128Codec.transform[BsonDecimal128 ](_.getValue, new BsonDecimal128 (_))
78-
79- implicit val bsonDoubleCodec : GenCodec [BsonDouble ] =
80- GenCodec .DoubleCodec .transform(_.getValue, new BsonDouble (_))
81-
82- implicit val bsonInt32Codec : GenCodec [BsonInt32 ] =
83- GenCodec .IntCodec .transform(_.getValue, new BsonInt32 (_))
65+ private def bsonValueSubCodec [T <: BsonValue ](fromBsonValue : BsonValue => T ): GenCodec [T ] =
66+ bsonValueCodec.transform(identity, fromBsonValue)
8467
85- implicit val bsonInt64Codec : GenCodec [BsonInt64 ] =
86- GenCodec .LongCodec .transform(_.getValue, new BsonInt64 (_))
68+ implicit val bsonArrayCodec : GenCodec [BsonArray ] = bsonValueSubCodec(_.asArray())
69+ implicit val bsonBinaryCodec : GenCodec [BsonBinary ] = bsonValueSubCodec(_.asBinary())
70+ implicit val bsonBooleanCodec : GenCodec [BsonBoolean ] = bsonValueSubCodec(_.asBoolean())
71+ implicit val bsonDateTimeCodec : GenCodec [BsonDateTime ] = bsonValueSubCodec(_.asDateTime())
72+ implicit val bsonDocumentCodec : GenCodec [BsonDocument ] = bsonValueSubCodec(_.asDocument())
73+ implicit val bsonDecimal128Codec : GenCodec [BsonDecimal128 ] = bsonValueSubCodec(_.asDecimal128())
74+ implicit val bsonDoubleCodec : GenCodec [BsonDouble ] = bsonValueSubCodec(_.asDouble())
75+ implicit val bsonInt32Codec : GenCodec [BsonInt32 ] = bsonValueSubCodec(_.asInt32())
76+ implicit val bsonInt64Codec : GenCodec [BsonInt64 ] = bsonValueSubCodec(_.asInt64())
8777
8878 implicit val bsonNullCodec : GenCodec [BsonNull ] =
89- GenCodec .create(i => {
90- if (! i.readNull()) throw new ReadFailure ( " Input did not contain expected null value " )
91- BsonNull . VALUE
92- }, (o, _) => o.writeNull())
79+ bsonValueSubCodec { bv =>
80+ if (bv.isNull) BsonNull . VALUE
81+ else throw new ReadFailure ( " Input did not contain expected null value " )
82+ }
9383
9484 implicit val bsonObjectIdCodec : GenCodec [BsonObjectId ] =
9585 objectIdCodec.transform(_.getValue, new BsonObjectId (_))
9686
9787 implicit val bsonStringCodec : GenCodec [BsonString ] =
9888 GenCodec .StringCodec .transform(_.getValue, new BsonString (_))
99-
100- private val mongoBsonValueCodec : BsonValueCodec = new BsonValueCodec ()
101- private val mongoDecoderContext : DecoderContext = DecoderContext .builder().build()
102- private val mongoEncoderContext : EncoderContext = EncoderContext .builder().build()
103-
104- implicit val bsonValueCodec : GenCodec [BsonValue ] = GenCodec .create(
105- i => {
106- val bvOpt = i.readMetadata(BsonTypeMetadata ) map {
107- case BsonType .ARRAY => bsonArrayCodec.read(i)
108- case BsonType .BINARY => bsonBinaryCodec.read(i)
109- case BsonType .BOOLEAN => bsonBooleanCodec.read(i)
110- case BsonType .DATE_TIME => bsonDateTimeCodec.read(i)
111- case BsonType .DECIMAL128 => bsonDecimal128Codec.read(i)
112- case BsonType .DOCUMENT => bsonDocumentCodec.read(i)
113- case BsonType .DOUBLE => bsonDoubleCodec.read(i)
114- case BsonType .INT32 => bsonInt32Codec.read(i)
115- case BsonType .INT64 => bsonInt64Codec.read(i)
116- case BsonType .NULL => bsonNullCodec.read(i)
117- case BsonType .OBJECT_ID => bsonObjectIdCodec.read(i)
118- case BsonType .STRING => bsonStringCodec.read(i)
119- case other => throw new ReadFailure (s " Unsupported Bson type: $other" )
120- }
121- bvOpt.getOrElse {
122- val reader = new BsonBinaryReader (ByteBuffer .wrap(i.readSimple().readBinary()))
123- mongoBsonValueCodec.decode(reader, mongoDecoderContext)
124- }
125- },
126- (o, bv) => if (o.keepsMetadata(BsonTypeMetadata )) {
127- bv match {
128- case array : BsonArray => bsonArrayCodec.write(o, array)
129- case binary : BsonBinary => bsonBinaryCodec.write(o, binary)
130- case boolean : BsonBoolean => bsonBooleanCodec.write(o, boolean)
131- case dateTime : BsonDateTime => bsonDateTimeCodec.write(o, dateTime)
132- case decimal128 : BsonDecimal128 => bsonDecimal128Codec.write(o, decimal128)
133- case document : BsonDocument => bsonDocumentCodec.write(o, document)
134- case double : BsonDouble => bsonDoubleCodec.write(o, double)
135- case int32 : BsonInt32 => bsonInt32Codec.write(o, int32)
136- case int64 : BsonInt64 => bsonInt64Codec.write(o, int64)
137- case bNull : BsonNull => bsonNullCodec.write(o, bNull)
138- case objectId : BsonObjectId => bsonObjectIdCodec.write(o, objectId)
139- case string : BsonString => bsonStringCodec.write(o, string)
140- case other => throw new WriteFailure (s " Unsupported value: $other" )
141- }
142- } else {
143- val buffer = new BasicOutputBuffer ()
144- val writer = new BsonBinaryWriter (buffer)
145- mongoBsonValueCodec.encode(writer, bv, mongoEncoderContext)
146- writer.flush()
147- writer.close()
148- o.writeSimple().writeBinary(buffer.toByteArray)
149- }
150- )
15189}
0 commit comments