/// <summary>
		/// Combines one or more ReadOnlySequences into a single ReadOnlySequence
		/// </summary>
		/// <typeparam name="T">The element type in the sequence</typeparam>
		/// <param name="source">An enumeration of ReadOnlySequences</param>
		/// <returns>The concatenation of the given ReadOnlySequences</returns>
		public static ReadOnlySequence<T> Combine<T>(this IEnumerable<ReadOnlySequence<T>> source)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));

			ReadOnlySequence<T>? FirstSequence = null;
			CombinedSegment<T>? StartSegment = null, CurrentSegment = null;

			// Merge all the sequences into one
			foreach (var Sequence in source)
			{
				if (Sequence.IsEmpty)
					continue;

				if (CurrentSegment == null)
				{
					// Cache the first sequence. If there are no others, we can just return it as-is
					if (FirstSequence == null)
					{
						FirstSequence = Sequence;
						continue;
					}

					// Found a second sequence
					// Create the first segment of the linked list
					StartSegment = CurrentSegment = new CombinedSegment<T>(FirstSequence.Value.First);

					// Append any subsequent segments
					foreach (var ChildSegment in FirstSequence.Value.Slice(StartSegment.Memory.Length))
						CurrentSegment = new CombinedSegment<T>(CurrentSegment, ChildSegment);
				}

				// Append the segments of this sequence to the linked list as well
				foreach (var ChildSegment in Sequence)
					CurrentSegment = new CombinedSegment<T>(CurrentSegment, ChildSegment);
			}

			if (CurrentSegment == null)
			{
				// Only found one non-empty sequence
				if (FirstSequence != null)
					return FirstSequence.Value;

				// Found no non-empty sequences
				return ReadOnlySequence<T>.Empty;
			}

			return new ReadOnlySequence<T>(StartSegment!, 0, CurrentSegment, CurrentSegment.Memory.Length);
		}
		/// <summary>
		/// Encodes a char sequence as a byte sequence
		/// </summary>
		/// <param name="sequence">The char sequence to decode</param>
		/// <param name="encoding">The encoding to use</param>
		/// <returns>The encoded contents of the sequence</returns>
		public static ReadOnlySequence<byte> Encode(this ReadOnlySequence<char> sequence, Encoding encoding)
		{
			if (encoding == null)
				throw new ArgumentNullException(nameof(encoding));

			if (sequence.IsSingleSegment)
				return new ReadOnlySequence<byte>(encoding.GetBytes(sequence.First.Span));

			var Encoder = encoding.GetEncoder();

			CombinedSegment<byte>? StartSegment = null, CurrentSegment = null;

			foreach (var MySegment in sequence)
			{
				var InBuffer = MySegment.Span;

				var OutBuffer = new byte[Encoder.GetByteCount(InBuffer, false)];
				var WrittenChars = Encoder.GetBytes(InBuffer, OutBuffer, false);
				var OutSegment = new ReadOnlyMemory<byte>(OutBuffer, 0, WrittenChars);

				if (StartSegment == null)
					StartSegment = CurrentSegment = new CombinedSegment<byte>(OutSegment);
				else
					CurrentSegment = new CombinedSegment<byte>(CurrentSegment!, OutSegment);
			}

			// Flush the encoder
			var RemainingBytes = Encoder.GetByteCount(Array.Empty<char>(), true);

			if (RemainingBytes > 0)
			{
				var OutBuffer = new byte[RemainingBytes];
				var WrittenChars = Encoder.GetBytes(Array.Empty<char>(), OutBuffer, true);
				var OutSegment = new ReadOnlyMemory<byte>(OutBuffer, 0, WrittenChars);

				if (StartSegment == null)
					StartSegment = CurrentSegment = new CombinedSegment<byte>(OutSegment);
				else
					CurrentSegment = new CombinedSegment<byte>(CurrentSegment!, OutSegment);
			}

			if (CurrentSegment == null)
				return ReadOnlySequence<byte>.Empty;

			return new ReadOnlySequence<byte>(StartSegment!, 0, CurrentSegment, CurrentSegment.Memory.Length);
		}
		/// <summary>
		/// Combines one or more ReadOnlyMemory blocks into a single ReadOnlySequence
		/// </summary>
		/// <typeparam name="T">The element type in the sequence</typeparam>
		/// <param name="source">An enumeration of ReadOnlyMemory blocks</param>
		/// <returns>A ReadOnlySequence from the given blocks</returns>
		public static ReadOnlySequence<T> Combine<T>(this IEnumerable<ReadOnlyMemory<T>> source)
		{
			if (source == null)
				throw new ArgumentNullException(nameof(source));

			ReadOnlyMemory<T>? FirstSegment = null;
			CombinedSegment<T>? StartSegment = null, CurrentSegment = null;

			foreach (var Segment in source)
			{
				if (Segment.IsEmpty)
					continue;

				if (CurrentSegment == null)
				{
					// Cache the first segment. If there are no others, we can just wrap it as-is
					if (FirstSegment == null)
					{
						FirstSegment = Segment;
						continue;
					}

					// Found a second segment
					// Create the first segment of the linked list
					StartSegment = CurrentSegment = new CombinedSegment<T>(FirstSegment.Value);
				}

				CurrentSegment = new CombinedSegment<T>(CurrentSegment, Segment);
			}

			if (CurrentSegment == null)
			{
				// Only found one non-empty sequence
				if (FirstSegment != null)
					return new ReadOnlySequence<T>(FirstSegment.Value);

				// Found no non-empty sequences
				return ReadOnlySequence<T>.Empty;
			}

			return new ReadOnlySequence<T>(StartSegment!, 0, CurrentSegment, CurrentSegment.Memory.Length);
		}