public void Serialize(EndianAwareBinaryWriter writer, object value, SerializedType serializedType, int? length = null) { if (value == null) { /* In the special case of sized strings, don't allow nulls */ if (serializedType == SerializedType.SizedString) value = string.Empty; else return; } int? constLength = null; long? maxLength = null; var typeParent = TypeNode.Parent as TypeNode; if (length != null) constLength = length.Value; else if (TypeNode.FieldLengthBinding != null && TypeNode.FieldLengthBinding.IsConst) { constLength = Convert.ToInt32(TypeNode.FieldLengthBinding.ConstValue); } else if (typeParent != null && typeParent.ItemLengthBinding != null && typeParent.ItemLengthBinding.IsConst) { constLength = Convert.ToInt32(typeParent.ItemLengthBinding.ConstValue); } else if (TypeNode.FieldCountBinding != null && TypeNode.FieldCountBinding.IsConst) { constLength = Convert.ToInt32(TypeNode.FieldCountBinding.ConstValue); } else if (serializedType == SerializedType.ByteArray || serializedType == SerializedType.SizedString || serializedType == SerializedType.NullTerminatedString) { // try to get bounded length from limiter var baseStream = (StreamLimiter) writer.BaseStream; maxLength = baseStream.AvailableForWriting; } switch (serializedType) { case SerializedType.Int1: writer.Write(Convert.ToSByte(value)); break; case SerializedType.UInt1: writer.Write(Convert.ToByte(value)); break; case SerializedType.Int2: writer.Write(Convert.ToInt16(value)); break; case SerializedType.UInt2: writer.Write(Convert.ToUInt16(value)); break; case SerializedType.Int4: writer.Write(Convert.ToInt32(value)); break; case SerializedType.UInt4: writer.Write(Convert.ToUInt32(value)); break; case SerializedType.Int8: writer.Write(Convert.ToInt64(value)); break; case SerializedType.UInt8: writer.Write(Convert.ToUInt64(value)); break; case SerializedType.Float4: writer.Write(Convert.ToSingle(value)); break; case SerializedType.Float8: writer.Write(Convert.ToDouble(value)); break; case SerializedType.ByteArray: { var data = (byte[]) value; writer.Write(data, 0, data.Length); break; } case SerializedType.NullTerminatedString: { byte[] data = Encoding.GetBytes(value.ToString()); if (constLength != null) Array.Resize(ref data, constLength.Value - 1); if(maxLength != null && data.Length > maxLength) Array.Resize(ref data, (int)maxLength.Value - 1); writer.Write(data); writer.Write((byte) 0); break; } case SerializedType.SizedString: { byte[] data = Encoding.GetBytes(value.ToString()); if (constLength != null) Array.Resize(ref data, constLength.Value); if (maxLength != null && data.Length > maxLength) Array.Resize(ref data, (int)maxLength.Value); writer.Write(data); break; } case SerializedType.LengthPrefixedString: { if(constLength != null) throw new NotSupportedException("Length-prefixed strings cannot have a const length."); writer.Write(value.ToString()); break; } default: throw new NotSupportedException(); } }
public void Serialize(Stream stream, object value, SerializedType serializedType, int? length = null) { var writer = new EndianAwareBinaryWriter(stream, Endianness); Serialize(writer, value, serializedType, length); }