@@ -163,6 +163,8 @@ type t =
163163 ; mutable bytes_written : int (* Total written bytes. Wraps. *)
164164 ; mutable state : state
165165 ; mutable wake_writer : unit -> unit
166+ ; mutable is_formatting : bool
167+ ; mutable formatter : Format .formatter option
166168 }
167169(* Invariant: [write_pos >= scheduled_pos] *)
168170
@@ -377,6 +379,8 @@ let of_buffer ?sw buffer =
377379 ; bytes_written = 0
378380 ; state = Active
379381 ; wake_writer = ignore
382+ ; is_formatting = false
383+ ; formatter = None
380384 }
381385 in
382386 begin match sw with
@@ -416,6 +420,30 @@ let flush t =
416420 Promise. await_exn p
417421 )
418422
423+ let get_formatter = function
424+ | { formatter = Some x ; _ } -> x
425+ | ({ formatter = None ; _ } as t ) ->
426+ let formatter = Format. make_formatter
427+ (fun buf off len -> write_gen t buf ~off ~len ~blit: Bigstringaf. blit_from_string)
428+ (fun () ->
429+ (* As per the Format module manual, an explicit flush writes to the
430+ output channel and ensures that "all pending text is displayed"
431+ and "these explicit flush calls [...] could dramatically impact efficiency".
432+ Therefore it is clear that we need to call `flush t` instead of `flush_buffer t`. *)
433+ if t.is_formatting then flush t)
434+ in
435+ t.formatter < - Some formatter;
436+ formatter
437+
438+ let printf t =
439+ let ppf = get_formatter t in
440+ t.is_formatting < - true ;
441+ Format. kfprintf (fun ppf ->
442+ assert t.is_formatting;
443+ t.is_formatting < - false ;
444+ Format. pp_print_flush ppf ()
445+ ) ppf
446+
419447let rec shift_buffers t written =
420448 match Buffers. dequeue_exn t.scheduled with
421449 | { Cstruct. len; _ } as iovec ->
0 commit comments