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