/* Copyright (c) Microsoft Corporation All rights reserved. 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 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using System.Reflection; using System.Linq; using System.Data.SqlTypes; using System.Diagnostics; using Microsoft.Research.DryadLinq.Internal; using Microsoft.Research.DryadLinq; namespace Microsoft.Research.DryadLinq { /// /// The interface for providing user-defined serialization for a .NET type. /// If a class T implements DryadLinqSerializer{T}, DryadLinq will use the /// read and write methods of the class to do serialization. /// /// The .NET type to be serialized. public interface IDryadLinqSerializer { /// /// Reads a record of type T from the specified reader. /// /// The reader to read from. /// A record of type T T Read(DryadLinqBinaryReader reader); /// /// Writes a record of type T to the specified writer. /// /// The writer to write to. /// The record to write. void Write(DryadLinqBinaryWriter writer, T x); } } #pragma warning disable 1591 namespace Microsoft.Research.DryadLinq.Internal { public abstract class DryadLinqSerializer : IDryadLinqSerializer { public DryadLinqSerializer() { } public abstract T Read(DryadLinqBinaryReader reader); public abstract void Write(DryadLinqBinaryWriter writer, T x); } internal struct DryadLinqSequence : IEnumerable { private T[] elements; internal DryadLinqSequence(T[] elems) { this.elements = elems; } internal int Count() { return this.elements.Length; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } internal IEnumerator GetEnumerator() { foreach (T x in this.elements) { yield return x; } } } // The only use is to handle Nullable. public static class StructDryadLinqSerialization where T : struct where S : DryadLinqSerializer, new() { private static S serializer = new S(); public static void Read(DryadLinqBinaryReader reader, out Nullable val) { bool hasValue = reader.ReadBool(); if (hasValue) { val = serializer.Read(reader); } else { val = null; } } public static void Write(DryadLinqBinaryWriter writer, Nullable val) { writer.Write(val.HasValue); if (val.HasValue) { serializer.Write(writer, val.Value); } } } public static class StructDryadLinqSerialization where T1 : struct where T2 : struct where S1 : DryadLinqSerializer, new() where S2 : DryadLinqSerializer, new() { private static S1 serializer1 = new S1(); private static S2 serializer2 = new S2(); } // A workaround to deal with some limitation of C# generics public static class DryadLinqSerialization where S : DryadLinqSerializer, new() { private static S serializer = new S(); public static void Read(DryadLinqBinaryReader reader, out List list) { int cnt = reader.ReadInt32(); list = new List(cnt); for (int i = 0; i < cnt; i++) { list.Add(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, List list) { writer.Write(list.Count); foreach (T elem in list) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out LinkedList list) { int cnt = reader.ReadInt32(); list = new LinkedList(); for (int i = 0; i < cnt; i++) { list.AddLast(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, LinkedList list) { writer.Write(list.Count); foreach (T elem in list) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out Queue queue) { int cnt = reader.ReadInt32(); queue = new Queue(cnt); for (int i = 0; i < cnt; i++) { queue.Enqueue(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, Queue queue) { writer.Write(queue.Count); foreach (T elem in queue) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out Stack stack) { int cnt = reader.ReadInt32(); stack = new Stack(cnt); for (int i = 0; i < cnt; i++) { stack.Push(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, Stack stack) { writer.Write(stack.Count); foreach (T elem in stack) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out HashSet set) { int cnt = reader.ReadInt32(); set = new HashSet(); for (int i = 0; i < cnt; i++) { set.Add(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, HashSet set) { writer.Write(set.Count); foreach (T elem in set) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out Collection set) { int cnt = reader.ReadInt32(); set = new Collection(); for (int i = 0; i < cnt; i++) { set.Add(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, Collection set) { writer.Write(set.Count); foreach (T elem in set) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out ReadOnlyCollection set) { int cnt = reader.ReadInt32(); List lst = new List(cnt); for (int i = 0; i < cnt; i++) { lst.Add(serializer.Read(reader)); } set = new ReadOnlyCollection(lst); } public static void Write(DryadLinqBinaryWriter writer, ReadOnlyCollection set) { writer.Write(set.Count); foreach (T elem in set) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out IEnumerable seq) { int cnt = reader.ReadInt32(); T[] elems = new T[cnt]; for (int i = 0; i < cnt; i++) { elems[i] = serializer.Read(reader); } seq = new DryadLinqSequence(elems); } public static void Write(DryadLinqBinaryWriter writer, IEnumerable seq) { writer.Write(seq.Count()); foreach (T elem in seq) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out IList seq) { int cnt = reader.ReadInt32(); seq = new List(cnt); for (int i = 0; i < cnt; i++) { seq.Add(serializer.Read(reader)); } } public static void Write(DryadLinqBinaryWriter writer, IList seq) { writer.Write(seq.Count); foreach (T elem in seq) { serializer.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out ForkValue val) { val = new ForkValue(); if (reader.ReadBool()) { val.Value = serializer.Read(reader); } } public static void Write(DryadLinqBinaryWriter writer, ForkValue val) { writer.Write(val.HasValue); if (val.HasValue) { serializer.Write(writer, val.Value); } } public static void Read(DryadLinqBinaryReader reader, out AggregateValue aggVal) { long cnt = reader.ReadInt64(); T val = default(T); if (cnt > 0) { val = serializer.Read(reader); } aggVal = new AggregateValue(val, cnt); } public static void Write(DryadLinqBinaryWriter writer, AggregateValue aggVal) { writer.Write(aggVal.Count); if (aggVal.Count > 0) { serializer.Write(writer, aggVal.Value); } } public static void Read(DryadLinqBinaryReader reader, out IndexedValue indexedVal) { int index = reader.ReadInt32(); T val = serializer.Read(reader); indexedVal = new IndexedValue(index, val); } public static void Write(DryadLinqBinaryWriter writer, IndexedValue indexedVal) { writer.Write(indexedVal.Index); serializer.Write(writer, indexedVal.Value); } } public static class DryadLinqSerialization where S1 : DryadLinqSerializer, new() where S2 : DryadLinqSerializer, new() { private static S1 serializer1 = new S1(); private static S2 serializer2 = new S2(); public static void Read(DryadLinqBinaryReader reader, out Dictionary dict) { int cnt = reader.ReadInt32(); dict = new Dictionary(cnt); for (int i = 0; i < cnt; i++) { T1 key = serializer1.Read(reader); T2 val = serializer2.Read(reader); dict.Add(key, val); } } public static void Write(DryadLinqBinaryWriter writer, Dictionary dict) { writer.Write(dict.Count); foreach (KeyValuePair elem in dict) { serializer1.Write(writer, elem.Key); serializer2.Write(writer, elem.Value); } } public static void Read(DryadLinqBinaryReader reader, out SortedDictionary dict) { int cnt = reader.ReadInt32(); dict = new SortedDictionary(); for (int i = 0; i < cnt; i++) { T1 key = serializer1.Read(reader); T2 val = serializer2.Read(reader); dict.Add(key, val); } } public static void Write(DryadLinqBinaryWriter writer, SortedDictionary dict) { writer.Write(dict.Count); foreach (KeyValuePair elem in dict) { serializer1.Write(writer, elem.Key); serializer2.Write(writer, elem.Value); } } public static void Read(DryadLinqBinaryReader reader, out SortedList list) { int cnt = reader.ReadInt32(); list = new SortedList(cnt); for (int i = 0; i < cnt; i++) { T1 key = serializer1.Read(reader); T2 value = serializer2.Read(reader); list.Add(key, value); } } public static void Write(DryadLinqBinaryWriter writer, SortedList list) { writer.Write(list.Count); foreach (KeyValuePair elem in list) { serializer1.Write(writer, elem.Key); serializer2.Write(writer, elem.Value); } } public static void Read(DryadLinqBinaryReader reader, out IGrouping group) { T1 key = serializer1.Read(reader); int len = reader.ReadInt32(); Grouping realGroup = new Grouping(key, len); for (int i = 0; i < len; i++) { realGroup.AddItem(serializer2.Read(reader)); } group = realGroup; } public static void Write(DryadLinqBinaryWriter writer, IGrouping group) { serializer1.Write(writer, group.Key); writer.Write(group.Count()); foreach (T2 elem in group) { serializer2.Write(writer, elem); } } public static void Read(DryadLinqBinaryReader reader, out KeyValuePair kv) { T1 key = serializer1.Read(reader); T2 val = serializer2.Read(reader); kv = new KeyValuePair(key, val); } public static void Write(DryadLinqBinaryWriter writer, KeyValuePair kv) { serializer1.Write(writer, kv.Key); serializer2.Write(writer, kv.Value); } public static void Read(DryadLinqBinaryReader reader, out Pair pair) { T1 x = serializer1.Read(reader); T2 y = serializer2.Read(reader); pair = new Pair(x, y); } public static void Write(DryadLinqBinaryWriter writer, Pair pair) { serializer1.Write(writer, pair.Key); serializer2.Write(writer, pair.Value); } public static void Read(DryadLinqBinaryReader reader, out ForkTuple val) { val = new ForkTuple(); if (reader.ReadBool()) { val.First = serializer1.Read(reader); } if (reader.ReadBool()) { val.Second = serializer2.Read(reader); } } public static void Write(DryadLinqBinaryWriter writer, ForkTuple val) { writer.Write(val.HasFirst); if (val.HasFirst) { serializer1.Write(writer, val.First); } writer.Write(val.HasSecond); if (val.HasSecond) { serializer2.Write(writer, val.Second); } } public static void Read(DryadLinqBinaryReader reader, out DryadLinqGrouping group) { T1 key = serializer1.Read(reader); int cnt = reader.ReadInt32(); T2[] elems = new T2[cnt]; for (int i = 0; i < cnt; i++) { elems[i] = serializer2.Read(reader); } group = new DryadLinqGrouping(key, elems); } public static void Write(DryadLinqBinaryWriter writer, DryadLinqGrouping group) { serializer1.Write(writer, group.Key); writer.Write(group.Count()); foreach (T2 elem in group) { serializer2.Write(writer, elem); } } } public static class DryadLinqSerialization where S1 : DryadLinqSerializer, new() where S2 : DryadLinqSerializer, new() where S3 : DryadLinqSerializer, new() { } public sealed class ByteDryadLinqSerializer : DryadLinqSerializer { public override byte Read(DryadLinqBinaryReader reader) { return reader.ReadUByte(); } public override void Write(DryadLinqBinaryWriter writer, byte x) { writer.Write(x); } } public sealed class SByteDryadLinqSerializer : DryadLinqSerializer { public override sbyte Read(DryadLinqBinaryReader reader) { return reader.ReadSByte(); } public override void Write(DryadLinqBinaryWriter writer, sbyte x) { writer.Write(x); } } public sealed class BoolDryadLinqSerializer : DryadLinqSerializer { public override bool Read(DryadLinqBinaryReader reader) { return reader.ReadBool(); } public override void Write(DryadLinqBinaryWriter writer, bool x) { writer.Write(x); } } public sealed class CharDryadLinqSerializer : DryadLinqSerializer { public override char Read(DryadLinqBinaryReader reader) { return reader.ReadChar(); } public override void Write(DryadLinqBinaryWriter writer, char x) { writer.Write(x); } } public sealed class Int16DryadLinqSerializer : DryadLinqSerializer { public override Int16 Read(DryadLinqBinaryReader reader) { return reader.ReadInt16(); } public override void Write(DryadLinqBinaryWriter writer, Int16 x) { writer.Write(x); } } public sealed class UInt16DryadLinqSerializer : DryadLinqSerializer { public override UInt16 Read(DryadLinqBinaryReader reader) { return reader.ReadUInt16(); } public override void Write(DryadLinqBinaryWriter writer, UInt16 x) { writer.Write(x); } } public sealed class Int32DryadLinqSerializer : DryadLinqSerializer { public override Int32 Read(DryadLinqBinaryReader reader) { return reader.ReadInt32(); } public override void Write(DryadLinqBinaryWriter writer, Int32 x) { writer.Write(x); } } public sealed class UInt32DryadLinqSerializer : DryadLinqSerializer { public override UInt32 Read(DryadLinqBinaryReader reader) { return reader.ReadUInt32(); } public override void Write(DryadLinqBinaryWriter writer, UInt32 x) { writer.Write(x); } } public sealed class Int64DryadLinqSerializer : DryadLinqSerializer { public override Int64 Read(DryadLinqBinaryReader reader) { return reader.ReadInt64(); } public override void Write(DryadLinqBinaryWriter writer, Int64 x) { writer.Write(x); } } public sealed class UInt64DryadLinqSerializer : DryadLinqSerializer { public override UInt64 Read(DryadLinqBinaryReader reader) { return reader.ReadUInt64(); } public override void Write(DryadLinqBinaryWriter writer, UInt64 x) { writer.Write(x); } } public sealed class SingleDryadLinqSerializer : DryadLinqSerializer { public override float Read(DryadLinqBinaryReader reader) { return reader.ReadSingle(); } public override void Write(DryadLinqBinaryWriter writer, float x) { writer.Write(x); } } public sealed class DoubleDryadLinqSerializer : DryadLinqSerializer { public override double Read(DryadLinqBinaryReader reader) { return reader.ReadDouble(); } public override void Write(DryadLinqBinaryWriter writer, double x) { writer.Write(x); } } public sealed class DecimalDryadLinqSerializer : DryadLinqSerializer { public override decimal Read(DryadLinqBinaryReader reader) { return reader.ReadDecimal(); } public override void Write(DryadLinqBinaryWriter writer, decimal x) { writer.Write(x); } } public sealed class DateTimeDryadLinqSerializer : DryadLinqSerializer { public override DateTime Read(DryadLinqBinaryReader reader) { return reader.ReadDateTime(); } public override void Write(DryadLinqBinaryWriter writer, DateTime x) { writer.Write(x); } } public sealed class StringDryadLinqSerializer : DryadLinqSerializer { public override string Read(DryadLinqBinaryReader reader) { return reader.ReadString(); } public override void Write(DryadLinqBinaryWriter writer, string x) { writer.Write(x); } } public sealed class GuidDryadLinqSerializer : DryadLinqSerializer { public override Guid Read(DryadLinqBinaryReader reader) { return reader.ReadGuid(); } public override void Write(DryadLinqBinaryWriter writer, Guid x) { writer.Write(x); } } public sealed class SqlDateTimeDryadLinqSerializer : DryadLinqSerializer { public override SqlDateTime Read(DryadLinqBinaryReader reader) { return reader.ReadSqlDateTime(); } public override void Write(DryadLinqBinaryWriter writer, SqlDateTime x) { writer.Write(x); } } public sealed class LineRecordDryadLinqSerializer : DryadLinqSerializer { public override LineRecord Read(DryadLinqBinaryReader reader) { string line = reader.ReadString(); return new LineRecord(line); } public override void Write(DryadLinqBinaryWriter writer, LineRecord x) { writer.Write(x.Line); } } }