sayiir_core/
loop_result.rs1use crate::codec::LoopDecision;
8
9#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
30#[serde(tag = "_loop", content = "value")]
31#[cfg_attr(
32 feature = "rkyv",
33 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
34)]
35pub enum LoopResult<T> {
36 #[serde(rename = "again")]
38 Again(T),
39 #[serde(rename = "done")]
41 Done(T),
42}
43
44pub trait LoopOutput {
57 type Inner;
59}
60
61impl<T> LoopOutput for LoopResult<T> {
62 type Inner = T;
63}
64
65impl<T> LoopResult<T> {
66 #[must_use]
68 pub fn is_done(&self) -> bool {
69 matches!(self, Self::Done(_))
70 }
71
72 #[must_use]
74 pub fn is_again(&self) -> bool {
75 matches!(self, Self::Again(_))
76 }
77
78 #[must_use]
80 pub fn into_inner(self) -> T {
81 match self {
82 Self::Again(v) | Self::Done(v) => v,
83 }
84 }
85
86 #[must_use]
88 pub fn into_decision(self) -> (LoopDecision, T) {
89 match self {
90 Self::Again(v) => (LoopDecision::Again, v),
91 Self::Done(v) => (LoopDecision::Done, v),
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn done_is_done() {
102 let r = LoopResult::Done(42);
103 assert!(r.is_done());
104 assert!(!r.is_again());
105 }
106
107 #[test]
108 fn again_is_again() {
109 let r = LoopResult::Again(42);
110 assert!(r.is_again());
111 assert!(!r.is_done());
112 }
113
114 #[test]
115 fn into_inner_done() {
116 assert_eq!(LoopResult::Done("hello").into_inner(), "hello");
117 }
118
119 #[test]
120 fn into_inner_again() {
121 assert_eq!(LoopResult::Again(99).into_inner(), 99);
122 }
123
124 #[test]
125 fn into_decision_done() {
126 let (decision, val) = LoopResult::Done(10).into_decision();
127 assert_eq!(decision, LoopDecision::Done);
128 assert_eq!(val, 10);
129 }
130
131 #[test]
132 fn into_decision_again() {
133 let (decision, val) = LoopResult::Again(5).into_decision();
134 assert_eq!(decision, LoopDecision::Again);
135 assert_eq!(val, 5);
136 }
137
138 #[test]
139 fn serde_round_trip_done() {
140 let r = LoopResult::Done(42u32);
141 let json = serde_json::to_string(&r).unwrap();
142 let back: LoopResult<u32> = serde_json::from_str(&json).unwrap();
143 assert!(back.is_done());
144 assert_eq!(back.into_inner(), 42);
145 }
146
147 #[test]
148 fn serde_round_trip_again() {
149 let r = LoopResult::Again("next".to_string());
150 let json = serde_json::to_string(&r).unwrap();
151 let back: LoopResult<String> = serde_json::from_str(&json).unwrap();
152 assert!(back.is_again());
153 assert_eq!(back.into_inner(), "next");
154 }
155}