public int CopyTo(Span <byte> buffer) { var first = First; var firstLength = first.Length; if (firstLength > buffer.Length) { first.Slice(0, buffer.Length).CopyTo(buffer); return(buffer.Length); } first.CopyTo(buffer); if (buffer.Length == firstLength || _rest == null) { return(firstLength); } return(firstLength + _rest.CopyTo(buffer.Slice(firstLength))); }
// TODO (pri 3): I am pretty sure this whole routine can be written much better // searches values that potentially straddle between first and rest internal static int IndexOfStraddling(this ReadOnlySpan <byte> first, IReadOnlyBufferList <byte> rest, ReadOnlySpan <byte> value) { Debug.Assert(first.IndexOf(value) == -1); if (rest == null) { return(-1); } // we only need to search the end of the first buffer. More precisely, only up to value.Length - 1 bytes in the first buffer // The other bytes in first, were already search and presumably did not match int bytesToSkipFromFirst = 0; if (first.Length > value.Length - 1) { bytesToSkipFromFirst = first.Length - value.Length - 1; } // now that we know how many bytes we need to skip, create slice of first buffer with bytes that need to be searched. ReadOnlySpan <byte> bytesToSearchAgain; if (bytesToSkipFromFirst > 0) { bytesToSearchAgain = first.Slice(bytesToSkipFromFirst); } else { bytesToSearchAgain = first; } int index; // now combine the bytes from the end of the first buffer with bytes in the rest, and serarch the combined buffer // this check is a small optimization: if the first byte from the value does not exist in the bytesToSearchAgain, there is no reason to combine if (bytesToSearchAgain.IndexOf(value[0]) != -1) { var combinedBufferLength = value.Length << 1; var combined = combinedBufferLength < 128 ? stackalloc byte[combinedBufferLength] : // TODO (pri 3): I think this could be eliminated by chunking values new byte[combinedBufferLength]; bytesToSearchAgain.CopyTo(combined); int combinedLength = bytesToSearchAgain.Length + rest.CopyTo(combined.Slice(bytesToSearchAgain.Length)); combined = combined.Slice(0, combinedLength); if (combined.Length < value.Length) { return(-1); } index = combined.IndexOf(value); if (index != -1) { return(index + bytesToSkipFromFirst); } } // try to find the bytes in _rest index = rest.IndexOf(value); if (index != -1) { return(first.Length + index); } return(-1); }