@@ -102,53 +102,78 @@ module Reader = struct
102102end
103103
104104module Writer = struct
105+ module Writer = Serialize. Writer
106+
105107 type encoding =
106108 | Identity
107109 | Chunked of { mutable written_final_chunk : bool }
108110
109111 type t =
110- { faraday : Faraday .t
111- ; encoding : encoding
112- ; when_ready_to_write : unit -> unit
113- ; buffered_bytes : int ref
112+ { faraday : Faraday .t
113+ ; writer : Writer .t
114+ ; encoding : encoding
115+ ; buffered_bytes : int ref
114116 }
115117
116- let of_faraday faraday ~ encoding ~ when_ready_to_write =
118+ let of_faraday faraday writer ~ encoding =
117119 let encoding =
118120 match encoding with
119121 | `Fixed _ | `Close_delimited -> Identity
120122 | `Chunked -> Chunked { written_final_chunk = false }
121123 in
122124 { faraday
123125 ; encoding
124- ; when_ready_to_write
126+ ; writer
125127 ; buffered_bytes = ref 0
126128 }
127129
128- let create buffer ~ encoding ~ when_ready_to_write =
129- of_faraday (Faraday. of_bigstring buffer) ~encoding ~when_ready_to_write
130+ let create buffer writer ~ encoding =
131+ of_faraday (Faraday. of_bigstring buffer) writer ~encoding
130132
131133 let write_char t c =
132- Faraday. write_char t.faraday c
134+ if not (Faraday. is_closed t.faraday) then
135+ Faraday. write_char t.faraday c
133136
134137 let write_string t ?off ?len s =
135- Faraday. write_string ?off ?len t.faraday s
138+ if not (Faraday. is_closed t.faraday) then
139+ Faraday. write_string ?off ?len t.faraday s
136140
137141 let write_bigstring t ?off ?len b =
138- Faraday. write_bigstring ?off ?len t.faraday b
142+ if not (Faraday. is_closed t.faraday) then
143+ Faraday. write_bigstring ?off ?len t.faraday b
139144
140145 let schedule_bigstring t ?off ?len (b :Bigstringaf.t ) =
141- Faraday. schedule_bigstring ?off ?len t.faraday b
146+ if not (Faraday. is_closed t.faraday) then
147+ Faraday. schedule_bigstring ?off ?len t.faraday b
142148
143- let ready_to_write t = t.when_ready_to_write ()
149+ let ready_to_write t = Writer. wakeup t.writer
144150
145151 let flush t kontinue =
146152 Faraday. flush t.faraday kontinue;
147153 ready_to_write t
148154
155+ let flush_with_reason t kontinue =
156+ if Writer. is_closed t.writer then
157+ kontinue `Closed
158+ else begin
159+ Faraday. flush_with_reason t.faraday (fun reason ->
160+ let result =
161+ match reason with
162+ | Nothing_pending | Shift -> `Written
163+ | Drain -> `Closed
164+ in
165+ kontinue result);
166+ ready_to_write t
167+ end
168+
149169 let is_closed t =
150170 Faraday. is_closed t.faraday
151171
172+ let close_and_drain t =
173+ Faraday. close t.faraday;
174+ (* Resolve all pending flushes *)
175+ ignore (Faraday. drain t.faraday : int )
176+
152177 let close t =
153178 Faraday. close t.faraday;
154179 ready_to_write t;
@@ -166,33 +191,39 @@ module Writer = struct
166191 in
167192 faraday_has_output || additional_encoding_output
168193
169- let transfer_to_writer t writer =
194+ let transfer_to_writer t =
170195 let faraday = t.faraday in
171- begin match Faraday. operation faraday with
172- | `Yield -> ()
173- | `Close ->
174- (match t.encoding with
175- | Identity -> ()
176- | Chunked ({ written_final_chunk } as chunked ) ->
177- if not written_final_chunk then begin
178- chunked.written_final_chunk < - true ;
179- Serialize.Writer. schedule_chunk writer [] ;
180- end );
181- Serialize.Writer. unyield writer;
182- | `Writev iovecs ->
183- let buffered = t.buffered_bytes in
184- begin match IOVec. shiftv iovecs ! buffered with
185- | [] -> ()
186- | iovecs ->
187- let lengthv = IOVec. lengthv iovecs in
188- buffered := ! buffered + lengthv;
189- begin match t.encoding with
190- | Identity -> Serialize.Writer. schedule_fixed writer iovecs
191- | Chunked _ -> Serialize.Writer. schedule_chunk writer iovecs
192- end ;
193- Serialize.Writer. flush writer (fun () ->
194- Faraday. shift faraday lengthv;
195- buffered := ! buffered - lengthv)
196- end
196+ if Writer. is_closed t.writer then
197+ close_and_drain t
198+ else begin
199+ match Faraday. operation faraday with
200+ | `Yield -> ()
201+ | `Close ->
202+ (match t.encoding with
203+ | Identity -> ()
204+ | Chunked ({ written_final_chunk } as chunked ) ->
205+ if not written_final_chunk then begin
206+ chunked.written_final_chunk < - true ;
207+ Serialize.Writer. schedule_chunk t.writer [] ;
208+ end );
209+ Serialize.Writer. unyield t.writer;
210+ | `Writev iovecs ->
211+ let buffered = t.buffered_bytes in
212+ begin match IOVec. shiftv iovecs ! buffered with
213+ | [] -> ()
214+ | iovecs ->
215+ let lengthv = IOVec. lengthv iovecs in
216+ buffered := ! buffered + lengthv;
217+ begin match t.encoding with
218+ | Identity -> Serialize.Writer. schedule_fixed t.writer iovecs
219+ | Chunked _ -> Serialize.Writer. schedule_chunk t.writer iovecs
220+ end ;
221+ Serialize.Writer. flush t.writer (fun result ->
222+ match result with
223+ | `Closed -> close_and_drain t
224+ | `Written ->
225+ Faraday. shift faraday lengthv;
226+ buffered := ! buffered - lengthv)
227+ end
197228 end
198229end
0 commit comments