origincloud_core/longrunning/
mod.rs1mod generated;
25
26pub use generated::*;
27
28use serde::{Deserialize, Serialize};
29
30use crate::rpc::{Any, Status};
31
32#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
35#[serde(from = "Wire", into = "Wire")]
36pub struct Operation {
37 pub name: String,
40 pub metadata: Option<Any>,
43 pub done: bool,
45 pub result: Option<OperationResult>,
47}
48
49#[derive(Clone, Debug, PartialEq)]
51pub enum OperationResult {
52 Error(Status),
54 Response(Any),
57}
58
59#[derive(Default, Serialize, Deserialize)]
61#[serde(default, rename_all = "camelCase")]
62struct Wire {
63 #[serde(skip_serializing_if = "String::is_empty")]
64 name: String,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 metadata: Option<Any>,
67 #[serde(skip_serializing_if = "std::ops::Not::not")]
68 done: bool,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 error: Option<Status>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 response: Option<Any>,
73}
74
75impl From<Wire> for Operation {
76 fn from(w: Wire) -> Self {
77 let result = match (w.error, w.response) {
78 (Some(error), _) => Some(OperationResult::Error(error)),
79 (None, Some(response)) => Some(OperationResult::Response(response)),
80 (None, None) => None,
81 };
82 Self {
83 name: w.name,
84 metadata: w.metadata,
85 done: w.done,
86 result,
87 }
88 }
89}
90
91impl From<Operation> for Wire {
92 fn from(o: Operation) -> Self {
93 let (error, response) = match o.result {
94 Some(OperationResult::Error(e)) => (Some(e), None),
95 Some(OperationResult::Response(r)) => (None, Some(r)),
96 None => (None, None),
97 };
98 Self {
99 name: o.name,
100 metadata: o.metadata,
101 done: o.done,
102 error,
103 response,
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn an_operation_reads_its_result() {
114 let done: Operation = serde_json::from_str(
115 r#"{"name":"projects/p/zones/z/operations/op-1","done":true,"response":{"@type":"type.googleapis.com/x.Y","name":"n"},"unknown":1}"#,
116 )
117 .unwrap();
118 assert!(done.done);
119 let Some(OperationResult::Response(any)) = &done.result else {
120 panic!("{done:?}");
121 };
122 assert_eq!(any.type_name(), "x.Y");
123 let again: Operation =
124 serde_json::from_str(&serde_json::to_string(&done).unwrap()).unwrap();
125 assert_eq!(again, done);
126
127 let running: Operation = serde_json::from_str(r#"{"name":"n"}"#).unwrap();
128 assert!(!running.done && running.result.is_none());
129 }
130}