translation_api_cn/tencent/
response.rs1use serde::Deserialize;
2use std::borrow::Cow;
3
4#[derive(Debug, Deserialize)]
5pub struct Response<'r> {
6 #[serde(borrow)]
7 #[serde(rename = "Response")]
8 pub res: ResponseInner<'r>,
9}
10
11impl<'r> Response<'r> {
12 pub fn dst(&self) -> Result<impl Iterator<Item = &str>, ResponseError> {
14 match &self.res {
15 ResponseInner::Ok { res, .. } => Ok(res.iter().map(|s| s.as_ref())),
16 ResponseInner::Err { error, .. } => Err(error.clone()),
17 }
18 }
19
20 pub fn dst_owned(self) -> Result<Vec<String>, ResponseError> {
22 match self.res {
23 ResponseInner::Ok { res, .. } => Ok(res.into_iter().map(|x| x.into()).collect()),
24 ResponseInner::Err { error, .. } => Err(error),
25 }
26 }
27
28 pub fn is_borrowed(&self) -> Option<bool> {
30 match &self.res {
31 ResponseInner::Ok { res, .. } if !res.is_empty() => {
32 Some(matches!(res[0], Cow::Borrowed(_)))
33 }
34 _ => None,
35 }
36 }
37}
38
39#[derive(Debug, Deserialize)]
41#[serde(untagged)]
42pub enum ResponseInner<'r> {
43 Ok {
44 #[serde(rename = "RequestId")]
45 id: &'r str,
46 #[serde(rename = "Source")]
47 from: &'r str,
48 #[serde(rename = "Target")]
49 to: &'r str,
50 #[serde(borrow)]
51 #[serde(rename = "TargetTextList")]
52 res: Vec<Cow<'r, str>>,
53 },
54 Err {
55 #[serde(rename = "RequestId")]
56 id: &'r str,
57 #[serde(rename = "Error")]
58 error: ResponseError,
59 },
60}
61
62#[derive(Debug, Clone, Deserialize)]
69pub struct ResponseError {
70 #[serde(rename = "Code")]
71 pub code: String,
72 #[serde(rename = "Message")]
73 pub msg: String,
74}
75
76impl std::error::Error for ResponseError {}
77impl std::fmt::Display for ResponseError {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 write!(f,
80 "错误码:`{}`\n错误信息:`{}`\n错误含义:{}\n以上内容由腾讯云 API 返回",
81 self.code,
82 self.msg,
83 self.solution())
84 }
85}
86
87impl ResponseError {
88 pub fn solution(&self) -> &str {
90 match self.code.as_bytes() {
91 b"ActionOffline" => "接口已下线。",
92 b"AuthFailure.InvalidAuthorization" => "请求头部的 Authorization 不符合腾讯云标准。",
93 b"AuthFailure.InvalidSecretId" => "密钥非法(不是云 API 密钥类型)。",
94 b"AuthFailure.MFAFailure" => {
95 "[MFA](https://cloud.tencent.com/document/product/378/12036) 错误。"
96 }
97 b"AuthFailure.SecretIdNotFound" => {
98 "密钥不存在。请在控制台检查密钥是否已被删除或者禁用,如状态正常,\
99 请检查密钥是否填写正确,注意前后不得有空格。"
100 }
101 b"AuthFailure.SignatureExpire" => {
102 "签名过期。Timestamp \
103 和服务器时间相差不得超过五分钟,请检查本地时间是否和标准时间同步。"
104 }
105 b"AuthFailure.SignatureFailure" => {
106 "签名错误。签名计算错误,请对照调用方式中的签名方法文档检查签名计算过程。"
107 }
108 b"AuthFailure.TokenFailure" => "token 错误。",
109 b"AuthFailure.UnauthorizedOperation" => "请求未授权。请参考",
110 b"DryRunOperation" => "DryRun 操作,代表请求将会是成功的,只是多传了 DryRun 参数。",
111 b"FailedOperation" => "操作失败。",
112 b"InternalError" => "内部错误。",
113 b"InvalidAction" => "接口不存在。",
114 b"InvalidParameter" => "参数错误(包括参数格式、类型等错误)。",
115 b"InvalidParameterValue" => "参数取值错误。",
116 b"InvalidRequest" => "请求 body 的 multipart 格式错误。",
117 b"IpInBlacklist" => "IP地址在黑名单中。",
118 b"IpNotInWhitelist" => "IP地址不在白名单中。",
119 b"LimitExceeded" => "超过配额限制。",
120 b"MissingParameter" => "缺少参数。",
121 b"NoSuchProduct" => "产品不存在",
122 b"NoSuchVersion" => "接口版本不存在。",
123 b"RequestLimitExceeded" => "请求的次数超过了频率限制。",
124 b"RequestLimitExceeded.GlobalRegionUinLimitExceeded" => "主账号超过频率限制。",
125 b"RequestLimitExceeded.IPLimitExceeded" => "IP限频。",
126 b"RequestLimitExceeded.UinLimitExceeded" => "主账号限频。",
127 b"RequestSizeLimitExceeded" => "请求包超过限制大小。",
128 b"ResourceInUse" => "资源被占用。",
129 b"ResourceInsufficient" => "资源不足。",
130 b"ResourceNotFound" => "资源不存在。",
131 b"ResourceUnavailable" => "资源不可用。",
132 b"ResponseSizeLimitExceeded" => "返回包超过限制大小。",
133 b"ServiceUnavailable" => "当前服务暂时不可用。",
134 b"UnauthorizedOperation" => "未授权操作。",
135 b"UnknownParameter" => "未知参数错误,用户多传未定义的参数会导致错误。",
136 b"UnsupportedOperation" => "操作不支持。",
137 b"UnsupportedProtocol" => "http(s) 请求协议错误,只支持 GET 和 POST 请求。",
138 b"UnsupportedRegion" => "接口不支持所传地域。",
139 b"FailedOperation.NoFreeAmount" => {
140 "本月免费额度已用完,如需继续使用您可以在机器翻译控制台升级为付费使用。"
141 }
142 b"FailedOperation.ServiceIsolate" => "账号因为欠费停止服务,请在腾讯云账户充值。",
143 b"FailedOperation.UserNotRegistered" => {
144 "服务未开通,请在腾讯云官网机器翻译控制台开通服务。"
145 }
146 b"InternalError.BackendTimeout" => "后台服务超时,请稍后重试。",
147 b"InternalError.ErrorUnknown" => "未知错误。",
148 b"InternalError.RequestFailed" => "请求失败。",
149 b"InvalidParameter.DuplicatedSessionIdAndSeq" => "重复的SessionUuid和Seq组合。",
150 b"InvalidParameter.MissingParameter" => "参数错误。",
151 b"InvalidParameter.SeqIntervalTooLarge" => "Seq之间的间隙请不要大于2000。",
152 b"LimitExceeded.LimitedAccessFrequency" => "超出请求频率。",
153 b"UnauthorizedOperation.ActionNotFound" => "请填写正确的Action字段名称。",
154 b"UnsupportedOperation.AudioDurationExceed" => {
155 "音频分片长度超过限制,请保证分片长度小于8s。"
156 }
157 b"UnsupportedOperation.TextTooLong" => {
158 "单次请求text超过长度限制,请保证单次请求长度低于2000。"
159 }
160 b"UnsupportedOperation.UnSupportedTargetLanguage" => {
161 "不支持的目标语言,请参照语言列表。"
162 }
163 b"UnsupportedOperation.UnsupportedLanguage" => "不支持的语言,请参照语言列表。",
164 b"UnsupportedOperation.UnsupportedSourceLanguage" => "不支持的源语言,请参照语言列表。",
165 _ => "未知错误。",
166 }
167 }
168}
169
170#[test]
171fn response_test() -> Result<(), Box<dyn std::error::Error>> {
172 let success = r#"{"Response":{"RequestId":"7895050c-b0bd-45f2-ba88-c95c509020f2","Source":"en","Target":"zh","TargetTextList":["嗨","那里"]}}"#;
173 let res: Response = serde_json::from_str(success)?;
174 assert_eq!(format!("{res:?}"),
175 "Response { res: Ok { id: \"7895050c-b0bd-45f2-ba88-c95c509020f2\", from: \"en\", \
176 to: \"zh\", res: [\"嗨\", \"那里\"] } }");
177 assert!(res.dst().is_ok());
178 assert_eq!(&res.dst()?.collect::<Vec<_>>(), &["嗨", "那里"]);
179
180 let error = r#"{"Response":{"Error":{"Code":"AuthFailure.SignatureFailure","Message":"The provided credentials could not be validated. Please check your signature is correct."},"RequestId":"47546ee3-767c-4671-8f90-2c02c7484a42"}}"#;
181 let res: Response = serde_json::from_str(error)?;
182 #[rustfmt::skip]
183 assert_eq!(
184 format!("{res:?}"),
185 "Response { res: Err { id: \"47546ee3-767c-4671-8f90-2c02c7484a42\", \
186 error: ResponseError { code: \"AuthFailure.SignatureFailure\", \
187 msg: \"The provided credentials could not be validated. \
188 Please check your signature is correct.\" } } }"
189 );
190 assert!(res.dst().is_err());
191 #[rustfmt::skip]
194 let error = "{\"Response\":{\"Error\":{\"Code\":\"AuthFailure.SecretIdNotFound\",\"Message\":\
195 \"The SecretId is not found, please ensure that your SecretId is \
196 correct.\"},\"RequestId\":\"c3d29f67-6e56-48b9-b583-2cfcde32cad1\"}}";
197 let res: Response = serde_json::from_str(error)?;
198 #[rustfmt::skip]
199 assert_eq!(
200 format!("{res:?}"),
201 "Response { res: Err { id: \"c3d29f67-6e56-48b9-b583-2cfcde32cad1\", \
202 error: ResponseError { code: \"AuthFailure.SecretIdNotFound\", \
203 msg: \"The SecretId is not found, please ensure that your SecretId is correct.\" } } }"
204 );
205 assert!(res.dst().is_err());
206 Ok(())
209}