cosmwasm_std/results/
contract_result.rs1use core::fmt;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
35#[serde(rename_all = "snake_case")]
36pub enum ContractResult<S> {
37 Ok(S),
38 #[serde(rename = "error")]
41 Err(String),
42}
43
44impl<S> ContractResult<S> {
47 pub fn into_result(self) -> Result<S, String> {
50 Result::<S, String>::from(self)
51 }
52
53 pub fn unwrap(self) -> S {
54 self.into_result().unwrap()
55 }
56
57 pub fn is_ok(&self) -> bool {
58 matches!(self, ContractResult::Ok(_))
59 }
60
61 pub fn is_err(&self) -> bool {
62 matches!(self, ContractResult::Err(_))
63 }
64}
65
66impl<S: fmt::Debug> ContractResult<S> {
67 pub fn unwrap_err(self) -> String {
68 self.into_result().unwrap_err()
69 }
70}
71
72impl<S, E: ToString> From<Result<S, E>> for ContractResult<S> {
73 fn from(original: Result<S, E>) -> ContractResult<S> {
74 match original {
75 Ok(value) => ContractResult::Ok(value),
76 Err(err) => ContractResult::Err(err.to_string()),
77 }
78 }
79}
80
81impl<S> From<ContractResult<S>> for Result<S, String> {
82 fn from(original: ContractResult<S>) -> Result<S, String> {
83 match original {
84 ContractResult::Ok(value) => Ok(value),
85 ContractResult::Err(err) => Err(err),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::{from_json, to_json_vec, Response, StdError, StdResult};
94
95 #[test]
96 fn contract_result_serialization_works() {
97 let result = ContractResult::Ok(12);
98 assert_eq!(&to_json_vec(&result).unwrap(), b"{\"ok\":12}");
99
100 let result = ContractResult::Ok("foo");
101 assert_eq!(&to_json_vec(&result).unwrap(), b"{\"ok\":\"foo\"}");
102
103 let result: ContractResult<Response> = ContractResult::Ok(Response::default());
104 assert_eq!(
105 to_json_vec(&result).unwrap(),
106 br#"{"ok":{"messages":[],"attributes":[],"events":[],"data":null}}"#
107 );
108
109 let result: ContractResult<Response> = ContractResult::Err("broken".to_string());
110 assert_eq!(&to_json_vec(&result).unwrap(), b"{\"error\":\"broken\"}");
111 }
112
113 #[test]
114 fn contract_result_deserialization_works() {
115 let result: ContractResult<u64> = from_json(br#"{"ok":12}"#).unwrap();
116 assert_eq!(result, ContractResult::Ok(12));
117
118 let result: ContractResult<String> = from_json(br#"{"ok":"foo"}"#).unwrap();
119 assert_eq!(result, ContractResult::Ok("foo".to_string()));
120
121 let result: ContractResult<Response> =
122 from_json(br#"{"ok":{"messages":[],"attributes":[],"events":[],"data":null}}"#)
123 .unwrap();
124 assert_eq!(result, ContractResult::Ok(Response::default()));
125
126 let result: ContractResult<Response> = from_json(br#"{"error":"broken"}"#).unwrap();
127 assert_eq!(result, ContractResult::Err("broken".to_string()));
128
129 let result: ContractResult<u64> = from_json(b" {\n\t \"ok\": 5898\n} ").unwrap();
131 assert_eq!(result, ContractResult::Ok(5898));
132
133 let parse: StdResult<ContractResult<u64>> = from_json(br#"{"unrelated":321,"ok":4554}"#);
135 match parse.unwrap_err() {
136 StdError::ParseErr { .. } => {}
137 err => panic!("Unexpected error: {err:?}"),
138 }
139 let parse: StdResult<ContractResult<u64>> = from_json(br#"{"ok":4554,"unrelated":321}"#);
140 match parse.unwrap_err() {
141 StdError::ParseErr { .. } => {}
142 err => panic!("Unexpected error: {err:?}"),
143 }
144 let parse: StdResult<ContractResult<u64>> =
145 from_json(br#"{"ok":4554,"error":"What's up now?"}"#);
146 match parse.unwrap_err() {
147 StdError::ParseErr { .. } => {}
148 err => panic!("Unexpected error: {err:?}"),
149 }
150 }
151
152 #[test]
153 fn can_convert_from_core_result() {
154 let original: Result<Response, StdError> = Ok(Response::default());
155 let converted: ContractResult<Response> = original.into();
156 assert_eq!(converted, ContractResult::Ok(Response::default()));
157
158 let original: Result<Response, StdError> = Err(StdError::generic_err("broken"));
159 let converted: ContractResult<Response> = original.into();
160 assert_eq!(
161 converted,
162 ContractResult::Err("Generic error: broken".to_string())
163 );
164 }
165
166 #[test]
167 fn can_convert_to_core_result() {
168 let original = ContractResult::Ok(Response::default());
169 let converted: Result<Response, String> = original.into();
170 assert_eq!(converted, Ok(Response::default()));
171
172 let original = ContractResult::Err("went wrong".to_string());
173 let converted: Result<Response, String> = original.into();
174 assert_eq!(converted, Err("went wrong".to_string()));
175 }
176}