Skip to main content

grpc/
stream.rs

1//! Synchronous streaming calls over a caller-thread I/O driver.
2//! Drivers handle transport, framing and codecs; handles enforce RPC lifecycle
3//! and cardinality without creating threads or an executor.
4use std::{cell::RefCell, rc::Rc};
5
6use grpc_core::{Metadata, Status};
7/// A pending operation or a terminal RPC failure.
8#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
9pub enum StreamError {
10    /// No message or transport capacity is available without waiting.
11    #[error("stream would block")]
12    WouldBlock,
13    /// Terminal local, transport or remote gRPC status.
14    #[error("{0}")]
15    Status(#[from] Status),
16}
17type Result<T> = std::result::Result<T, StreamError>;
18fn invalid(message: &str) -> StreamError {
19    Status::failed_precondition(message).into()
20}
21/// Typed, single-threaded transport seam for one RPC.
22///
23/// `WouldBlock` means no message, send, half-close or finish was committed; a
24/// retry must not duplicate a frame. All methods except `wait_ready` are bounded
25/// nonblocking steps. `wait_ready` waits for actual I/O readiness or a deadline
26/// on the caller thread; it must not busy-spin. Errors other than `WouldBlock`
27/// terminate the call. Before returning client response EOF, validate grpc-status
28/// and expose trailers (including an empty collection); non-OK status is an error.
29/// Request EOF on a server only half-closes its inbound direction.
30///
31/// Metadata remains available after cancellation. `cancel` releases local stream
32/// resources without waiting, cannot panic, and does not promise peer acknowledgement.
33pub trait StreamDriver {
34    type Send;
35    type Receive;
36    /// Attempts to commit one outgoing message.
37    /// # Errors
38    /// Returns pending without accepting the message, or a terminal failure.
39    fn send(&mut self, message: &Self::Send) -> Result<()>;
40    /// Attempts to half-close outgoing messages.
41    /// # Errors
42    /// Returns pending without closing, or a terminal failure.
43    fn half_close(&mut self) -> Result<()>;
44    /// Receives a message, validated EOF, or a pending/terminal error.
45    /// # Errors
46    /// Returns `WouldBlock` while pending; all other errors are terminal.
47    fn try_recv_next(&mut self) -> Result<Option<Self::Receive>>;
48    /// Waits for readiness needed by the last pending operation.
49    /// # Errors
50    /// Returns a terminal transport/deadline failure; must not return `WouldBlock`.
51    fn wait_ready(&mut self) -> Result<()>;
52    /// Attempts server completion, including non-OK trailers-only responses.
53    /// # Errors
54    /// Returns pending without committing completion, or a terminal failure.
55    fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()>;
56    fn initial_metadata(&self) -> Option<&Metadata>;
57    fn trailing_metadata(&self) -> Option<&Metadata>;
58    fn cancel(&mut self);
59}
60struct State<D: StreamDriver> {
61    driver: D,
62    error: Option<StreamError>,
63    receive_closed: bool,
64    send_closed: bool,
65    complete: bool,
66    client: bool,
67}
68impl<D: StreamDriver> State<D> {
69    fn fail(&mut self, error: StreamError) -> StreamError {
70        self.error = Some(error.clone());
71        if !self.complete {
72            self.driver.cancel();
73        }
74        self.complete = true;
75        error
76    }
77    fn check(&self) -> Result<()> {
78        self.error.clone().map_or(Ok(()), Err)
79    }
80    fn accept<T>(&mut self, result: Result<T>) -> Result<T> {
81        match result {
82            Err(StreamError::WouldBlock) => Err(StreamError::WouldBlock),
83            Err(e) => Err(self.fail(e)),
84            Ok(value) => Ok(value),
85        }
86    }
87    fn poll(&mut self) -> Result<Option<D::Receive>> {
88        self.check()?;
89        if self.receive_closed {
90            return Ok(None);
91        }
92        let result = self.driver.try_recv_next();
93        let message = self.accept(result)?;
94        if message.is_none() {
95            if self.client && self.driver.trailing_metadata().is_none() {
96                return Err(
97                    self.fail(Status::unknown("response ended without validated trailers").into())
98                );
99            }
100            self.receive_closed = true;
101            if self.client {
102                if !self.send_closed {
103                    self.driver.cancel();
104                }
105                (self.complete, self.send_closed) = (true, true);
106            }
107        }
108        Ok(message)
109    }
110    fn send(&mut self, value: &D::Send) -> Result<()> {
111        self.check()?;
112        if self.send_closed {
113            return Err(invalid("send direction is closed"));
114        }
115        let result = self.driver.send(value);
116        self.accept(result)
117    }
118    fn close(&mut self) -> Result<()> {
119        self.check()?;
120        if self.send_closed {
121            return Ok(());
122        }
123        let result = self.driver.half_close();
124        self.accept(result)?;
125        self.send_closed = true;
126        Ok(())
127    }
128    fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()> {
129        self.check()?;
130        if self.complete {
131            return Err(invalid("RPC is already finished"));
132        }
133        let result = self.driver.finish(status, trailers);
134        self.accept(result)?;
135        (self.complete, self.send_closed, self.receive_closed) = (true, true, true);
136        Ok(())
137    }
138    fn wait(&mut self) -> Result<()> {
139        self.check()?;
140        match self.driver.wait_ready() {
141            Ok(()) => Ok(()),
142            Err(StreamError::WouldBlock) => {
143                Err(self.fail(Status::internal("driver wait made no progress").into()))
144            }
145            Err(e) => Err(self.fail(e)),
146        }
147    }
148    fn cancel(&mut self) {
149        if !self.complete {
150            self.fail(Status::cancelled("call cancelled").into());
151        }
152    }
153}
154impl<D: StreamDriver> Drop for State<D> {
155    fn drop(&mut self) {
156        if !self.complete {
157            self.driver.cancel();
158        }
159    }
160}
161trait Control {
162    fn fail(&mut self, error: StreamError) -> Result<()>;
163    fn wait(&mut self) -> Result<()>;
164    fn metadata(&self, trailing: bool) -> Result<Option<Metadata>>;
165    fn cancel(&mut self) -> Result<()>;
166}
167trait Receive<T>: Control {
168    fn poll(&mut self) -> Result<Option<T>>;
169}
170trait Send<T>: Control {
171    fn send(&mut self, value: &T) -> Result<()>;
172    fn close(&mut self) -> Result<()>;
173    fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()>;
174}
175struct Handle<D: StreamDriver>(Rc<RefCell<State<D>>>);
176impl<D: StreamDriver> Handle<D> {
177    fn with<T>(&self, f: impl FnOnce(&mut State<D>) -> Result<T>) -> Result<T> {
178        let mut state = self
179            .0
180            .try_borrow_mut()
181            .map_err(|_| invalid("reentrant stream operation"))?;
182        f(&mut state)
183    }
184}
185impl<D: StreamDriver> Control for Handle<D> {
186    fn fail(&mut self, error: StreamError) -> Result<()> {
187        self.with(|state| {
188            state.fail(error);
189            Ok(())
190        })
191    }
192    fn wait(&mut self) -> Result<()> {
193        self.with(State::wait)
194    }
195    fn metadata(&self, trailing: bool) -> Result<Option<Metadata>> {
196        let state = self
197            .0
198            .try_borrow()
199            .map_err(|_| invalid("reentrant metadata access"))?;
200        Ok(if trailing {
201            state.driver.trailing_metadata()
202        } else {
203            state.driver.initial_metadata()
204        }
205        .cloned())
206    }
207    fn cancel(&mut self) -> Result<()> {
208        self.with(|state| {
209            state.cancel();
210            Ok(())
211        })
212    }
213}
214impl<D: StreamDriver> Receive<D::Receive> for Handle<D> {
215    fn poll(&mut self) -> Result<Option<D::Receive>> {
216        self.with(State::poll)
217    }
218}
219impl<D: StreamDriver> Send<D::Send> for Handle<D> {
220    fn send(&mut self, value: &D::Send) -> Result<()> {
221        self.with(|s| s.send(value))
222    }
223    fn close(&mut self) -> Result<()> {
224        self.with(State::close)
225    }
226    fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()> {
227        self.with(|s| s.finish(status, trailers))
228    }
229}
230type Shared<D> = Rc<RefCell<State<D>>>;
231fn shared<D: StreamDriver>(driver: D, client: bool, send_closed: bool) -> Shared<D> {
232    Rc::new(RefCell::new(State {
233        driver,
234        error: None,
235        receive_closed: false,
236        send_closed,
237        complete: false,
238        client,
239    }))
240}
241fn blocking<T, C: Control + ?Sized>(
242    control: &mut C,
243    mut step: impl FnMut(&mut C) -> Result<T>,
244) -> Result<T> {
245    loop {
246        match step(control) {
247            Err(StreamError::WouldBlock) => control.wait()?,
248            result => return result,
249        }
250    }
251}
252macro_rules! control_methods {
253    ($($field:ident).+) => {
254        /// Copies received initial metadata, if available.
255        /// # Errors
256        /// Rejects reentrant access from a driver callback.
257        pub fn initial_metadata(&self) -> Result<Option<Metadata>> {
258            self.$($field).+.metadata(false)
259        }
260        /// Copies terminal metadata, including on a remote failure.
261        /// # Errors
262        /// Rejects reentrant access from a driver callback.
263        pub fn trailing_metadata(&self) -> Result<Option<Metadata>> {
264            self.$($field).+.metadata(true)
265        }
266        /// Cancels local resources without waiting for peer acknowledgement.
267        /// # Errors
268        /// Rejects reentrant access from a driver callback.
269        pub fn cancel(&mut self) -> Result<()> { self.$($field).+.cancel() }
270    };
271}
272macro_rules! send_methods {
273    ($message:ty, $($field:ident).+) => {
274        /// Sends a message, waiting for transport capacity.
275        /// # Errors
276        /// Returns a closed-direction or terminal failure.
277        pub fn send(&mut self, value: &$message) -> Result<()> {
278            blocking(self.$($field).+.as_mut(), |sender| sender.send(value))
279        }
280        /// Attempts a send; pending means the message was not accepted.
281        /// # Errors
282        /// Returns pending, closed-direction or terminal failure.
283        pub fn try_send(&mut self, value: &$message) -> Result<()> { self.$($field).+.send(value) }
284    };
285}
286macro_rules! close_methods {
287    ($($field:ident).+) => {
288        /// Idempotently half-closes requests while allowing further responses.
289        /// # Errors
290        /// Returns a terminal failure.
291        pub fn half_close(&mut self) -> Result<()> {
292            blocking(self.$($field).+.as_mut(), |sender| sender.close())
293        }
294        /// Attempts request half-close without waiting.
295        /// # Errors
296        /// Returns pending or terminal failure.
297        pub fn try_half_close(&mut self) -> Result<()> { self.$($field).+.close() }
298    };
299}
300/// Receiving half of a server-streaming or bidirectional client call.
301pub struct ServerStreamingCall<T> {
302    receiver: Box<dyn Receive<T>>,
303}
304impl<T: 'static> ServerStreamingCall<T> {
305    /// Wraps a call whose unary request was sent and half-closed by its driver.
306    pub fn new<D: StreamDriver<Receive = T> + 'static>(driver: D) -> Self {
307        Self {
308            receiver: Box::new(Handle(shared(driver, true, true))),
309        }
310    }
311    /// Performs one nonblocking receive attempt.
312    /// # Errors
313    /// Returns pending or the sticky terminal failure; EOF is `Ok(None)`.
314    pub fn try_recv_next(&mut self) -> Result<Option<T>> {
315        self.receiver.poll()
316    }
317    /// Receives the next message, waiting for readiness on the caller thread.
318    /// # Errors
319    /// Returns a terminal RPC, transport or deadline failure.
320    pub fn recv_next(&mut self) -> Result<Option<T>> {
321        blocking(self.receiver.as_mut(), |receiver| receiver.poll())
322    }
323    /// Drains and returns remaining messages through validated completion.
324    /// # Errors
325    /// Returns a terminal failure, including missing successful trailers.
326    pub fn finish(&mut self) -> Result<Vec<T>> {
327        let mut messages = Vec::new();
328        while let Some(message) = self.recv_next()? {
329            messages.push(message);
330        }
331        Ok(messages)
332    }
333    control_methods!(receiver);
334}
335/// Inbound server requests, created together with a response sink by [`server_streams`].
336/// Request EOF half-closes inbound messages without closing the response sink.
337pub struct RequestStream<Req>(ServerStreamingCall<Req>);
338impl<Req: 'static> RequestStream<Req> {
339    /// Wraps inbound requests without treating request EOF as response completion.
340    pub fn new<D: StreamDriver<Receive = Req> + 'static>(driver: D) -> Self {
341        Self(ServerStreamingCall {
342            receiver: Box::new(Handle(shared(driver, false, false))),
343        })
344    }
345}
346impl<Req> std::ops::Deref for RequestStream<Req> {
347    type Target = ServerStreamingCall<Req>;
348    fn deref(&self) -> &Self::Target {
349        &self.0
350    }
351}
352impl<Req> std::ops::DerefMut for RequestStream<Req> {
353    fn deref_mut(&mut self) -> &mut Self::Target {
354        &mut self.0
355    }
356}
357/// Sending half of a server response stream.
358pub struct ResponseSink<T> {
359    sender: Box<dyn Send<T>>,
360}
361impl<T> ResponseSink<T> {
362    send_methods!(T, sender);
363    /// Attempts completion without waiting or consuming trailers on backpressure.
364    /// # Errors
365    /// Returns pending, a terminal error or an already-finished error.
366    pub fn try_finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()> {
367        self.sender.finish(status, trailers)
368    }
369    /// Sends final status and trailers, including a trailers-only error response.
370    /// # Errors
371    /// Returns a terminal failure or rejects an already finished RPC.
372    pub fn finish(&mut self, status: Status, trailers: Metadata) -> Result<()> {
373        blocking(self.sender.as_mut(), |sender| {
374            sender.finish(&status, &trailers)
375        })
376    }
377    control_methods!(sender);
378}
379/// Creates server halves sharing a driver; only the last unfinished half's drop cancels.
380pub fn server_streams<D: StreamDriver + 'static>(
381    driver: D,
382) -> (RequestStream<D::Receive>, ResponseSink<D::Send>) {
383    let state = shared(driver, false, false);
384    (
385        RequestStream(ServerStreamingCall {
386            receiver: Box::new(Handle(Rc::clone(&state))),
387        }),
388        ResponseSink {
389            sender: Box::new(Handle(state)),
390        },
391    )
392}
393/// Independent request and response directions for a bidirectional client call.
394pub struct BidiStreamingCall<Req, Resp> {
395    incoming: ServerStreamingCall<Resp>,
396    outgoing: ResponseSink<Req>,
397}
398impl<Req: 'static, Resp: 'static> BidiStreamingCall<Req, Resp> {
399    pub fn new<D: StreamDriver<Send = Req, Receive = Resp> + 'static>(driver: D) -> Self {
400        let state = shared(driver, true, false);
401        Self {
402            incoming: ServerStreamingCall {
403                receiver: Box::new(Handle(Rc::clone(&state))),
404            },
405            outgoing: ResponseSink {
406                sender: Box::new(Handle(state)),
407            },
408        }
409    }
410    send_methods!(Req, outgoing.sender);
411    close_methods!(outgoing.sender);
412    /// Receives the next response without blocking.
413    /// # Errors
414    /// Returns pending or sticky terminal failure.
415    pub fn try_recv_next(&mut self) -> Result<Option<Resp>> {
416        self.incoming.try_recv_next()
417    }
418    /// Waits for the next response.
419    /// # Errors
420    /// Returns terminal failure.
421    pub fn recv_next(&mut self) -> Result<Option<Resp>> {
422        self.incoming.recv_next()
423    }
424    /// Half-closes requests and returns all remaining responses through completion.
425    /// # Errors
426    /// Returns terminal failure.
427    pub fn finish(&mut self) -> Result<Vec<Resp>> {
428        self.half_close()?;
429        self.incoming.finish()
430    }
431    control_methods!(incoming.receiver);
432}
433/// Client-streaming requests with exactly one response after successful completion.
434pub struct ClientStreamingCall<Req, Resp> {
435    call: BidiStreamingCall<Req, Resp>,
436    response: Option<Resp>,
437    delivered: bool,
438}
439impl<Req: 'static, Resp: 'static> ClientStreamingCall<Req, Resp> {
440    pub fn new<D: StreamDriver<Send = Req, Receive = Resp> + 'static>(driver: D) -> Self {
441        Self {
442            call: BidiStreamingCall::new(driver),
443            response: None,
444            delivered: false,
445        }
446    }
447    send_methods!(Req, call.outgoing.sender);
448    close_methods!(call.outgoing.sender);
449    /// Advances completion by at most two receive steps, preserving a pending response.
450    /// # Errors
451    /// Returns pending, terminal error, or response cardinality failure.
452    pub fn try_finish(&mut self) -> Result<Resp> {
453        if self.delivered {
454            return Err(invalid("response already delivered"));
455        }
456        let result = self.poll_finish();
457        if let Err(error) = &result
458            && *error != StreamError::WouldBlock
459        {
460            self.call.incoming.receiver.fail(error.clone())?;
461        }
462        result
463    }
464    fn poll_finish(&mut self) -> Result<Resp> {
465        self.call.try_half_close()?;
466        if self.response.is_none() {
467            match self.call.try_recv_next()? {
468                Some(message) => self.response = Some(message),
469                None => return Err(Status::internal("missing client-streaming response").into()),
470            }
471        }
472        match self.call.try_recv_next()? {
473            Some(_) => Err(Status::internal("multiple client-streaming responses").into()),
474            None => {
475                self.delivered = true;
476                self.response
477                    .take()
478                    .ok_or_else(|| Status::internal("missing client-streaming response").into())
479            }
480        }
481    }
482    /// Polls the single response through validated final status.
483    /// # Errors
484    /// Returns the same pending or terminal errors as [`Self::try_finish`].
485    pub fn try_recv_next(&mut self) -> Result<Option<Resp>> {
486        (!self.delivered).then(|| self.try_finish()).transpose()
487    }
488    /// Waits for the single response, then returns EOF on subsequent reads.
489    /// # Errors
490    /// Returns the terminal errors from [`Self::finish`].
491    pub fn recv_next(&mut self) -> Result<Option<Resp>> {
492        (!self.delivered).then(|| self.finish()).transpose()
493    }
494    /// Waits for exactly one response and a successful final status.
495    /// # Errors
496    /// Returns terminal failure or response cardinality failure.
497    pub fn finish(&mut self) -> Result<Resp> {
498        loop {
499            match self.try_finish() {
500                Err(StreamError::WouldBlock) => self.call.incoming.receiver.wait()?,
501                result => return result,
502            }
503        }
504    }
505    control_methods!(call.incoming.receiver);
506}
507#[cfg(test)]
508mod unit_lifecycle_scenario {
509    use std::collections::VecDeque;
510
511    use super::*;
512    type TestResult = std::result::Result<(), Box<dyn std::error::Error>>;
513    #[derive(Default)]
514    struct Journal {
515        ops: Vec<&'static str>,
516        accepted: Vec<i32>,
517        finished: Vec<(Status, Metadata)>,
518    }
519    struct Script {
520        incoming: VecDeque<Result<Option<i32>>>,
521        sends: VecDeque<Result<()>>,
522        closes: VecDeque<Result<()>>,
523        finishes: VecDeque<Result<()>>,
524        waits: VecDeque<Result<()>>,
525        initial: Metadata,
526        trailers: Option<Metadata>,
527        send_trailers: bool,
528        log: Rc<RefCell<Journal>>,
529    }
530    impl Script {
531        fn new(events: Vec<Result<Option<i32>>>) -> (Self, Rc<RefCell<Journal>>) {
532            let log = Rc::new(RefCell::new(Journal::default()));
533            (
534                Self {
535                    incoming: events.into(),
536                    sends: VecDeque::new(),
537                    closes: VecDeque::new(),
538                    finishes: VecDeque::new(),
539                    waits: VecDeque::new(),
540                    initial: Metadata::new(),
541                    trailers: None,
542                    send_trailers: true,
543                    log: Rc::clone(&log),
544                },
545                log,
546            )
547        }
548        fn attempt(queue: &mut VecDeque<Result<()>>) -> Result<()> {
549            queue.pop_front().transpose().map(|_| ())
550        }
551        fn record(&self, operation: &'static str) {
552            self.log.borrow_mut().ops.push(operation);
553        }
554    }
555    impl StreamDriver for Script {
556        type Send = i32;
557        type Receive = i32;
558        fn send(&mut self, value: &i32) -> Result<()> {
559            self.record("send");
560            Self::attempt(&mut self.sends)?;
561            self.log.borrow_mut().accepted.push(*value);
562            Ok(())
563        }
564        fn half_close(&mut self) -> Result<()> {
565            self.record("close");
566            Self::attempt(&mut self.closes)
567        }
568        fn try_recv_next(&mut self) -> Result<Option<i32>> {
569            self.record("recv");
570            let result = self
571                .incoming
572                .pop_front()
573                .ok_or_else(|| invalid("script exhausted"))?;
574            if self.send_trailers && matches!(&result, Ok(None) | Err(StreamError::Status(_))) {
575                self.trailers = Some(Metadata::new());
576            }
577            result
578        }
579        fn wait_ready(&mut self) -> Result<()> {
580            self.record("wait");
581            Self::attempt(&mut self.waits)
582        }
583        fn finish(&mut self, status: &Status, trailers: &Metadata) -> Result<()> {
584            self.record("finish");
585            Self::attempt(&mut self.finishes)?;
586            self.log
587                .borrow_mut()
588                .finished
589                .push((status.clone(), trailers.clone()));
590            Ok(())
591        }
592        fn initial_metadata(&self) -> Option<&Metadata> {
593            Some(&self.initial)
594        }
595        fn trailing_metadata(&self) -> Option<&Metadata> {
596            self.trailers.as_ref()
597        }
598        fn cancel(&mut self) {
599            self.record("cancel");
600        }
601    }
602    #[test]
603    fn server_stream_pending_metadata_and_completion() -> TestResult {
604        let (mut driver, log) =
605            Script::new(vec![Err(StreamError::WouldBlock), Ok(Some(7)), Ok(None)]);
606        driver.initial.append_ascii("tag", "a")?;
607        driver.initial.append_ascii("tag", "b")?;
608        driver.initial.append_binary("raw-bin", &[0, 255])?;
609        let initial = driver.initial.clone();
610        let mut call = ServerStreamingCall::new(driver);
611        assert_eq!(call.try_recv_next(), Err(StreamError::WouldBlock));
612        assert_eq!(log.borrow().ops, ["recv"]);
613        assert_eq!(call.initial_metadata()?, Some(initial.clone()));
614        assert_eq!(call.trailing_metadata()?, None);
615        assert_eq!(call.recv_next()?, Some(7));
616        assert_eq!(call.recv_next()?, None);
617        assert_eq!(call.try_recv_next()?, None);
618        assert_eq!(call.initial_metadata()?, Some(initial));
619        assert_eq!(call.trailing_metadata()?, Some(Metadata::new()));
620        drop(call);
621        assert_eq!(log.borrow().ops, ["recv", "recv", "recv"]);
622        Ok(())
623    }
624    #[test]
625    fn blocking_receive_waits_and_failure_is_sticky() -> TestResult {
626        let failure = StreamError::from(Status::unavailable("offline"));
627        let (driver, log) = Script::new(vec![
628            Err(StreamError::WouldBlock),
629            Ok(Some(3)),
630            Err(failure.clone()),
631            Ok(Some(9)),
632        ]);
633        let mut call = ServerStreamingCall::new(driver);
634        assert_eq!(call.recv_next()?, Some(3));
635        assert_eq!(log.borrow().ops, ["recv", "wait", "recv"]);
636        assert_eq!(call.recv_next(), Err(failure.clone()));
637        assert_eq!(call.try_recv_next(), Err(failure));
638        assert_eq!(call.trailing_metadata()?, Some(Metadata::new()));
639        call.cancel()?;
640        drop(call);
641        assert_eq!(log.borrow().ops, ["recv", "wait", "recv", "recv", "cancel"]);
642        Ok(())
643    }
644    #[test]
645    fn client_response_waits_for_status_and_enforces_cardinality() -> TestResult {
646        let (driver, log) = Script::new(vec![Ok(Some(8)), Err(StreamError::WouldBlock), Ok(None)]);
647        let mut call = ClientStreamingCall::new(driver);
648        assert_eq!(call.try_recv_next(), Err(StreamError::WouldBlock));
649        assert_eq!(call.recv_next()?, Some(8));
650        assert_eq!(call.try_recv_next()?, None);
651        assert!(call.try_finish().is_err());
652        drop(call);
653        assert_eq!(log.borrow().ops, ["close", "recv", "recv", "recv"]);
654        for events in [
655            vec![Ok(None)],
656            vec![Ok(Some(1)), Ok(Some(2))],
657            vec![Ok(Some(1)), Err(Status::unavailable("late status").into())],
658        ] {
659            let (driver, _) = Script::new(events);
660            let mut call = ClientStreamingCall::new(driver);
661            let first = call.try_finish();
662            assert!(matches!(first, Err(StreamError::Status(_))));
663            assert_eq!(call.try_finish(), first);
664            assert_eq!(call.try_send(&9).err(), first.clone().err());
665            assert_eq!(call.try_half_close().err(), first.err());
666        }
667        Ok(())
668    }
669    #[test]
670    fn blocking_client_finish_waits_only_for_pending_io() -> TestResult {
671        let (mut driver, log) =
672            Script::new(vec![Err(StreamError::WouldBlock), Ok(Some(4)), Ok(None)]);
673        driver.closes.push_back(Err(StreamError::WouldBlock));
674        let mut call = ClientStreamingCall::new(driver);
675        call.send(&1)?;
676        assert_eq!(call.finish()?, 4);
677        assert_eq!(log.borrow().accepted, [1]);
678        assert_eq!(
679            log.borrow().ops.join(","),
680            "send,close,wait,close,recv,wait,recv,recv"
681        );
682        Ok(())
683    }
684    #[test]
685    fn bidi_backpressure_half_close_preserves_responses() -> TestResult {
686        let (mut driver, log) = Script::new(vec![Ok(Some(5)), Ok(Some(6)), Ok(None)]);
687        driver.sends = vec![Err(StreamError::WouldBlock); 2].into();
688        driver.sends.push_back(Ok(()));
689        driver.closes = vec![Err(StreamError::WouldBlock), Ok(())].into();
690        let mut call = BidiStreamingCall::new(driver);
691        assert_eq!(call.try_send(&4), Err(StreamError::WouldBlock));
692        assert!(log.borrow().accepted.is_empty());
693        assert_eq!(call.recv_next()?, Some(5));
694        call.send(&4)?;
695        assert_eq!(call.try_half_close(), Err(StreamError::WouldBlock));
696        call.half_close()?;
697        call.half_close()?;
698        assert!(call.try_send(&99).is_err());
699        assert_eq!(call.finish()?, vec![6]);
700        drop(call);
701        assert_eq!(log.borrow().accepted, [4]);
702        assert_eq!(
703            log.borrow().ops.join(","),
704            "send,recv,send,wait,send,close,close,recv,recv"
705        );
706        let (driver, log) = Script::new(vec![Ok(None)]);
707        let mut call = BidiStreamingCall::new(driver);
708        assert_eq!(call.try_recv_next()?, None);
709        drop(call);
710        assert_eq!(log.borrow().ops, ["recv", "cancel"]);
711        Ok(())
712    }
713    #[test]
714    fn server_halves_finish_and_last_drop_control_lifetime() -> TestResult {
715        let (mut driver, log) = Script::new(vec![Ok(None)]);
716        driver.finishes = vec![Err(StreamError::WouldBlock); 2].into();
717        driver.finishes.push_back(Ok(()));
718        let (mut requests, mut responses) = server_streams(driver);
719        assert_eq!(requests.try_recv_next()?, None);
720        drop(requests);
721        responses.send(&2)?;
722        let status = Status::permission_denied("denied");
723        let mut trailers = Metadata::new();
724        trailers.append_ascii("reason", "policy")?;
725        assert_eq!(
726            responses.try_finish(&status, &trailers),
727            Err(StreamError::WouldBlock)
728        );
729        responses.finish(status.clone(), trailers.clone())?;
730        assert!(responses.try_send(&3).is_err());
731        assert!(responses.finish(Status::ok(""), Metadata::new()).is_err());
732        drop(responses);
733        assert_eq!(log.borrow().finished, [(status, trailers)]);
734        assert_eq!(
735            log.borrow().ops,
736            ["recv", "send", "finish", "finish", "wait", "finish"]
737        );
738        let (driver, log) = Script::new(vec![Ok(None)]);
739        let mut requests = RequestStream::new(driver);
740        assert_eq!(requests.recv_next()?, None);
741        drop(requests);
742        assert_eq!(log.borrow().ops, ["recv", "cancel"]);
743        let (driver, log) = Script::new(vec![]);
744        let (requests, responses) = server_streams(driver);
745        drop(responses);
746        assert!(log.borrow().ops.is_empty());
747        drop(requests);
748        assert_eq!(log.borrow().ops, ["cancel"]);
749        Ok(())
750    }
751    #[test]
752    fn cancellation_and_invalid_wait_are_terminal() -> TestResult {
753        let (driver, log) = Script::new(vec![Ok(Some(1))]);
754        let mut call = BidiStreamingCall::new(driver);
755        call.half_close()?;
756        call.cancel()?;
757        call.cancel()?;
758        assert!(call.try_send(&1).is_err());
759        assert!(call.try_recv_next().is_err());
760        assert!(call.initial_metadata()?.is_some());
761        drop(call);
762        assert_eq!(log.borrow().ops, ["close", "cancel"]);
763        let (mut driver, log) = Script::new(vec![Ok(None), Ok(Some(9))]);
764        driver.send_trailers = false;
765        let mut call = ServerStreamingCall::new(driver);
766        let failure = call.recv_next();
767        assert!(
768            matches!(&failure, Err(StreamError::Status(s)) if s.code() == grpc_core::Code::Unknown)
769        );
770        assert_eq!(call.try_recv_next(), failure);
771        drop(call);
772        assert_eq!(log.borrow().ops, ["recv", "cancel"]);
773        let (mut driver, log) = Script::new(vec![Err(StreamError::WouldBlock)]);
774        driver.waits.push_back(Err(StreamError::WouldBlock));
775        let mut call = ServerStreamingCall::new(driver);
776        assert!(matches!(call.recv_next(), Err(StreamError::Status(_))));
777        drop(call);
778        assert_eq!(log.borrow().ops, ["recv", "wait", "cancel"]);
779        Ok(())
780    }
781}