/* Copyright 2010-present MongoDB Inc.
*
* 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.
*/
using System;
using System.Collections.Generic;
namespace MongoDB.Bson.Serialization.Serializers
{
///
/// Represents a serializer for two-dimensional arrays.
///
/// The type of the elements.
public class TwoDimensionalArraySerializer :
SealedClassSerializerBase,
IChildSerializerConfigurable
{
// private fields
private readonly Lazy> _lazyItemSerializer;
// constructors
///
/// Initializes a new instance of the class.
///
public TwoDimensionalArraySerializer()
: this(BsonSerializer.SerializerRegistry)
{
}
///
/// Initializes a new instance of the class.
///
/// The item serializer.
public TwoDimensionalArraySerializer(IBsonSerializer itemSerializer)
{
if (itemSerializer == null)
{
throw new ArgumentNullException("itemSerializer");
}
_lazyItemSerializer = new Lazy>(() => itemSerializer);
}
///
/// Initializes a new instance of the class.
///
/// The serializer registry.
public TwoDimensionalArraySerializer(IBsonSerializerRegistry serializerRegistry)
{
if (serializerRegistry == null)
{
throw new ArgumentNullException("serializerRegistry");
}
_lazyItemSerializer = new Lazy>(() => serializerRegistry.GetSerializer());
}
// public properties
///
/// Gets the item serializer.
///
///
/// The item serializer.
///
public IBsonSerializer ItemSerializer
{
get { return _lazyItemSerializer.Value; }
}
// public methods
///
/// Deserializes a value.
///
/// The deserialization context.
/// The deserialization args.
/// A deserialized value.
protected override TItem[,] DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var bsonReader = context.Reader;
EnsureBsonTypeEquals(bsonReader, BsonType.Array);
bsonReader.ReadStartArray();
var outerList = new List>();
while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
{
bsonReader.ReadStartArray();
var innerList = new List();
while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
{
innerList.Add(_lazyItemSerializer.Value.Deserialize(context));
}
bsonReader.ReadEndArray();
outerList.Add(innerList);
}
bsonReader.ReadEndArray();
var length1 = outerList.Count;
var length2 = (length1 == 0) ? 0 : outerList[0].Count;
var array = new TItem[length1, length2];
for (int i = 0; i < length1; i++)
{
var innerList = outerList[i];
if (innerList.Count != length2)
{
var message = string.Format("Inner list {0} is of length {1} but should be of length {2}.", i, innerList.Count, length2);
throw new FormatException(message);
}
for (int j = 0; j < length2; j++)
{
array[i, j] = innerList[j];
}
}
return array;
}
///
/// Serializes a value.
///
/// The serialization context.
/// The serialization args.
/// The object.
protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, TItem[,] value)
{
var bsonWriter = context.Writer;
var length1 = value.GetLength(0);
var length2 = value.GetLength(1);
bsonWriter.WriteStartArray();
for (int i = 0; i < length1; i++)
{
bsonWriter.WriteStartArray();
for (int j = 0; j < length2; j++)
{
_lazyItemSerializer.Value.Serialize(context, value[i, j]);
}
bsonWriter.WriteEndArray();
}
bsonWriter.WriteEndArray();
}
///
/// Returns a serializer that has been reconfigured with the specified item serializer.
///
/// The item serializer.
/// The reconfigured serializer.
public TwoDimensionalArraySerializer WithItemSerializer(IBsonSerializer itemSerializer)
{
return new TwoDimensionalArraySerializer(itemSerializer);
}
// explicit interface implementations
IBsonSerializer IChildSerializerConfigurable.ChildSerializer
{
get { return ItemSerializer; }
}
IBsonSerializer IChildSerializerConfigurable.WithChildSerializer(IBsonSerializer childSerializer)
{
return WithItemSerializer((IBsonSerializer)childSerializer);
}
}
}