Example #1
0
        void ProcessCall(uint callId, uint type, BufferView data)
        {
            object inflatedData;

            // Check the sequence id
            if (callId != ++LastReceivedId)
            {
                ProtocolError();
                return;
            }

            // Get call definition
            Registry.RegisteredCall call = Registry.GetServerCall(type);
            if (call == null)
            {
                ProtocolError();
                return;
            }

            // Read the incoming data
            try {
                inflatedData = InflateData.Inflate(data, call.ArgsFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Emit the "call" event
            if (OnCall != null)
            {
                OnCall(this, new CallEventArgs(call, inflatedData, this, callId));
            }
        }
Example #2
0
        /// <summary>
        /// Extract a single element from the view
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <param name="data">The data ArrayList to store the extracted data</param>
        /// <param name="format">The format of the data to be extracted</param>
        /// <returns>Return the view parameter</returns>
        static BufferView ReadElement(BufferView buffer, ArrayList data, Format.ElementsArray format)
        {
            for (int i = 0; i < format.Elements.Count; i++)
            {
                switch (format.Elements[i].ElementType)
                {
                case Format.Element.Type.ARRAY:
                    data.Add(ReadArray(buffer, (Format.ElementsArray)format.Elements[i]));
                    break;

                case Format.Element.Type.UINT:
                    data.Add(ReadUint(buffer));
                    break;

                case Format.Element.Type.INT:
                    data.Add(ReadInt(buffer));
                    break;

                case Format.Element.Type.FLOAT:
                    data.Add(ReadFloat(buffer));
                    break;

                case Format.Element.Type.TOKEN:
                    data.Add(ReadToken(buffer));
                    break;

                case Format.Element.Type.STRING:
                    data.Add(ReadString(buffer));
                    break;
                }
            }
            return(buffer);
        }
Example #3
0
        void Socket_OnData(object sender, EventSocket.DataEventArgs args)
        {
            // Store the data
            Cache.Concat(args.Data);

            // Try to read messages
            while (true)
            {
                int        length;
                BufferView backup = new BufferView(Cache);

                try {
                    // Extract the size of the message
                    length = (int)InflateData.ReadUint(Cache);
                } catch (Exception e) {
                    if (!(e is InflateData.NotEnoughData))
                    {
                        ProtocolError();
                    }
                    break;
                }

                if (Cache.Length < length)
                {
                    Cache = backup;
                    break;
                }

                ProcessMessage(Cache.ExtractSlice(length));
            }
        }
Example #4
0
        /// <summary>
        /// Extract an array
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <param name="format">A component of an inflated format object</param>
        /// <returns>Return the extracted data</returns>
        static ArrayList ReadArray(BufferView buffer, Format.ElementsArray format)
        {
            int length;

            // Get the number of elements
            length = (int)ReadUint(buffer);

            // Extract each element
            ArrayList array = new ArrayList();

            if (format.Elements.Count == 1)
            {
                for (int i = 0; i < length; i++)
                {
                    ReadElement(buffer, array, format);
                }
            }
            else
            {
                for (int i = 0; i < length; i++)
                {
                    ArrayList subArray = new ArrayList();
                    ReadElement(buffer, subArray, format);
                    array.Add(subArray);
                }
            }

            return(array);
        }
Example #5
0
        void ProcessReturn(uint callId, BufferView data)
        {
            PendingCall callInfo = FetchPendingCall(callId);

            if (callInfo == null)
            {
                // Received a timeouted (or invalid) answer
                ProtocolError();
                return;
            }

            // Read the incoming data
            object inflatedData;

            try {
                inflatedData = InflateData.Inflate(data, callInfo.Call.ReturnFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Clear the timeout
            if (callInfo.Interval != null)
            {
                callInfo.Interval.Stop();
            }

            // Call the callback
            if (callInfo.OnReturn != null)
            {
                callInfo.OnReturn(this, inflatedData);
            }
        }
Example #6
0
 /// <summary>
 /// Inflate the data with the given format stored in a buffer
 /// </summary>
 /// <param name="buffer">A view with the encoded data</param>
 /// <param name="format">An inflated format object</param>
 /// <returns>Return null, an ArrayList or a single value (ulong, long, float, Token or string)</returns>
 internal static object Inflate(BufferView buffer, Format format)
 {
     ArrayList data = new ArrayList();
     if (InflateData.ReadElement(buffer, data, format.Root).Length != 0)
         throw new ArgumentException("Unable to read data in the given format");
     return data.Count == 0 ? null : (data.Count == 1 ? data[0] : data);
 }
Example #7
0
        /// <summary>
        /// Inflate the data with the given format stored in a buffer
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <param name="format">An inflated format object</param>
        /// <returns>Return null, an ArrayList or a single value (ulong, long, float, Token or string)</returns>
        internal static object Inflate(BufferView buffer, Format format)
        {
            ArrayList data = new ArrayList();

            if (InflateData.ReadElement(buffer, data, format.Root).Length != 0)
            {
                throw new ArgumentException("Unable to read data in the given format");
            }
            return(data.Count == 0 ? null : (data.Count == 1 ? data[0] : data));
        }
Example #8
0
        /// <summary>
        /// Extract a Token
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        static Token ReadToken(BufferView buffer)
        {
            if (buffer.Length < 16)
            {
                throw new NotEnoughData("Unable to extract Token");
            }
            Token r = new Token(buffer.GetBytes(16));

            buffer.Slice(16);
            return(r);
        }
Example #9
0
        /// <summary>
        /// Extract an unsigned integer
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        internal static ulong ReadUint(BufferView buffer)
        {
            byte firstByte;
            int length, shifts;
            ulong u;

            // Get the first byte
            if (buffer.Length == 0)
                throw new NotEnoughData("Unable to extract unsigned integer");
            firstByte = buffer[0];

            // Get the total length and the first bits
            if (firstByte < Data.OFFSET_2_B) {
                // Fast path
                buffer.Slice(1);
                return (ulong)firstByte;
            } else if (firstByte < Data.OFFSET_3_B) {
                length = 1;
                u = (ulong)(firstByte & Data.MASK_6_B);
            } else if (firstByte < Data.OFFSET_4_B) {
                length = 2;
                u = (ulong)(firstByte & Data.MASK_5_B);
            } else if (firstByte < Data.OFFSET_5_B) {
                length = 3;
                u = (ulong)(firstByte & Data.MASK_4_B);
            } else if (firstByte < Data.OFFSET_6_B) {
                length = 4;
                u = (ulong)(firstByte & Data.MASK_3_B);
            } else if (firstByte < Data.OFFSET_7_B) {
                length = 5;
                u = (ulong)(firstByte & Data.MASK_2_B);
            } else if (firstByte < Data.OFFSET_8_B) {
                length = 6;
                u = (ulong)(firstByte & Data.MASK_1_B);
            } else if (firstByte == Data.OFFSET_8_B) {
                length = 7;
                u = 0;
            } else
                throw new InvalidOperationException("Unable to extract unsigned integer");

            // Get the remaining bytes
            if (buffer.Length <= length)
                throw new NotEnoughData("Unable to extract unsigned integer");
            shifts = 7 - length;
            for (int i = 1; i <= length; i++) {
                ulong temp = buffer[i];
                u += temp << shifts;
                shifts += 8;
            }

            buffer.Slice(length + 1);
            return u;
        }
Example #10
0
        /// <summary>
        /// Extract initial bytes from this view
        /// </summary>
        /// <param name="size">The number of bytes to extract</param>
        /// <returns>Return a new BufferView with the desired number of bytes</returns>
        public BufferView ExtractSlice(int size)
        {
            if (size < 0 || size > Length)
            {
                throw new ArgumentException("Invalid size");
            }
            BufferView r = new BufferView(Buffer, Offset, size);

            Offset += size;
            Length -= size;
            return(r);
        }
Example #11
0
 /// <summary>
 /// Extract a float
 /// </summary>
 /// <param name="buffer">A view with the encoded data</param>
 /// <returns>Return the extracted data</returns>
 static float ReadFloat(BufferView buffer)
 {
     if (buffer.Length < 4)
     {
         throw new NotEnoughData("Unable to extract float");
     }
     byte[] temp = buffer.GetBytes(4);
     if (!BitConverter.IsLittleEndian)
     {
         Array.Reverse(temp);
     }
     buffer.Slice(4);
     return(BitConverter.ToSingle(temp, 0));
 }
Example #12
0
        void ProcessException(uint callId, uint type, BufferView data)
        {
            PendingCall callInfo = FetchPendingCall(callId);

            if (callInfo == null)
            {
                // Received a timeouted (or invalid) answer
                ProtocolError();
                return;
            }
            if (!callInfo.Call.HasException(type))
            {
                // Received an invalid exception type
                ProtocolError();
                return;
            }

            // Get exception definition
            Registry.RegisteredException exception = Registry.GetException(type);
            if (exception == null)
            {
                ProtocolError();
                return;
            }

            // Read the incoming data
            object inflatedData;

            try {
                inflatedData = InflateData.Inflate(data, exception.DataFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Clear the timeout
            if (callInfo.Interval != null)
            {
                callInfo.Interval.Stop();
            }

            // Call the callback
            if (callInfo.OnException != null)
            {
                callInfo.OnException(this, (int)type, inflatedData);
            }
        }
Example #13
0
        /// <summary>
        /// Extract a string
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        static string ReadString(BufferView buffer)
        {
            int length;

            // Get the string length
            length = (int)ReadUint(buffer);

            if (buffer.Length < length)
            {
                throw new NotEnoughData("Unable to extract string");
            }

            string r = Encoding.UTF8.GetString(buffer.GetBytes(length));

            buffer.Slice(length);
            return(r);
        }
Example #14
0
        void ProcessMessage(BufferView message)
        {
            uint type, callId;

            // Extract the message type and sequence id
            try {
                type   = (uint)InflateData.ReadUint(message);
                callId = (uint)InflateData.ReadUint(message);
            } catch {
                ProtocolError();
                return;
            }

            if (type != 0)
            {
                // A call from the other side
                ProcessCall(callId, type, message);
            }
            else
            {
                try {
                    type = (uint)InflateData.ReadUint(message);
                } catch {
                    ProtocolError();
                    return;
                }
                if (type != 0)
                {
                    // An exception from the other side
                    ProcessException(callId, type, message);
                }
                else
                {
                    // A return from the other side
                    ProcessReturn(callId, message);
                }
            }
        }
Example #15
0
 /// <summary>
 /// Extract a Token
 /// </summary>
 /// <param name="buffer">A view with the encoded data</param>
 /// <returns>Return the extracted data</returns>
 static Token ReadToken(BufferView buffer)
 {
     if (buffer.Length < 16)
         throw new NotEnoughData("Unable to extract Token");
     Token r = new Token(buffer.GetBytes(16));
     buffer.Slice(16);
     return r;
 }
Example #16
0
 /// <summary>
 /// Extract initial bytes from this view
 /// </summary>
 /// <param name="size">The number of bytes to extract</param>
 /// <returns>Return a new BufferView with the desired number of bytes</returns>
 public BufferView ExtractSlice(int size)
 {
     if (size < 0 || size > Length)
         throw new ArgumentException("Invalid size");
     BufferView r = new BufferView(Buffer, Offset, size);
     Offset += size;
     Length -= size;
     return r;
 }
Example #17
0
        /// <summary>
        /// Extract a string
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        static string ReadString(BufferView buffer)
        {
            int length;

            // Get the string length
            length = (int)ReadUint(buffer);

            if (buffer.Length < length)
                throw new NotEnoughData("Unable to extract string");

            string r = Encoding.UTF8.GetString(buffer.GetBytes(length));
            buffer.Slice(length);
            return r;
        }
Example #18
0
 /// <summary>
 /// Extract a float
 /// </summary>
 /// <param name="buffer">A view with the encoded data</param>
 /// <returns>Return the extracted data</returns>
 static float ReadFloat(BufferView buffer)
 {
     if (buffer.Length < 4)
         throw new NotEnoughData("Unable to extract float");
     byte[] temp = buffer.GetBytes(4);
     if (!BitConverter.IsLittleEndian)
         Array.Reverse(temp);
     buffer.Slice(4);
     return BitConverter.ToSingle(temp, 0);
 }
Example #19
0
        /// <summary>
        /// Extract a signed integer
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        static long ReadInt(BufferView buffer)
        {
            byte firstByte;
            long i;
            int length, shifts;

            // Get the first byte
            if (buffer.Length == 0)
                throw new NotEnoughData("Unable to extract signed integer");
            firstByte = buffer[0];

            // Get the total length and the first bits
            if (firstByte < Data.OFFSET_2_B) {
                // Fast path
                buffer.Slice(1);
                return (long)firstByte + Data.MIN_INT_1_B;
            } else if (firstByte < Data.OFFSET_3_B) {
                length = 1;
                i = (long)(firstByte & Data.MASK_6_B) + Data.MIN_INT_2_B;
            } else if (firstByte < Data.OFFSET_4_B) {
                length = 2;
                i = (long)(firstByte & Data.MASK_5_B) + Data.MIN_INT_3_B;
            } else if (firstByte < Data.OFFSET_5_B) {
                length = 3;
                i = (long)(firstByte & Data.MASK_4_B) + Data.MIN_INT_4_B;
            } else if (firstByte < Data.OFFSET_6_B) {
                length = 4;
                i = (long)(firstByte & Data.MASK_3_B) + Data.MIN_INT_5_B;
            } else if (firstByte < Data.OFFSET_7_B) {
                length = 5;
                i = (long)(firstByte & Data.MASK_2_B) + Data.MIN_INT_6_B;
            } else if (firstByte < Data.OFFSET_8_B) {
                length = 6;
                i = (long)(firstByte & Data.MASK_1_B) + Data.MIN_INT_7_B;
            } else if (firstByte == Data.OFFSET_8_B) {
                length = 7;
                i = Data.MIN_INT_8_B;
            } else
                throw new InvalidOperationException("Unable to extract signed integer");

            // Get the remaining bytes
            if (buffer.Length <= length)
                throw new NotEnoughData("Unable to extract signed integer");
            shifts = 7 - length;
            for (int j = 1; j <= length; j++) {
                long temp = buffer[j];
                i += temp << shifts;
                shifts += 8;
            }

            buffer.Slice(length + 1);
            return i;
        }
Example #20
0
        void Socket_OnData(object sender, EventSocket.DataEventArgs args)
        {
            // Store the data
            Cache.Concat(args.Data);

            // Try to read messages
            while (true) {
                int length;
                BufferView backup = new BufferView(Cache);

                try {
                    // Extract the size of the message
                    length = (int)InflateData.ReadUint(Cache);
                } catch (Exception e) {
                    if (!(e is InflateData.NotEnoughData))
                        ProtocolError();
                    break;
                }

                if (Cache.Length < length) {
                    Cache = backup;
                    break;
                }

                ProcessMessage(Cache.ExtractSlice(length));
            }
        }
Example #21
0
 /// <summary>
 /// Extract a single element from the view
 /// </summary>
 /// <param name="buffer">A view with the encoded data</param>
 /// <param name="data">The data ArrayList to store the extracted data</param>
 /// <param name="format">The format of the data to be extracted</param>
 /// <returns>Return the view parameter</returns>
 static BufferView ReadElement(BufferView buffer, ArrayList data, Format.ElementsArray format)
 {
     for (int i = 0; i < format.Elements.Count; i++) {
         switch (format.Elements[i].ElementType) {
             case Format.Element.Type.ARRAY:
                 data.Add(ReadArray(buffer, (Format.ElementsArray)format.Elements[i]));
                 break;
             case Format.Element.Type.UINT:
                 data.Add(ReadUint(buffer));
                 break;
             case Format.Element.Type.INT:
                 data.Add(ReadInt(buffer));
                 break;
             case Format.Element.Type.FLOAT:
                 data.Add(ReadFloat(buffer));
                 break;
             case Format.Element.Type.TOKEN:
                 data.Add(ReadToken(buffer));
                 break;
             case Format.Element.Type.STRING:
                 data.Add(ReadString(buffer));
                 break;
         }
     }
     return buffer;
 }
Example #22
0
        void ProcessMessage(BufferView message)
        {
            uint type, callId;
            // Extract the message type and sequence id
            try {
                type = (uint)InflateData.ReadUint(message);
                callId = (uint)InflateData.ReadUint(message);
            } catch {
                ProtocolError();
                return;
            }

            if (type != 0)
                // A call from the other side
                ProcessCall(callId, type, message);
            else {
                try {
                    type = (uint)InflateData.ReadUint(message);
                } catch {
                    ProtocolError();
                    return;
                }
                if (type != 0)
                    // An exception from the other side
                    ProcessException(callId, type, message);
                else
                    // A return from the other side
                    ProcessReturn(callId, message);
            }
        }
Example #23
0
        void ProcessReturn(uint callId, BufferView data)
        {
            PendingCall callInfo = FetchPendingCall(callId);
            if (callInfo == null) {
                // Received a timeouted (or invalid) answer
                ProtocolError();
                return;
            }

            // Read the incoming data
            object inflatedData;
            try {
                inflatedData = InflateData.Inflate(data, callInfo.Call.ReturnFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Clear the timeout
            if (callInfo.Interval != null)
                callInfo.Interval.Stop();

            // Call the callback
            if (callInfo.OnReturn != null)
                callInfo.OnReturn(this, inflatedData);
        }
Example #24
0
        void ProcessException(uint callId, uint type, BufferView data)
        {
            PendingCall callInfo = FetchPendingCall(callId);
            if (callInfo == null) {
                // Received a timeouted (or invalid) answer
                ProtocolError();
                return;
            }
            if (!callInfo.Call.HasException(type)) {
                // Received an invalid exception type
                ProtocolError();
                return;
            }

            // Get exception definition
            Registry.RegisteredException exception = Registry.GetException(type);
            if (exception == null) {
                ProtocolError();
                return;
            }

            // Read the incoming data
            object inflatedData;
            try {
                inflatedData = InflateData.Inflate(data, exception.DataFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Clear the timeout
            if (callInfo.Interval != null)
                callInfo.Interval.Stop();

            // Call the callback
            if (callInfo.OnException != null)
                callInfo.OnException(this, (int)type, inflatedData);
        }
Example #25
0
        void ProcessCall(uint callId, uint type, BufferView data)
        {
            object inflatedData;

            // Check the sequence id
            if (callId != ++LastReceivedId) {
                ProtocolError();
                return;
            }

            // Get call definition
            Registry.RegisteredCall call = Registry.GetServerCall(type);
            if (call == null) {
                ProtocolError();
                return;
            }

            // Read the incoming data
            try {
                inflatedData = InflateData.Inflate(data, call.ArgsFormat);
            } catch {
                ProtocolError();
                return;
            }

            // Emit the "call" event
            if (OnCall != null)
                OnCall(this, new CallEventArgs(call, inflatedData, this, callId));
        }
Example #26
0
 /// <summary>
 /// Clone a given view
 /// </summary>
 /// <param name="buffer">The old object to clone</param>
 public BufferView(BufferView buffer)
     : this(buffer.Buffer, buffer.Offset, buffer.Length)
 {
 }
Example #27
0
 /// <summary>
 /// Clone a given view
 /// </summary>
 /// <param name="buffer">The old object to clone</param>
 public BufferView(BufferView buffer) : this(buffer.Buffer, buffer.Offset, buffer.Length)
 {
 }
Example #28
0
        /// <summary>
        /// Extract a signed integer
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        static long ReadInt(BufferView buffer)
        {
            byte firstByte;
            long i;
            int  length, shifts;

            // Get the first byte
            if (buffer.Length == 0)
            {
                throw new NotEnoughData("Unable to extract signed integer");
            }
            firstByte = buffer[0];

            // Get the total length and the first bits
            if (firstByte < Data.OFFSET_2_B)
            {
                // Fast path
                buffer.Slice(1);
                return((long)firstByte + Data.MIN_INT_1_B);
            }
            else if (firstByte < Data.OFFSET_3_B)
            {
                length = 1;
                i      = (long)(firstByte & Data.MASK_6_B) + Data.MIN_INT_2_B;
            }
            else if (firstByte < Data.OFFSET_4_B)
            {
                length = 2;
                i      = (long)(firstByte & Data.MASK_5_B) + Data.MIN_INT_3_B;
            }
            else if (firstByte < Data.OFFSET_5_B)
            {
                length = 3;
                i      = (long)(firstByte & Data.MASK_4_B) + Data.MIN_INT_4_B;
            }
            else if (firstByte < Data.OFFSET_6_B)
            {
                length = 4;
                i      = (long)(firstByte & Data.MASK_3_B) + Data.MIN_INT_5_B;
            }
            else if (firstByte < Data.OFFSET_7_B)
            {
                length = 5;
                i      = (long)(firstByte & Data.MASK_2_B) + Data.MIN_INT_6_B;
            }
            else if (firstByte < Data.OFFSET_8_B)
            {
                length = 6;
                i      = (long)(firstByte & Data.MASK_1_B) + Data.MIN_INT_7_B;
            }
            else if (firstByte == Data.OFFSET_8_B)
            {
                length = 7;
                i      = Data.MIN_INT_8_B;
            }
            else
            {
                throw new InvalidOperationException("Unable to extract signed integer");
            }

            // Get the remaining bytes
            if (buffer.Length <= length)
            {
                throw new NotEnoughData("Unable to extract signed integer");
            }
            shifts = 7 - length;
            for (int j = 1; j <= length; j++)
            {
                long temp = buffer[j];
                i      += temp << shifts;
                shifts += 8;
            }

            buffer.Slice(length + 1);
            return(i);
        }
Example #29
0
        /// <summary>
        /// Extract an array
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <param name="format">A component of an inflated format object</param>
        /// <returns>Return the extracted data</returns>
        static ArrayList ReadArray(BufferView buffer, Format.ElementsArray format)
        {
            int length;

            // Get the number of elements
            length = (int)ReadUint(buffer);

            // Extract each element
            ArrayList array = new ArrayList();
            if (format.Elements.Count == 1)
                for (int i = 0; i < length; i++)
                    ReadElement(buffer, array, format);
            else
                for (int i = 0; i < length; i++) {
                    ArrayList subArray = new ArrayList();
                    ReadElement(buffer, subArray, format);
                    array.Add(subArray);
                }

            return array;
        }
Example #30
0
        /// <summary>
        /// Extract an unsigned integer
        /// </summary>
        /// <param name="buffer">A view with the encoded data</param>
        /// <returns>Return the extracted data</returns>
        internal static ulong ReadUint(BufferView buffer)
        {
            byte  firstByte;
            int   length, shifts;
            ulong u;

            // Get the first byte
            if (buffer.Length == 0)
            {
                throw new NotEnoughData("Unable to extract unsigned integer");
            }
            firstByte = buffer[0];

            // Get the total length and the first bits
            if (firstByte < Data.OFFSET_2_B)
            {
                // Fast path
                buffer.Slice(1);
                return((ulong)firstByte);
            }
            else if (firstByte < Data.OFFSET_3_B)
            {
                length = 1;
                u      = (ulong)(firstByte & Data.MASK_6_B);
            }
            else if (firstByte < Data.OFFSET_4_B)
            {
                length = 2;
                u      = (ulong)(firstByte & Data.MASK_5_B);
            }
            else if (firstByte < Data.OFFSET_5_B)
            {
                length = 3;
                u      = (ulong)(firstByte & Data.MASK_4_B);
            }
            else if (firstByte < Data.OFFSET_6_B)
            {
                length = 4;
                u      = (ulong)(firstByte & Data.MASK_3_B);
            }
            else if (firstByte < Data.OFFSET_7_B)
            {
                length = 5;
                u      = (ulong)(firstByte & Data.MASK_2_B);
            }
            else if (firstByte < Data.OFFSET_8_B)
            {
                length = 6;
                u      = (ulong)(firstByte & Data.MASK_1_B);
            }
            else if (firstByte == Data.OFFSET_8_B)
            {
                length = 7;
                u      = 0;
            }
            else
            {
                throw new InvalidOperationException("Unable to extract unsigned integer");
            }

            // Get the remaining bytes
            if (buffer.Length <= length)
            {
                throw new NotEnoughData("Unable to extract unsigned integer");
            }
            shifts = 7 - length;
            for (int i = 1; i <= length; i++)
            {
                ulong temp = buffer[i];
                u      += temp << shifts;
                shifts += 8;
            }

            buffer.Slice(length + 1);
            return(u);
        }