/// <summary> /// Tries deserialize a tuple from stream /// </summary> /// <typeparam name="T">tuple type</typeparam> /// <param name="tuple">tuple object</param> /// <param name="stream">the stream to read the tuple</param> /// <returns>true when success</returns> public static void Deserialize <T>(this Stream stream, T proto, ProtoSchema schema) { try { using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) { int bitLen = reader.ReadByte(); byte[] bitmasks = reader.ReadBytes(bitLen); foreach (IProtoColumn column in schema.Columns) { if (bitmasks.GetBitmask(column.ID)) { object value = column.Read(reader); proto.SetValue(column, value); } else { proto.SetValue(column, column.DefaultValue); } } } } catch (EndOfStreamException) { throw new ProtoException(ProtoErrorCode.DataCorrupted); } }
/// <summary> /// Serialize a tuple into stream. /// /// The following data are writen into the stream /// 1. bitmask bytes length /// 2. bitmarks bytes /// 3. serialized value for each column in columns masks. /// /// </summary> /// <typeparam name="T">tuple type</typeparam> /// <param name="tuple">tuple object</param> /// <param name="stream">the stread to write the tuple into</param> /// <param name="columnMasks">column masks for serialized columns</param> public static void Serialize <T>(this Stream stream, T proto, ProtoSchema schema) { using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) { int bitPos = (int)stream.Position; byte[] bitmarks = new byte[schema.ColumnMasks.Length]; writer.Write((byte)bitmarks.Length); writer.Write(bitmarks, 0, bitmarks.Length); for (int index = 0; index < schema.Columns.Length; index++) { IProtoColumn column = schema.Columns[index]; if (column.ID >= schema.ColumnMasks.Length * 8) { break; } if (!schema.ColumnMasks.GetBitmask(column.ID)) { bitmarks.SetBitmask(column.ID, false); continue; } object value = proto.GetValue(column); if (CommonUtils.Equals(value, column.DefaultValue)) { bitmarks.SetBitmask(column.ID, false); } else { bitmarks.SetBitmask(column.ID, true); column.Write(writer, value); } } int endPos = (int)stream.Position; stream.Position = bitPos; writer.Write((byte)bitmarks.Length); writer.Write(bitmarks, 0, bitmarks.Length); stream.Position = endPos; } }