using System.Collections;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
public static class StringExtensions
static readonly Encoding encoding = Encoding.GetEncoding(Encoding.UTF8.CodePage, new EncoderExceptionFallback(), new DecoderExceptionFallback());
static readonly int maxBytes = encoding.GetMaxByteCount(1);
public static int IndexOf(this ReadOnlySpan<byte> utf8Bytes, char @char)
Span<byte> charBytes = stackalloc byte[maxBytes];
var n = encoding.GetBytes(stackalloc char[1] { @char }, charBytes);
charBytes = charBytes.Slice(0, n);
catch (EncoderFallbackException)
for (int i = 0; i <= utf8Bytes.Length - charBytes.Length; i++)
if (charBytes.CommonPrefixLength(utf8Bytes.Slice(i)) == charBytes.Length)
public static int IndexOf(this ReadOnlySpan<byte> utf8Bytes, Rune @char)
Span<byte> charBytes = stackalloc byte[@char.Utf8SequenceLength];
var n = @char.EncodeToUtf8(charBytes);
charBytes = charBytes.Slice(0, n);
catch (EncoderFallbackException)
for (int i = 0; i <= utf8Bytes.Length - charBytes.Length; i++)
if (charBytes.CommonPrefixLength(utf8Bytes.Slice(i)) == charBytes.Length)
public static void Test()
Test("?hello", '\xFFFF');
Test("?hello", '\xDC00');
public static void Test(string s, char c)
ReadOnlySpan<byte> bytes = Encoding.UTF8.GetBytes(s);
var index = bytes.IndexOf(c);
var charIndex = s.IndexOf(c);
var charFound = charIndex >= 0;
Console.WriteLine($"For s={s} and c={c}, index={index}, charIndex={charIndex}");
Assert.That(charFound == found, $"For s={s} and c={c}, {charFound} != {found}");
var charBytes = Encoding.UTF8.GetBytes(c.ToString());
if (charBytes.Length == 1 && bytes.Length == s.Length)
Assert.AreEqual(charIndex, index, $"{charIndex} == {index}");
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription, Environment.Version, Environment.OSVersion);
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");