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);
 }