/// <summary>
    /// Seek past the value for the previously read key.
    /// </summary>
    public static void SkipKey(CitoStream stream, Key key)
    {
        switch (key.GetWireType())
        {
        case Wire.Fixed32:
            stream.Seek(4, CitoSeekOrigin.Current);
            return;

        case Wire.Fixed64:
            stream.Seek(8, CitoSeekOrigin.Current);
            return;

        case Wire.LengthDelimited:
            stream.Seek(ProtocolParser.ReadUInt32(stream), CitoSeekOrigin.Current);
            return;

        case Wire.Varint:
            ProtocolParser.ReadSkipVarInt(stream);
            return;

        default:
#if !CITO
            throw new NotImplementedException("Unknown wire type: " + key.GetWireType());
#else
            return;
#endif
        }
    }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static void WriteUInt64(CitoStream stream, int val)
    {
        byte[] buffer = new byte[10];
        int    count  = 0;

        while (true)
        {
#if !CITO
            buffer[count] = (byte)(val & 0x7F);
#else
            buffer[count] = (val & 0x7F).LowByte;
#endif
            val = ProtoPlatform.logical_right_shift(val, 7);
            if (val == 0)
            {
                break;
            }

            buffer[count] |= 0x80;

            count += 1;
        }

        stream.Write(buffer, 0, count + 1);
    }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static void WriteUInt32_(CitoStream stream, int val)
    {
        byte[] buffer = new byte[5];
        int    count  = 0;

        while (true)
        {
#if !CITO
            buffer[count] = (byte)(val & 0x7F);
#else
            buffer[count] = (val & 0x7F).LowByte;
#endif
            val = val >> 7;
            if (val == 0)
            {
                break;
            }

            buffer[count] |= 0x80;

            count += 1;
        }

        stream.Write(buffer, 0, count + 1);
    }
    /// <summary>
    /// Read the value for an unknown key as bytes.
    /// Used to preserve unknown keys during deserialization.
    /// Requires the message option preserveunknown=true.
    /// </summary>
    public static byte[] ReadValueBytes(CitoStream stream, Key key)
    {
        byte[] b;
        int    offset = 0;

        switch (key.GetWireType())
        {
        case Wire.Fixed32:
            b = new byte[4];
            while (offset < 4)
            {
                offset += stream.Read(b, offset, 4 - offset);
            }
            return(b);

        case Wire.Fixed64:
            b = new byte[8];
            while (offset < 8)
            {
                offset += stream.Read(b, offset, 8 - offset);
            }
            return(b);

        case Wire.LengthDelimited:
            //Read and include length in value buffer
            int length          = ProtocolParser.ReadUInt32(stream);
            CitoMemoryStream ms = new CitoMemoryStream();
            {
                //TODO: pass b directly to MemoryStream constructor or skip usage of it completely
                ProtocolParser.WriteUInt32(ms, length);
                b = new byte[length + ms.Length()];
                byte[] arr = ms.ToArray();
                for (int i = 0; i < ProtoPlatform.ArrayLength(arr); i++)
                {
                    b[i] = arr[i];
                }
                offset = ms.Length();
            }

            //Read data into buffer
            while (offset < ProtoPlatform.ArrayLength(b))
            {
                offset += stream.Read(b, offset, ProtoPlatform.ArrayLength(b) - offset);
            }
            return(b);

        case Wire.Varint:
            return(ProtocolParser.ReadVarIntBytes(stream));

        default:
#if !CITO
            throw new NotImplementedException("Unknown wire type: " + key.GetWireType());
#else
            return(null);
#endif
        }
    }
    public static Key ReadKey_(byte firstByte, CitoStream stream)
    {
        if (firstByte < 128)
        {
            return(Key.Create((firstByte >> 3), (firstByte & 0x07)));
        }
        int fieldID = (ReadUInt32(stream) << 4) | ((firstByte >> 3) & 0x0F);

        return(Key.Create(fieldID, (firstByte & 0x07)));
    }
    public static void WriteBool(CitoStream stream, bool val)
    {
        byte ret = 0;

        if (val)
        {
            ret = 1;
        }
        stream.WriteByte(ret);
    }
    /// <summary>
    /// Skip the next varint length prefixed bytes.
    /// Alternative to ReadBytes when the data is not of interest.
    /// </summary>
    public static void SkipBytes(CitoStream stream)
    {
        int length = ReadUInt32(stream);

        if (stream.CanSeek())
        {
            stream.Seek(length, CitoSeekOrigin.Current);
        }
        else
        {
            ReadBytes(stream);
        }
    }
    //}
    //}

    //using System;
    //using System.IO;

    //namespace SilentOrbit.ProtocolBuffers
    //{
    //public static partial class ProtocolParser
    //{
    /// <summary>
    /// Reads past a varint for an unknown field.
    /// </summary>
    public static void ReadSkipVarInt(CitoStream stream)
    {
        while (true)
        {
            int b = stream.ReadByte();
            if (b < 0)
#if !CITO
            { throw new IOException("Stream ended too early"); }
#else
            { return; }
#endif

            if ((b & 0x80) == 0)
            {
                return; //end of varint
            }
        }
    }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static int ReadUInt64(CitoStream stream)
    {
        int b;
        int val = 0;

        for (int n = 0; n < 10; n++)
        {
            b = stream.ReadByte();
            if (b < 0)
#if !CITO
            { throw new IOException("Stream ended too early"); }
#else
            { return(0); }
#endif

            //Check that it fits in 64 bits
            if ((n == 9) && (b & 0xFE) != 0)
#if !CITO
            { throw new InvalidDataException("Got larger VarInt than 64 bit unsigned"); }
#else
            { return(0); }
#endif
            //End of check

            if ((b & 0x80) == 0)
            {
                //return val | (ulong)b << (7 * n);
                return(val | b << (7 * n));
            }

            //val |= (ulong)(b & 0x7F) << (7 * n);
            val |= (b & 0x7F) << (7 * n);
        }
#if !CITO
        throw new InvalidDataException("Got larger VarInt than 64 bit unsigned");
#else
        return(0);
#endif
    }
    /// <summary>
    /// Reads a length delimited byte array
    /// </summary>
    public static byte[] ReadBytes(CitoStream stream)
    {
        //VarInt length
        int length = ReadUInt32(stream);

        //Bytes
        byte[] buffer = new byte[length];
        int    read   = 0;

        while (read < length)
        {
            int r = stream.Read(buffer, read, length - read);
            if (r == 0)
#if !CITO
            { throw new InvalidDataException("Expected " + (length - read) + " got " + read); }
#else
            { return(null); }
#endif
            read += r;
        }
        return(buffer);
    }
    public static byte[] ReadVarIntBytes(CitoStream stream)
    {
        byte[] buffer = new byte[10];
        int    offset = 0;

        while (true)
        {
            int b = stream.ReadByte();
            if (b < 0)
#if !CITO
            { throw new IOException("Stream ended too early"); }
#else
            { return(null); }
#endif
#if !CITO
            buffer[offset] = (byte)b;
#else
            buffer[offset] = b.LowByte;
#endif
            offset += 1;
            if ((b & 0x80) == 0)
            {
                break; //end of varint
            }
            if (offset >= ProtoPlatform.ArrayLength(buffer))
#if !CITO
            { throw new InvalidDataException("VarInt too long, more than 10 bytes"); }
#else
            { return(null); }
#endif
        }
        byte[] ret = new byte[offset];
        for (int i = 0; i < offset; i++)
        {
            ret[i] = buffer[i];
        }
        return(ret);
    }
    //#endregion
    //#region Varint: bool
    public static bool ReadBool(CitoStream stream)
    {
        int b = stream.ReadByte();

        if (b < 0)
#if !CITO
        { throw new IOException("Stream ended too early"); }
#else
        { return(false); }
#endif
        if (b == 1)
        {
            return(true);
        }
        if (b == 0)
        {
            return(false);
        }
#if !CITO
        throw new InvalidDataException("Invalid boolean value");
#else
        return(false);
#endif
    }
 //}
 //}
 //
 //  This file contain references on how to write and read
 //  fixed integers and float/double.
 //
 //using System;
 //using System.IO;
 //namespace SilentOrbit.ProtocolBuffers
 //{
 //public static partial class ProtocolParser
 //{
 //#region Fixed Int, Only for reference
 //#endregion
 //}
 //}
 //
 //  Reader/Writer for field key
 //
 //using System;
 //using System.IO;
 //namespace SilentOrbit.ProtocolBuffers
 //{
 //public static partial class ProtocolParser
 //{
 public static Key ReadKey(CitoStream stream)
 {
     int n = ReadUInt32(stream);
     return Key.Create(n >> 3, (n & 0x07));
 }
 public static void WriteBool(CitoStream stream, bool val)
 {
     byte ret = 0;
     if (val)
     {
         ret = 1;
     }
     stream.WriteByte(ret);
 }
 //#endregion
 //#region VarInt: int64, UInt64, SInt64
 //[Obsolete("Use (long)ReadUInt64(stream); instead")]
 /// <summary>
 /// Since the int64 format is inefficient for negative numbers we have avoided to implement it.
 /// The same functionality can be achieved using: (long)ReadUInt64(stream);
 /// </summary>
 public static int ReadInt64(CitoStream stream)
 {
     return(ReadUInt64(stream));
 }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static int ReadZInt32(CitoStream stream)
 {
     int val = ReadUInt32(stream);
     return (val >> 1) ^ ((val << 31) >> 31);
 }
 /// <summary>
 /// Skip the next varint length prefixed bytes.
 /// Alternative to ReadBytes when the data is not of interest.
 /// </summary>
 public static void SkipBytes(CitoStream stream)
 {
     int length = ReadUInt32(stream);
     if (stream.CanSeek())
         stream.Seek(length, CitoSeekOrigin.Current);
     else
         ReadBytes(stream);
 }
 public static string ReadString(CitoStream stream)
 {
     byte[] bytes = ReadBytes(stream);
     return ProtoPlatform.BytesToString(bytes, 0);
 }
    /// <summary>
    /// Read the value for an unknown key as bytes.
    /// Used to preserve unknown keys during deserialization.
    /// Requires the message option preserveunknown=true.
    /// </summary>
    public static byte[] ReadValueBytes(CitoStream stream, Key key)
    {
        byte[] b;
        int offset = 0;

        switch (key.GetWireType())
        {
            case Wire.Fixed32:
                b = new byte[4];
                while (offset < 4)
                    offset += stream.Read(b, offset, 4 - offset);
                return b;
            case Wire.Fixed64:
                b = new byte[8];
                while (offset < 8)
                    offset += stream.Read(b, offset, 8 - offset);
                return b;
            case Wire.LengthDelimited:
                //Read and include length in value buffer
                int length = ProtocolParser.ReadUInt32(stream);
                CitoMemoryStream ms = new CitoMemoryStream();
                {
                    //TODO: pass b directly to MemoryStream constructor or skip usage of it completely
                    ProtocolParser.WriteUInt32(ms, length);
                    b = new byte[length + ms.Length()];
                    byte[] arr = ms.ToArray();
                    for (int i = 0; i < ProtoPlatform.ArrayLength(arr); i++)
                    {
                        b[i] = arr[i];
                    }
                    offset = ms.Length();
                }

                //Read data into buffer
                while (offset < ProtoPlatform.ArrayLength(b))
                    offset += stream.Read(b, offset, ProtoPlatform.ArrayLength(b) - offset);
                return b;
            case Wire.Varint:
                return ProtocolParser.ReadVarIntBytes(stream);
            default:
        #if !CITO
                throw new NotImplementedException("Unknown wire type: " + key.GetWireType());
        #else
                return null;
        #endif
        }
    }
 public static string ReadString(CitoStream stream)
 {
     byte[] bytes = ReadBytes(stream);
     return(ProtoPlatform.BytesToString(bytes, 0));
 }
 //[Obsolete("Use WriteUInt64(stream, (ulong)val); //yes 64, negative numbers are encoded that way")]
 /// <summary>
 /// Since the int32 format is inefficient for negative numbers we have avoided to imlplement.
 /// The same functionality can be achieved using: WriteUInt64(stream, (uint)val);
 /// Note that 64 must always be used for int32 to generate the ten byte wire format.
 /// </summary>
 public static void WriteInt32(CitoStream stream, int val)
 {
     //signed varint is always encoded as 64 but values!
     WriteUInt64(stream, val);
 }
    /// <summary>
    /// Zig-zag signed VarInt format
    /// </summary>
    public static int ReadZInt32(CitoStream stream)
    {
        int val = ReadUInt32(stream);

        return((val >> 1) ^ ((val << 31) >> 31));
    }
 //[Obsolete("Use WriteUInt64(stream, (ulong)val); //yes 64, negative numbers are encoded that way")]
 /// <summary>
 /// Since the int32 format is inefficient for negative numbers we have avoided to imlplement.
 /// The same functionality can be achieved using: WriteUInt64(stream, (uint)val);
 /// Note that 64 must always be used for int32 to generate the ten byte wire format.
 /// </summary>
 public static void WriteInt32(CitoStream stream, int val)
 {
     //signed varint is always encoded as 64 but values!
     WriteUInt64(stream, val);
 }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static void WriteZInt64(CitoStream stream, int val)
 {
     WriteUInt64(stream, ((val << 1) ^ (val >> 63)));
 }
    /// <summary>
    /// Zig-zag signed VarInt format
    /// </summary>
    public static int ReadZInt64(CitoStream stream)
    {
        int val = ReadUInt64(stream);

        return((val >> 1) ^ ((val << 63) >> 63));
    }
 //[Obsolete("Use WriteUInt64 (stream, (ulong)val); instead")]
 /// <summary>
 /// Since the int64 format is inefficient for negative numbers we have avoided to implement.
 /// The same functionality can be achieved using: WriteUInt64 (stream, (ulong)val);
 /// </summary>
 public static void WriteInt64(CitoStream stream, int val)
 {
     WriteUInt64(stream, val);
 }
 public static Key ReadKey_(byte firstByte, CitoStream stream)
 {
     if (firstByte < 128)
         return Key.Create((firstByte >> 3), (firstByte & 0x07));
     int fieldID = (ReadUInt32(stream) << 4) | ((firstByte >> 3) & 0x0F);
     return Key.Create(fieldID, (firstByte & 0x07));
 }
 public static void WriteKey(CitoStream stream, Key key)
 {
     int n = (key.GetField() << 3) | (key.GetWireType());
     WriteUInt32_(stream, n);
 }
    //}
    //}
    //using System;
    //using System.IO;
    //namespace SilentOrbit.ProtocolBuffers
    //{
    //public static partial class ProtocolParser
    //{
    /// <summary>
    /// Reads past a varint for an unknown field.
    /// </summary>
    public static void ReadSkipVarInt(CitoStream stream)
    {
        while (true)
        {
            int b = stream.ReadByte();
            if (b < 0)
        #if !CITO
                throw new IOException("Stream ended too early");
        #else
                return;
        #endif

            if ((b & 0x80) == 0)
                return; //end of varint
        }
    }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static void WriteUInt32_(CitoStream stream, int val)
    {
        byte[] buffer = new byte[5];
        int count = 0;

        while (true)
        {
        #if !CITO
            buffer[count] = (byte)(val & 0x7F);
        #else
            buffer[count] = (val & 0x7F).LowByte;
        #endif
            val = val >> 7;
            if (val == 0)
                break;

            buffer[count] |= 0x80;

            count += 1;
        }

        stream.Write(buffer, 0, count + 1);
    }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static int ReadUInt64(CitoStream stream)
    {
        int b;
        int val = 0;

        for (int n = 0; n < 10; n++)
        {
            b = stream.ReadByte();
            if (b < 0)
        #if !CITO
                throw new IOException("Stream ended too early");
        #else
                return 0;
        #endif

            //Check that it fits in 64 bits
            if ((n == 9) && (b & 0xFE) != 0)
        #if !CITO
                throw new InvalidDataException("Got larger VarInt than 64 bit unsigned");
        #else
                return 0;
        #endif
            //End of check

            if ((b & 0x80) == 0)
                //return val | (ulong)b << (7 * n);
                return val | b << (7 * n);

            //val |= (ulong)(b & 0x7F) << (7 * n);
            val |= (b & 0x7F) << (7 * n);
        }
        #if !CITO
        throw new InvalidDataException("Got larger VarInt than 64 bit unsigned");
        #else
        return 0;
        #endif
    }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static void WriteZInt32(CitoStream stream, int val)
 {
     WriteUInt32_(stream, ((val << 1) ^ (val >> 31)));
 }
 public static byte[] ReadVarIntBytes(CitoStream stream)
 {
     byte[] buffer = new byte[10];
     int offset = 0;
     while (true)
     {
         int b = stream.ReadByte();
         if (b < 0)
     #if !CITO
             throw new IOException("Stream ended too early");
     #else
             return null;
     #endif
     #if !CITO
         buffer[offset] = (byte)b;
     #else
         buffer[offset] = b.LowByte;
     #endif
         offset += 1;
         if ((b & 0x80) == 0)
             break; //end of varint
         if (offset >= ProtoPlatform.ArrayLength(buffer))
     #if !CITO
             throw new InvalidDataException("VarInt too long, more than 10 bytes");
     #else
             return null;
     #endif
     }
     byte[] ret = new byte[offset];
     for (int i = 0; i < offset; i++)
     {
         ret[i] = buffer[i];
     }
     return ret;
 }
    public static void WriteKey(CitoStream stream, Key key)
    {
        int n = (key.GetField() << 3) | (key.GetWireType());

        WriteUInt32_(stream, n);
    }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static int ReadZInt64(CitoStream stream)
 {
     int val = ReadUInt64(stream);
     return (val >> 1) ^ ((val << 63) >> 63);
 }
    /// <summary>
    /// Reads a length delimited byte array
    /// </summary>
    public static byte[] ReadBytes(CitoStream stream)
    {
        //VarInt length
        int length = ReadUInt32(stream);

        //Bytes
        byte[] buffer = new byte[length];
        int read = 0;
        while (read < length)
        {
            int r = stream.Read(buffer, read, length - read);
            if (r == 0)
        #if !CITO
                throw new InvalidDataException("Expected " + (length - read) + " got " + read);
        #else
            return null;
        #endif
            read += r;
        }
        return buffer;
    }
 /// <summary>
 /// Seek past the value for the previously read key.
 /// </summary>
 public static void SkipKey(CitoStream stream, Key key)
 {
     switch (key.GetWireType())
     {
         case Wire.Fixed32:
             stream.Seek(4, CitoSeekOrigin.Current);
             return;
         case Wire.Fixed64:
             stream.Seek(8, CitoSeekOrigin.Current);
             return;
         case Wire.LengthDelimited:
             stream.Seek(ProtocolParser.ReadUInt32(stream), CitoSeekOrigin.Current);
             return;
         case Wire.Varint:
             ProtocolParser.ReadSkipVarInt(stream);
             return;
         default:
     #if !CITO
             throw new NotImplementedException("Unknown wire type: " + key.GetWireType());
     #else
             return;
     #endif
     }
 }
 //#endregion
 //#region VarInt: int64, UInt64, SInt64
 //[Obsolete("Use (long)ReadUInt64(stream); instead")]
 /// <summary>
 /// Since the int64 format is inefficient for negative numbers we have avoided to implement it.
 /// The same functionality can be achieved using: (long)ReadUInt64(stream);
 /// </summary>
 public static int ReadInt64(CitoStream stream)
 {
     return ReadUInt64(stream);
 }
 /// <summary>
 /// Writes length delimited byte array
 /// </summary>
 public static void WriteBytes(CitoStream stream, byte[] val)
 {
     WriteUInt32_(stream, ProtoPlatform.ArrayLength(val));
     stream.Write(val, 0, ProtoPlatform.ArrayLength(val));
 }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static void WriteZInt32(CitoStream stream, int val)
 {
     WriteUInt32_(stream, ((val << 1) ^ (val >> 31)));
 }
 //[Obsolete("Use WriteUInt64 (stream, (ulong)val); instead")]
 /// <summary>
 /// Since the int64 format is inefficient for negative numbers we have avoided to implement.
 /// The same functionality can be achieved using: WriteUInt64 (stream, (ulong)val);
 /// </summary>
 public static void WriteInt64(CitoStream stream, int val)
 {
     WriteUInt64(stream, val);
 }
 public static void WriteString(CitoStream stream, string val)
 {
     WriteBytes(stream, ProtoPlatform.StringToBytes(val));
 }
 public static void WriteString(CitoStream stream, string val)
 {
     WriteBytes(stream, ProtoPlatform.StringToBytes(val));
 }
 /// <summary>
 /// Writes length delimited byte array
 /// </summary>
 public static void WriteBytes(CitoStream stream, byte[] val)
 {
     WriteUInt32_(stream, ProtoPlatform.ArrayLength(val));
     stream.Write(val, 0, ProtoPlatform.ArrayLength(val));
 }
    /// <summary>
    /// Unsigned VarInt format
    /// </summary>
    public static void WriteUInt64(CitoStream stream, int val)
    {
        byte[] buffer = new byte[10];
        int count = 0;

        while (true)
        {
        #if !CITO
            buffer[count] = (byte)(val & 0x7F);
        #else
            buffer[count] = (val & 0x7F).LowByte;
        #endif
            val = ProtoPlatform.logical_right_shift(val, 7);
            if (val == 0)
                break;

            buffer[count] |= 0x80;

            count += 1;
        }

        stream.Write(buffer, 0, count + 1);
    }
 //#endregion
 //#region Varint: bool
 public static bool ReadBool(CitoStream stream)
 {
     int b = stream.ReadByte();
     if (b < 0)
     #if !CITO
         throw new IOException("Stream ended too early");
     #else
         return false;
     #endif
     if (b == 1)
         return true;
     if (b == 0)
         return false;
     #if !CITO
     throw new InvalidDataException("Invalid boolean value");
     #else
     return false;
     #endif
 }
 /// <summary>
 /// Zig-zag signed VarInt format
 /// </summary>
 public static void WriteZInt64(CitoStream stream, int val)
 {
     WriteUInt64(stream, ((val << 1) ^ (val >> 63)));
 }
    //}
    //}

    //
    //  This file contain references on how to write and read
    //  fixed integers and float/double.
    //
    //using System;
    //using System.IO;

    //namespace SilentOrbit.ProtocolBuffers
    //{
    //public static partial class ProtocolParser
    //{
    //#region Fixed Int, Only for reference

    //#endregion
    //}
    //}

    //
    //  Reader/Writer for field key
    //
    //using System;
    //using System.IO;

    //namespace SilentOrbit.ProtocolBuffers
    //{

    //public static partial class ProtocolParser
    //{

    public static Key ReadKey(CitoStream stream)
    {
        int n = ReadUInt32(stream);

        return(Key.Create(n >> 3, (n & 0x07)));
    }