     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39

    use core::pin::Pin;

    use pin_project_lite::pin_project;

    pin_project! {
        /// UnfoldState used for stream and sink unfolds
        #[project = UnfoldStateProj]
        #[project_replace = UnfoldStateProjReplace]
        #[derive(Debug)]
        pub(crate) enum UnfoldState<T, R> {
            Value {
                value: T,
            },
            Future {
                #[pin]
                future: R,
            },
            Empty,
        }
    }

    impl<T, R> UnfoldState<T, R> {
        pub(crate) fn project_future(self: Pin<&mut Self>) -> Option<Pin<&mut R>> {
            match self.project() {
                UnfoldStateProj::Future { future } => Some(future),
                _ => None,
            }
        }

        pub(crate) fn take_value(self: Pin<&mut Self>) -> Option<T> {
            match &*self {
                UnfoldState::Value { .. } => match self.project_replace(UnfoldState::Empty) {
                    UnfoldStateProjReplace::Value { value } => Some(value),
                    _ => unreachable!(),
                },
                _ => None,
            }
        }
    }