void ReturnOtherThanLastBuffer()
        {
            var bufferList     = m_ReceiveCache.GetAllCachedItems();
            var count          = bufferList.Count;
            var lastBufferItem = bufferList[count - 1].Key.Array;

            for (var i = count - 2; i >= 0; i--)
            {
                if (bufferList[i].Key.Array != lastBufferItem)
                {
                    m_BufferRecycler.Return(bufferList, 0, i + 1);
                    break;
                }
            }

            m_ReceiveCache.Clear();
        }
        /// <summary>
        /// Processes the input segment.
        /// </summary>
        /// <param name="segment">The input segment.</param>
        /// <param name="state">The buffer state.</param>
        /// <returns>
        /// the processing result
        /// </returns>
        public virtual ProcessResult Process(ArraySegment <byte> segment, IBufferState state)
        {
            m_ReceiveCache.Add(segment, state);

            var rest = 0;

            while (true)
            {
                var packageInfo = m_ReceiveFilter.Filter(m_ReceiveCache, out rest);

                if (m_ReceiveFilter.State == FilterState.Error)
                {
                    m_BufferRecycler.Return(m_ReceiveCache.GetAllCachedItems(), 0, m_ReceiveCache.Count);
                    return(ProcessResult.Create(ProcessState.Error));
                }

                if (m_MaxPackageLength > 0)
                {
                    var length = m_ReceiveCache.Total;

                    if (length > m_MaxPackageLength)
                    {
                        m_BufferRecycler.Return(m_ReceiveCache.GetAllCachedItems(), 0, m_ReceiveCache.Count);
                        return(ProcessResult.Create(ProcessState.Error, string.Format("Max package length: {0}, current processed length: {1}", m_MaxPackageLength, length)));
                    }
                }

                //Receive continue
                if (packageInfo == null)
                {
                    if (rest > 0)
                    {
                        PushResetData(segment, rest, state);
                        continue;
                    }

                    return(ProcessResult.Create(ProcessState.Cached));
                }

                m_ReceiveFilter.Reset();

                var nextReceiveFilter = m_ReceiveFilter.NextReceiveFilter;

                if (nextReceiveFilter != null)
                {
                    m_ReceiveFilter = nextReceiveFilter;
                }

                m_PackageHandler.Handle(packageInfo);

                if (packageInfo is IBufferedPackageInfo && // is a buffered package
                    (packageInfo as IBufferedPackageInfo).Data is BufferList)        // and it uses receive buffer directly
                {
                    // so we need to create a new receive buffer container to use
                    m_ReceiveCache = new BufferList();

                    if (rest <= 0)
                    {
                        return(ProcessResult.Create(ProcessState.Cached));
                    }
                }
                else
                {
                    ReturnOtherThanLastBuffer();

                    if (rest <= 0)
                    {
                        return(ProcessResult.Create(ProcessState.Completed));
                    }
                }

                PushResetData(segment, rest, state);
            }
        }