private static async Task WriteAsyncCore(Stream utf8Json, object?value, Type inputType, JsonSerializerOptions?options, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                options = JsonSerializerOptions.s_defaultOptions;
            }

            JsonWriterOptions writerOptions = options.GetWriterOptions();

            using (var bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize))
                using (var writer = new Utf8JsonWriter(bufferWriter, writerOptions))
                {
                    if (value == null)
                    {
                        writer.WriteNullValue();
                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        return;
                    }

                    if (inputType == null)
                    {
                        inputType = value.GetType();
                    }

                    WriteStack state = default;
                    state.InitializeRoot(inputType, options, supportContinuation: true);

                    bool isFinalBlock;

                    do
                    {
                        // todo: determine best value here
                        // https://github.com/dotnet/runtime/issues/32356
                        state.FlushThreshold = (int)(bufferWriter.Capacity * .9);
                        isFinalBlock         = WriteCore(
                            writer,
                            value,
                            options,
                            ref state,
                            state.Current.JsonClassInfo !.PolicyProperty !.ConverterBase);

                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        bufferWriter.Clear();
                    } while (!isFinalBlock);
                }

            // todo: verify that we do want to call FlushAsync here (or above). It seems like leaving it to the caller would be best.
        }