Skip to main content

openlark_core/
response_handler.rs

1use serde_json::Value;
2use tracing::debug;
3use tracing::{info_span, Instrument};
4
5use crate::{
6    api::{ApiResponseTrait, BaseResponse, RawResponse, Response, ResponseFormat},
7    content_disposition,
8    error::{network_error, validation_error},
9    observability::ResponseTracker,
10    SDKResult,
11};
12use serde::Deserialize;
13use std::any::Any;
14
15#[cfg(test)]
16use crate::error::{CoreError, ErrorCategory, ErrorCode, ErrorContext};
17
18/// 改进的响应处理器,解决双重解析问题
19/// 使用 #[serde(flatten)] 和高级 Serde 特性简化反序列化
20pub struct ImprovedResponseHandler;
21
22impl ImprovedResponseHandler {
23    /// 处理响应的核心方法
24    /// 相比原始实现,这个版本:
25    /// 1. 减少了不必要的JSON解析次数
26    /// 2. 使用更高效的直接反序列化
27    /// 3. 更好的错误处理
28    /// 4. 完整的可观测性支持
29    pub async fn handle_response<T: ApiResponseTrait + for<'de> Deserialize<'de>>(
30        response: reqwest::Response,
31    ) -> SDKResult<Response<T>> {
32        let format = match T::data_format() {
33            ResponseFormat::Data => "data",
34            ResponseFormat::Flatten => "flatten",
35            ResponseFormat::Binary => "binary",
36            ResponseFormat::Text => "text",
37            ResponseFormat::Custom => "custom",
38        };
39
40        let span = info_span!(
41            "response_handling",
42            format = format,
43            status_code = response.status().as_u16(),
44            content_length = tracing::field::Empty,
45            processing_duration_ms = tracing::field::Empty,
46        );
47
48        async move {
49            let start_time = std::time::Instant::now();
50
51            // 获取内容长度用于监控
52            let content_length = response.content_length();
53            if let Some(length) = content_length {
54                tracing::Span::current().record("content_length", length);
55            }
56
57            let result = match T::data_format() {
58                ResponseFormat::Data => Self::handle_data_response(response).await,
59                ResponseFormat::Flatten => Self::handle_flatten_response(response).await,
60                ResponseFormat::Binary => Self::handle_binary_response(response).await,
61                ResponseFormat::Text => Self::handle_data_response(response).await, // 暂时使用data处理器
62                ResponseFormat::Custom => Self::handle_data_response(response).await, // 暂时使用data处理器
63            };
64
65            // 记录处理时间
66            let duration_ms = start_time.elapsed().as_millis() as u64;
67            tracing::Span::current().record("processing_duration_ms", duration_ms);
68
69            result
70        }
71        .instrument(span)
72        .await
73    }
74
75    /// 处理标准数据格式响应
76    /// 使用单次解析而非双重解析,包含详细的可观测性
77    async fn handle_data_response<T: ApiResponseTrait + for<'de> Deserialize<'de>>(
78        response: reqwest::Response,
79    ) -> SDKResult<Response<T>> {
80        let tracker = ResponseTracker::start("json_data", response.content_length());
81
82        let response_text = response.text().await?;
83        debug!("Raw response: {response_text}");
84
85        // 记录解析阶段开始
86        tracker.parsing_complete();
87
88        // 尝试直接解析为BaseResponse<T>
89        match serde_json::from_str::<Response<T>>(&response_text) {
90            Ok(base_response) => {
91                tracker.success();
92                Ok(base_response)
93            }
94            Err(direct_parse_err) => {
95                tracing::debug!("Direct parsing failed, attempting structured data extraction");
96
97                // 解析基础JSON结构
98                match serde_json::from_str::<Value>(&response_text) {
99                    Ok(raw_value) => {
100                        let code = raw_value["code"].as_i64().unwrap_or(-1) as i32;
101                        let msg = raw_value["msg"]
102                            .as_str()
103                            .unwrap_or("Unknown error")
104                            .to_string();
105
106                        // 如果响应成功,尝试提取并解析data字段
107                        let data = if code == 0 {
108                            if let Some(data_value) = raw_value.get("data") {
109                                // 尝试解析为期望的类型T
110                                match serde_json::from_value::<T>(data_value.clone()) {
111                                    Ok(parsed_data) => {
112                                        tracing::debug!("Successfully parsed data field as type T");
113                                        Some(parsed_data)
114                                    }
115                                    Err(data_parse_err) => {
116                                        tracing::debug!(
117                                            "Failed to parse data field as type T: {data_parse_err:?}"
118                                        );
119                                        // 保持 core 通用性:不在这里做“按具体业务类型名”的特殊兼容。
120                                        // 若某个业务 API 存在历史字段差异,请在对应业务 crate 的响应模型上做兼容反序列化。
121                                        None
122                                    }
123                                }
124                            } else {
125                                tracing::debug!("No data field found in successful response");
126                                None
127                            }
128                        } else {
129                            None
130                        };
131
132                        tracker.validation_complete();
133                        tracker.success();
134
135                        Ok(BaseResponse {
136                            raw_response: RawResponse {
137                                code,
138                                msg,
139                                request_id: None,
140                                data: None,
141                                error: None,
142                            },
143                            data,
144                        })
145                    }
146                    Err(fallback_err) => {
147                        let error_msg = format!(
148                            "Failed to parse response. Direct parse error: {}. Fallback parse error: {}",
149                            direct_parse_err, fallback_err
150                        );
151                        tracker.error(&error_msg);
152                        Err(validation_error("api_response", error_msg))
153                    }
154                }
155            }
156        }
157    }
158
159    /// 处理扁平格式响应
160    /// 对于扁平格式,使用自定义反序列化器,包含可观测性支持
161    async fn handle_flatten_response<T: ApiResponseTrait + for<'de> Deserialize<'de>>(
162        response: reqwest::Response,
163    ) -> SDKResult<Response<T>> {
164        let tracker = ResponseTracker::start("json_flatten", response.content_length());
165
166        let response_text = response.text().await?;
167        debug!("Raw response: {response_text}");
168
169        // 解析阶段
170        let raw_value: Value = match serde_json::from_str(&response_text) {
171            Ok(value) => {
172                tracker.parsing_complete();
173                value
174            }
175            Err(e) => {
176                let error_msg = format!("Failed to parse JSON: {}", e);
177                tracker.error(&error_msg);
178                return Err(validation_error("base_response", error_msg));
179            }
180        };
181
182        // 解析原始响应信息
183        let raw_response: RawResponse = match serde_json::from_value(raw_value.clone()) {
184            Ok(response) => response,
185            Err(e) => {
186                let error_msg = format!("Failed to parse raw response: {}", e);
187                tracker.error(&error_msg);
188                return Err(validation_error("response", error_msg));
189            }
190        };
191
192        // 验证和数据解析阶段
193        let data = if raw_response.code == 0 {
194            match serde_json::from_value::<T>(raw_value) {
195                Ok(parsed_data) => {
196                    tracker.validation_complete();
197                    Some(parsed_data)
198                }
199                Err(e) => {
200                    debug!("Failed to parse data for flatten response: {e}");
201                    tracker.validation_complete();
202                    None
203                }
204            }
205        } else {
206            tracker.validation_complete();
207            None
208        };
209
210        tracker.success();
211        Ok(BaseResponse { raw_response, data })
212    }
213
214    /// 处理二进制响应,包含可观测性支持
215    async fn handle_binary_response<T: ApiResponseTrait>(
216        response: reqwest::Response,
217    ) -> SDKResult<Response<T>> {
218        let tracker = ResponseTracker::start("binary", response.content_length());
219
220        // 获取文件名
221        let _file_name = response
222            .headers()
223            .get("Content-Disposition")
224            .and_then(|header| header.to_str().ok())
225            .and_then(content_disposition::extract_filename)
226            .unwrap_or_default();
227
228        // 记录解析阶段完成(文件名提取)
229        tracker.parsing_complete();
230
231        // 获取二进制数据
232        let bytes = match response.bytes().await {
233            Ok(bytes) => {
234                let byte_vec = bytes.to_vec();
235                tracing::debug!("Binary response received: {} bytes", byte_vec.len());
236                byte_vec
237            }
238            Err(e) => {
239                let error_msg = format!("Failed to read binary response: {}", e);
240                tracker.error(&error_msg);
241                return Err(network_error(error_msg));
242            }
243        };
244
245        // 二进制响应:目前仅对 `Vec<u8>` / `String` 做直接承载,其它类型返回 None。
246        // 约定:当业务侧需要二进制内容时,将响应类型定义为 `Vec<u8>`(并使用 ResponseFormat::Binary)。
247        let data: Option<T> = {
248            let any: Box<dyn Any> =
249                if std::any::TypeId::of::<T>() == std::any::TypeId::of::<Vec<u8>>() {
250                    Box::new(bytes)
251                } else if std::any::TypeId::of::<T>() == std::any::TypeId::of::<String>() {
252                    let s = String::from_utf8_lossy(&bytes).to_string();
253                    Box::new(s)
254                } else {
255                    // 其它类型目前不做自动解析
256                    Box::new(())
257                };
258
259            any.downcast::<T>().ok().map(|boxed| *boxed)
260        };
261
262        tracker.success();
263        Ok(BaseResponse {
264            raw_response: RawResponse {
265                code: 0,
266                msg: "success".to_string(),
267                request_id: None,
268                data: None,
269                error: None,
270            },
271            data,
272        })
273    }
274}
275
276/// 优化的BaseResponse,使用更好的serde特性
277///
278/// 注意:该结构目前仅用于单元测试与序列化验证,不参与线上请求链路。
279#[cfg(test)]
280#[derive(Debug, serde::Serialize, serde::Deserialize)]
281pub struct OptimizedBaseResponse<T>
282where
283    T: Default,
284{
285    /// 响应状态码
286    pub code: i32,
287    /// 响应消息
288    pub msg: String,
289    /// 错误信息(可选)
290    #[serde(rename = "error", default, skip_serializing_if = "Option::is_none")]
291    pub error: Option<ErrorInfo>,
292    /// 业务数据(可选)
293    #[serde(default, skip_serializing_if = "Option::is_none")]
294    pub data: Option<T>,
295}
296
297#[cfg(test)]
298impl<T> OptimizedBaseResponse<T>
299where
300    T: Default,
301{
302    /// 检查请求是否成功
303    pub fn is_success(&self) -> bool {
304        self.code == 0
305    }
306
307    /// 获取业务数据,如果请求失败则返回错误
308    pub fn into_data(self) -> Result<T, CoreError> {
309        if self.is_success() {
310            self.data.ok_or_else(|| {
311                validation_error("data", "Response is successful but data is missing")
312            })
313        } else {
314            // 优先使用飞书通用错误码映射
315            let mapped_code = ErrorCode::from_feishu_code(self.code)
316                .unwrap_or_else(|| ErrorCode::from_code(self.code));
317
318            // 将飞书 code 记录到上下文,便于观测与排查
319            let mut ctx = ErrorContext::new();
320            ctx.add_context("feishu_code", self.code.to_string());
321
322            // log_id 作为 request_id 便于链路追踪
323            if let Some(log_id) = self.error.as_ref().and_then(|e| e.log_id.clone()) {
324                ctx.set_request_id(log_id);
325            }
326
327            // 推导合适的 HTTP 状态用于 Api 变体(避免 u16 溢出)
328            let status =
329                mapped_code
330                    .http_status()
331                    .unwrap_or_else(|| match mapped_code.category() {
332                        ErrorCategory::RateLimit => 429,
333                        ErrorCategory::Authentication
334                        | ErrorCategory::Permission
335                        | ErrorCategory::Parameter => 400,
336                        ErrorCategory::Resource => 404,
337                        _ => 500,
338                    });
339
340            Err(CoreError::Api(Box::new(crate::error::ApiError {
341                status,
342                endpoint: "unknown_endpoint".into(),
343                message: self.msg,
344                source: None,
345                code: mapped_code,
346                ctx: Box::new(ctx),
347            })))
348        }
349    }
350
351    /// 获取数据的引用
352    pub fn data(&self) -> Option<&T> {
353        self.data.as_ref()
354    }
355
356    /// 检查是否有错误信息
357    pub fn has_error(&self) -> bool {
358        self.error.is_some()
359    }
360}
361
362#[cfg(test)]
363#[derive(Debug, serde::Serialize, serde::Deserialize)]
364pub struct ErrorInfo {
365    #[serde(rename = "key", default, skip_serializing_if = "Option::is_none")]
366    pub log_id: Option<String>,
367    #[serde(default, skip_serializing_if = "Vec::is_empty")]
368    pub details: Vec<ErrorDetail>,
369}
370
371#[cfg(test)]
372#[derive(Debug, serde::Serialize, serde::Deserialize)]
373pub struct ErrorDetail {
374    #[serde(default, skip_serializing_if = "Option::is_none")]
375    pub key: Option<String>,
376    #[serde(default, skip_serializing_if = "Option::is_none")]
377    pub value: Option<String>,
378    #[serde(default, skip_serializing_if = "Option::is_none")]
379    pub description: Option<String>,
380}
381
382/// 使用宏简化APIResponseTrait实现
383#[macro_export]
384macro_rules! impl_api_response {
385    ($type:ty, $format:expr) => {
386        impl ApiResponseTrait for $type {
387            fn data_format() -> ResponseFormat {
388                $format
389            }
390        }
391    };
392
393    ($type:ty, $format:expr, binary) => {
394        impl ApiResponseTrait for $type {
395            fn data_format() -> ResponseFormat {
396                $format
397            }
398
399            fn from_binary(file_name: String, body: Vec<u8>) -> Option<Self> {
400                Some(<$type>::from_binary_data(file_name, body))
401            }
402        }
403    };
404}
405
406#[cfg(test)]
407mod tests {
408    use super::*;
409    use crate::api::ResponseFormat;
410    use serde::{Deserialize, Serialize};
411
412    #[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)]
413    struct TestData {
414        id: i32,
415        name: String,
416    }
417
418    impl ApiResponseTrait for TestData {
419        fn data_format() -> ResponseFormat {
420            ResponseFormat::Data
421        }
422    }
423
424    #[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)]
425    struct TestFlattenData {
426        id: i32,
427        name: String,
428        code: i32,
429        msg: String,
430    }
431
432    impl ApiResponseTrait for TestFlattenData {
433        fn data_format() -> ResponseFormat {
434            ResponseFormat::Flatten
435        }
436    }
437
438    #[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)]
439    struct TestBinaryData {
440        file_name: String,
441        content: Vec<u8>,
442    }
443
444    impl ApiResponseTrait for TestBinaryData {
445        fn data_format() -> ResponseFormat {
446            ResponseFormat::Binary
447        }
448    }
449
450    // Note: Mock HTTP responses would require a more sophisticated testing setup
451    // The helper functions below are simplified examples of what mock functions might look like
452
453    #[test]
454    fn test_optimized_base_response_success() {
455        let response = OptimizedBaseResponse {
456            code: 0,
457            msg: "success".to_string(),
458            error: None,
459            data: Some(TestData {
460                id: 1,
461                name: "test".to_string(),
462            }),
463        };
464
465        assert!(response.is_success());
466        assert!(response.data().is_some());
467        assert_eq!(response.data().unwrap().id, 1);
468        assert!(!response.has_error());
469    }
470
471    #[test]
472    fn test_optimized_base_response_error() {
473        let response: OptimizedBaseResponse<TestData> = OptimizedBaseResponse {
474            code: 400,
475            msg: "Bad Request".to_string(),
476            error: Some(ErrorInfo {
477                log_id: Some("log123".to_string()),
478                details: vec![],
479            }),
480            data: None,
481        };
482
483        assert!(!response.is_success());
484        assert!(response.has_error());
485        assert!(response.data().is_none());
486    }
487
488    #[test]
489    fn test_optimized_base_response_into_data_success() {
490        let response = OptimizedBaseResponse {
491            code: 0,
492            msg: "success".to_string(),
493            error: None,
494            data: Some(TestData {
495                id: 1,
496                name: "test".to_string(),
497            }),
498        };
499
500        let data = response.into_data().unwrap();
501        assert_eq!(data.id, 1);
502        assert_eq!(data.name, "test");
503    }
504
505    #[test]
506    fn test_optimized_base_response_into_data_error() {
507        let response: OptimizedBaseResponse<TestData> = OptimizedBaseResponse {
508            code: 400,
509            msg: "Bad Request".to_string(),
510            error: None,
511            data: None,
512        };
513
514        let result = response.into_data();
515        assert!(result.is_err());
516        match result.unwrap_err() {
517            CoreError::Api(api) => {
518                assert_eq!(api.status, 400);
519                assert_eq!(api.message, "Bad Request");
520            }
521            _ => panic!("Expected ApiError"),
522        }
523    }
524
525    #[test]
526    fn test_optimized_base_response_into_data_success_but_no_data() {
527        let response: OptimizedBaseResponse<TestData> = OptimizedBaseResponse {
528            code: 0,
529            msg: "success".to_string(),
530            error: None,
531            data: None,
532        };
533
534        let result = response.into_data();
535        assert!(result.is_err());
536        match result.unwrap_err() {
537            CoreError::Validation { message, .. } => {
538                assert!(message.contains("data is missing"));
539            }
540            _ => panic!("Expected IllegalParamError"),
541        }
542    }
543
544    #[test]
545    fn test_error_info_serialization() {
546        let error_info = ErrorInfo {
547            log_id: Some("test_log_id".to_string()),
548            details: vec![
549                ErrorDetail {
550                    key: Some("field1".to_string()),
551                    value: Some("invalid_value".to_string()),
552                    description: Some("Field is required".to_string()),
553                },
554                ErrorDetail {
555                    key: Some("field2".to_string()),
556                    value: None,
557                    description: Some("Missing field".to_string()),
558                },
559            ],
560        };
561
562        let json = serde_json::to_string(&error_info).unwrap();
563        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
564
565        assert_eq!(deserialized.log_id, error_info.log_id);
566        assert_eq!(deserialized.details.len(), 2);
567        assert_eq!(deserialized.details[0].key, Some("field1".to_string()));
568        assert_eq!(deserialized.details[1].value, None);
569    }
570
571    #[test]
572    fn test_error_detail_optional_fields() {
573        let detail = ErrorDetail {
574            key: None,
575            value: Some("test_value".to_string()),
576            description: None,
577        };
578
579        let json = serde_json::to_string(&detail).unwrap();
580        let deserialized: ErrorDetail = serde_json::from_str(&json).unwrap();
581
582        assert_eq!(deserialized.key, None);
583        assert_eq!(deserialized.value, Some("test_value".to_string()));
584        assert_eq!(deserialized.description, None);
585    }
586
587    #[test]
588    fn test_filename_extraction() {
589        let cases = vec![
590            (
591                "attachment; filename=\"test.txt\"",
592                Some("test.txt".to_string()),
593            ),
594            (
595                "attachment; filename*=UTF-8''test%20file.pdf",
596                Some("test%20file.pdf".to_string()),
597            ),
598            (
599                "attachment; filename=simple.doc",
600                Some("simple.doc".to_string()),
601            ),
602            ("attachment", None),
603            ("", None),
604            ("filename=\"quoted.txt\"", Some("quoted.txt".to_string())),
605            ("filename=unquoted.txt", Some("unquoted.txt".to_string())),
606            (
607                "filename*=UTF-8''unicode%E2%9C%93.txt",
608                Some("unicode%E2%9C%93.txt".to_string()),
609            ),
610            (
611                "attachment; filename=\"spaced file.doc\"; other=value",
612                Some("spaced file.doc".to_string()),
613            ),
614        ];
615
616        for (input, expected) in cases {
617            let result = crate::content_disposition::extract_filename(input);
618            assert_eq!(result, expected, "Failed for input: {input}");
619        }
620    }
621
622    #[test]
623    fn test_filename_extraction_edge_cases() {
624        // Test empty and whitespace-only strings
625        assert_eq!(crate::content_disposition::extract_filename(""), None);
626        assert_eq!(crate::content_disposition::extract_filename("   "), None);
627        assert_eq!(crate::content_disposition::extract_filename(";;;"), None);
628
629        // Test malformed headers - based on implementation behavior
630        assert_eq!(
631            crate::content_disposition::extract_filename("filename="),
632            Some("".to_string())
633        );
634        assert_eq!(
635            crate::content_disposition::extract_filename("filename*="),
636            None
637        );
638        assert_eq!(
639            crate::content_disposition::extract_filename("filename=\""),
640            Some("".to_string())
641        );
642
643        // Test with only quotes - the current implementation extracts empty string
644        assert_eq!(
645            crate::content_disposition::extract_filename("filename=\"\""),
646            Some("".to_string())
647        );
648
649        // Test multiple filename directives (should return first valid one)
650        let multi_filename = "filename=\"first.txt\"; filename=\"second.txt\"";
651        assert_eq!(
652            crate::content_disposition::extract_filename(multi_filename),
653            Some("first.txt".to_string())
654        );
655    }
656
657    #[test]
658    fn test_json_parsing_performance() {
659        let json_data = r#"{"code": 0, "msg": "success", "data": {"id": 1, "name": "test"}}"#;
660
661        // 测试直接解析
662        let start = std::time::Instant::now();
663        let _result: Result<OptimizedBaseResponse<TestData>, _> = serde_json::from_str(json_data);
664        let direct_parse_time = start.elapsed();
665
666        // 测试双重解析(原始方法)
667        let start = std::time::Instant::now();
668        let _value: Value = serde_json::from_str(json_data).unwrap();
669        let _result: Result<OptimizedBaseResponse<TestData>, _> = serde_json::from_value(_value);
670        let double_parse_time = start.elapsed();
671
672        println!("Direct parse time: {direct_parse_time:?}");
673        println!("Double parse time: {double_parse_time:?}");
674
675        // 直接解析应该更快(虽然在微基准测试中差异可能很小)
676        // 这里主要是为了展示概念
677    }
678
679    #[test]
680    fn test_api_response_trait_data_format() {
681        assert_eq!(TestData::data_format(), ResponseFormat::Data);
682        assert_eq!(TestFlattenData::data_format(), ResponseFormat::Flatten);
683        assert_eq!(TestBinaryData::data_format(), ResponseFormat::Binary);
684    }
685
686    #[test]
687    fn test_api_response_trait_from_binary() {
688        let file_name = "test.txt".to_string();
689        let content = b"Hello, World!".to_vec();
690
691        let binary_data = TestBinaryData {
692            file_name: file_name.clone(),
693            content: content.clone(),
694        };
695        assert_eq!(binary_data.file_name, file_name);
696        assert_eq!(binary_data.content, content);
697
698        // Test default implementation for non-binary types
699        // TestData doesn't support binary format directly
700        let _ = "test.txt".to_string();
701    }
702
703    // Mock tests for response handlers would require a more sophisticated mocking setup
704    // For now, we'll test the logic that doesn't require actual HTTP responses
705
706    #[tokio::test]
707    async fn test_handle_data_response_parsing_logic() {
708        // Test JSON parsing logic without actual HTTP response
709        let test_cases = vec![
710            // Error response with fallback parsing
711            (r#"{"code": 400, "msg": "Bad Request"}"#, true),
712            // Invalid JSON
713            (r#"{"invalid": json"#, false),
714        ];
715
716        for (json, should_succeed) in test_cases {
717            // Test fallback parsing for error responses
718            if json.contains("code") && !json.contains("raw_response") {
719                let fallback_result = serde_json::from_str::<Value>(json);
720                if should_succeed {
721                    assert!(
722                        fallback_result.is_ok(),
723                        "Fallback parsing should succeed for: {}",
724                        json
725                    );
726                    let value = fallback_result.unwrap();
727                    assert!(value["code"].is_i64());
728                    assert!(value["msg"].is_string());
729                }
730            } else if json.contains("invalid") {
731                let parse_result = serde_json::from_str::<Value>(json);
732                assert!(parse_result.is_err(), "Invalid JSON should fail to parse");
733            }
734        }
735    }
736
737    #[tokio::test]
738    async fn test_handle_flatten_response_parsing_logic() {
739        let test_cases = vec![
740            // Success response
741            (
742                r#"{"id": 1, "name": "test", "code": 0, "msg": "success"}"#,
743                0,
744                true,
745            ),
746            // Error response
747            (r#"{"code": 400, "msg": "Bad Request"}"#, 400, false),
748            // Invalid JSON
749            (r#"{"invalid": json"#, -1, false),
750        ];
751
752        for (json, expected_code, should_have_data) in test_cases {
753            if json.contains("invalid") {
754                let parse_result = serde_json::from_str::<Value>(json);
755                assert!(parse_result.is_err(), "Invalid JSON should fail to parse");
756                continue;
757            }
758
759            let value_result = serde_json::from_str::<Value>(json);
760            assert!(value_result.is_ok(), "Valid JSON should parse as Value");
761
762            let value = value_result.unwrap();
763            let raw_response_result = serde_json::from_value::<RawResponse>(value.clone());
764
765            if expected_code >= 0 {
766                assert!(
767                    raw_response_result.is_ok(),
768                    "Should parse RawResponse for: {}",
769                    json
770                );
771                let raw_response = raw_response_result.unwrap();
772                assert_eq!(raw_response.code, expected_code);
773
774                if should_have_data && raw_response.code == 0 {
775                    let data_result = serde_json::from_value::<TestFlattenData>(value);
776                    assert!(
777                        data_result.is_ok(),
778                        "Should parse data for success response"
779                    );
780                }
781            }
782        }
783    }
784
785    #[test]
786    fn test_response_format_display_logic() {
787        let formats = vec![
788            (ResponseFormat::Data, "data"),
789            (ResponseFormat::Flatten, "flatten"),
790            (ResponseFormat::Binary, "binary"),
791        ];
792
793        for (format, expected_str) in formats {
794            let format_str = match format {
795                ResponseFormat::Data => "data",
796                ResponseFormat::Flatten => "flatten",
797                ResponseFormat::Binary => "binary",
798                ResponseFormat::Text => "text",
799                ResponseFormat::Custom => "custom",
800            };
801            assert_eq!(format_str, expected_str);
802        }
803    }
804
805    #[test]
806    fn test_binary_response_logic() {
807        let test_file_name = "test_document.pdf";
808        let test_content = b"PDF content here".to_vec();
809
810        // Test successful binary data creation
811        let binary_data = TestBinaryData {
812            file_name: test_file_name.to_string(),
813            content: test_content.clone(),
814        };
815        assert!(binary_data.file_name == test_file_name);
816        assert!(binary_data.content == test_content);
817
818        // Test empty content
819        let empty_data = TestBinaryData {
820            file_name: "empty.txt".to_string(),
821            content: vec![],
822        };
823        assert_eq!(empty_data.content.len(), 0);
824    }
825
826    #[test]
827    fn test_optimized_response_serialization_roundtrip() {
828        let original = OptimizedBaseResponse {
829            code: 0,
830            msg: "success".to_string(),
831            error: Some(ErrorInfo {
832                log_id: Some("test123".to_string()),
833                details: vec![ErrorDetail {
834                    key: Some("validation".to_string()),
835                    value: Some("failed".to_string()),
836                    description: Some("Field validation failed".to_string()),
837                }],
838            }),
839            data: Some(TestData {
840                id: 42,
841                name: "serialization_test".to_string(),
842            }),
843        };
844
845        // Serialize to JSON
846        let json = serde_json::to_string(&original).unwrap();
847
848        // Deserialize back
849        let deserialized: OptimizedBaseResponse<TestData> = serde_json::from_str(&json).unwrap();
850
851        // Verify all fields are preserved
852        assert_eq!(deserialized.code, original.code);
853        assert_eq!(deserialized.msg, original.msg);
854        assert_eq!(deserialized.data, original.data);
855        assert!(deserialized.error.is_some());
856
857        let error = deserialized.error.unwrap();
858        assert_eq!(error.log_id, Some("test123".to_string()));
859        assert_eq!(error.details.len(), 1);
860        assert_eq!(error.details[0].key, Some("validation".to_string()));
861    }
862
863    #[test]
864    fn test_optimized_response_skipped_fields() {
865        // Test response with None values (should be skipped in serialization)
866        let response: OptimizedBaseResponse<TestData> = OptimizedBaseResponse {
867            code: 0,
868            msg: "success".to_string(),
869            error: None,
870            data: None,
871        };
872
873        let json = serde_json::to_string(&response).unwrap();
874
875        // Should not contain "error" or "data" fields when they are None
876        assert!(!json.contains("\"error\""));
877        assert!(!json.contains("\"data\""));
878        assert!(json.contains("\"code\":0"));
879        assert!(json.contains("\"msg\":\"success\""));
880    }
881
882    #[test]
883    fn test_macro_api_response_implementation() {
884        // Test that the macro would work correctly
885        // Since we can't actually invoke the macro in tests easily,
886        // we'll test the pattern it would generate
887
888        #[derive(Debug, Default, Serialize, Deserialize)]
889        struct MacroTestData;
890
891        impl ApiResponseTrait for MacroTestData {
892            fn data_format() -> ResponseFormat {
893                ResponseFormat::Data
894            }
895        }
896
897        assert_eq!(MacroTestData::data_format(), ResponseFormat::Data);
898        // from_binary is not part of ApiResponseTrait
899        // assert!(MacroTestData::from_binary("test".to_string(), vec![1, 2, 3]).is_none());
900    }
901
902    #[test]
903    fn test_error_detail_empty_values() {
904        let detail = ErrorDetail {
905            key: Some("".to_string()),
906            value: Some("".to_string()),
907            description: Some("".to_string()),
908        };
909
910        let json = serde_json::to_string(&detail).unwrap();
911        let deserialized: ErrorDetail = serde_json::from_str(&json).unwrap();
912
913        assert_eq!(deserialized.key, Some("".to_string()));
914        assert_eq!(deserialized.value, Some("".to_string()));
915        assert_eq!(deserialized.description, Some("".to_string()));
916    }
917
918    #[test]
919    fn test_content_disposition_header_edge_cases() {
920        let edge_cases = vec![
921            // Case-insensitive filename
922            ("FILENAME=\"test.txt\"", None), // Our implementation is case-sensitive
923            ("Filename=\"test.txt\"", None), // Our implementation is case-sensitive
924            // Multiple spaces
925            (
926                "attachment;  filename=\"test.txt\"",
927                Some("test.txt".to_string()),
928            ),
929            ("attachment; filename =  \"test.txt\"", None), // Space before = is not handled
930            // Special characters in filename
931            (
932                "attachment; filename=\"test-file_v1.2.txt\"",
933                Some("test-file_v1.2.txt".to_string()),
934            ),
935            (
936                "attachment; filename=\"测试文件.txt\"",
937                Some("测试文件.txt".to_string()),
938            ),
939            // Both UTF-8 and regular filename (current implementation returns first match)
940            (
941                "attachment; filename=\"test.txt\"; filename*=UTF-8''better.txt",
942                Some("better.txt".to_string()),
943            ),
944        ];
945
946        for (input, expected) in edge_cases {
947            let result = crate::content_disposition::extract_filename(input);
948            assert_eq!(result, expected, "Failed for input: {}", input);
949        }
950    }
951
952    // ==================== Enhanced Coverage Tests ====================
953
954    // Complex error handling scenarios
955    #[test]
956    fn test_complex_error_response_scenarios() {
957        use serde_json::Value;
958
959        // Test nested error structures
960        let complex_error = r#"{
961            "code": 400,
962            "msg": "Validation failed",
963            "error": {
964                "log_id": "error_12345",
965                "details": [
966                    {
967                        "key": "field1",
968                        "value": "invalid",
969                        "description": "Field must be valid email"
970                    },
971                    {
972                        "key": "field2",
973                        "description": "Required field missing"
974                    }
975                ]
976            }
977        }"#;
978
979        let parsed: Value = serde_json::from_str(complex_error).unwrap();
980        assert_eq!(parsed["code"], 400);
981        assert_eq!(parsed["msg"], "Validation failed");
982        assert!(parsed["error"]["log_id"].is_string());
983        assert_eq!(parsed["error"]["details"].as_array().unwrap().len(), 2);
984
985        // Test error response with missing msg
986        let error_missing_msg = r#"{"code": 500}"#;
987        let parsed_missing: Value = serde_json::from_str(error_missing_msg).unwrap();
988        assert_eq!(parsed_missing["code"], 500);
989        assert!(!parsed_missing["msg"].is_string());
990
991        // Test error response with non-integer code
992        let invalid_code = r#"{"code": "400", "msg": "Invalid code type"}"#;
993        let parsed_invalid: Value = serde_json::from_str(invalid_code).unwrap();
994        assert!(parsed_invalid["code"].is_string());
995    }
996
997    // Large data handling tests
998    #[test]
999    fn test_large_response_data_handling() {
1000        use serde_json::Value;
1001
1002        // Test large JSON response
1003        let large_data_list: Vec<String> = (0..1000).map(|i| format!("item_{}", i)).collect();
1004
1005        let large_response = serde_json::json!({
1006            "code": 0,
1007            "msg": "success",
1008            "data": {
1009                "items": large_data_list,
1010                "metadata": {
1011                    "total": 1000,
1012                    "page": 1
1013                }
1014            }
1015        });
1016
1017        let json_str = serde_json::to_string(&large_response).unwrap();
1018        assert!(json_str.len() > 10000); // Should be reasonably large
1019
1020        // Test parsing large response
1021        let parsed: Value = serde_json::from_str(&json_str).unwrap();
1022        assert_eq!(parsed["code"], 0);
1023        assert_eq!(parsed["data"]["items"].as_array().unwrap().len(), 1000);
1024    }
1025
1026    // Unicode and internationalization tests for responses
1027    #[test]
1028    fn test_unicode_response_handling() {
1029        use serde_json::json;
1030
1031        let unicode_response = json!({
1032            "code": 0,
1033            "msg": "操作成功",
1034            "data": {
1035                "title": "测试标题",
1036                "description": "这是一个包含中文、English و العربية 的描述",
1037                "tags": ["标签1", "tag2", "العربية", "🚀"]
1038            }
1039        });
1040
1041        let json_str = serde_json::to_string(&unicode_response).unwrap();
1042        let parsed: Value = serde_json::from_str(&json_str).unwrap();
1043
1044        assert_eq!(parsed["msg"], "操作成功");
1045        assert_eq!(parsed["data"]["title"], "测试标题");
1046        assert!(parsed["data"]["description"]
1047            .as_str()
1048            .unwrap()
1049            .contains("中文"));
1050        assert!(parsed["data"]["tags"].as_array().unwrap()[3] == "🚀");
1051    }
1052
1053    // Memory efficiency tests
1054    #[test]
1055    fn test_memory_efficient_response_processing() {
1056        use std::mem;
1057
1058        // Test that OptimizedBaseResponse doesn't unnecessarily copy data
1059        let response = OptimizedBaseResponse {
1060            code: 0,
1061            msg: "success".to_string(),
1062            error: None,
1063            data: Some(TestData {
1064                id: 123,
1065                name: "test".to_string(),
1066            }),
1067        };
1068
1069        let response_size = mem::size_of_val(&response);
1070        assert!(response_size > 0);
1071
1072        // Test that Option fields don't increase size when None
1073        let empty_response: OptimizedBaseResponse<TestData> = OptimizedBaseResponse {
1074            code: 0,
1075            msg: "success".to_string(),
1076            error: None,
1077            data: None,
1078        };
1079
1080        let empty_size = mem::size_of_val(&empty_response);
1081        // Both should have similar size since Option<T> has overhead regardless of value
1082        assert!(empty_size > 0);
1083    }
1084
1085    // Performance benchmarking tests
1086    #[test]
1087    fn test_response_parsing_performance() {
1088        use std::time::Instant;
1089
1090        let test_json = r#"{"code": 0, "msg": "success", "data": {"id": 1, "name": "test"}}"#;
1091
1092        // Benchmark direct parsing
1093        let iterations = 1000;
1094        let start = Instant::now();
1095
1096        for _ in 0..iterations {
1097            let _: Result<OptimizedBaseResponse<TestData>, _> = serde_json::from_str(test_json);
1098        }
1099
1100        let direct_time = start.elapsed();
1101
1102        // Benchmark fallback parsing (Value -> BaseResponse)
1103        let start = Instant::now();
1104
1105        for _ in 0..iterations {
1106            let value: Value = serde_json::from_str(test_json).unwrap();
1107            let _: Result<Response<TestData>, _> = serde_json::from_value(value);
1108        }
1109
1110        let fallback_time = start.elapsed();
1111
1112        // Performance test is informational - timing can vary
1113        println!(
1114            "Direct parsing: {:?}, Fallback parsing: {:?}",
1115            direct_time, fallback_time
1116        );
1117
1118        // Only assert that both completed successfully and within reasonable time
1119        assert!(direct_time.as_millis() < 1000); // Should complete within 1 second
1120        assert!(fallback_time.as_millis() < 1000); // Should complete within 1 second
1121
1122        // Performance characteristics check - direct parsing should be competitive
1123        // We don't assert strict ordering since timing can be non-deterministic
1124        let ratio = fallback_time.as_nanos() as f64 / direct_time.as_nanos() as f64;
1125        println!("Performance ratio (fallback/direct): {:.2}x", ratio);
1126    }
1127
1128    // Concurrent response processing tests
1129    #[test]
1130    fn test_concurrent_response_parsing() {
1131        use std::sync::{Arc, Mutex};
1132        use std::thread;
1133
1134        let test_responses = vec![
1135            r#"{"code": 0, "msg": "success", "data": {"id": 1, "name": "test1"}}"#,
1136            r#"{"code": 0, "msg": "success", "data": {"id": 2, "name": "test2"}}"#,
1137            r#"{"code": 400, "msg": "error", "data": null}"#,
1138            r#"{"code": 0, "msg": "success", "data": {"id": 4, "name": "test4"}}"#,
1139        ];
1140
1141        let results = Arc::new(Mutex::new(Vec::new()));
1142        let mut handles = vec![];
1143
1144        for (i, response_json) in test_responses.into_iter().enumerate() {
1145            let results_clone = results.clone();
1146            let handle = thread::spawn(move || {
1147                let parsed: Result<OptimizedBaseResponse<TestData>, _> =
1148                    serde_json::from_str(response_json);
1149
1150                results_clone.lock().unwrap().push((i, parsed.is_ok()));
1151            });
1152            handles.push(handle);
1153        }
1154
1155        for handle in handles {
1156            handle.join().unwrap();
1157        }
1158
1159        let results_vec = results.lock().unwrap();
1160        assert_eq!(results_vec.len(), 4);
1161        assert!(results_vec.iter().all(|(_, success)| *success));
1162    }
1163
1164    // Edge case JSON structures
1165    #[test]
1166    fn test_edge_case_json_structures() {
1167        use serde_json::json;
1168
1169        // Test with null values
1170        let null_response = json!({
1171            "code": 0,
1172            "msg": "success",
1173            "data": null
1174        });
1175
1176        let parsed: OptimizedBaseResponse<TestData> =
1177            serde_json::from_value(null_response).unwrap();
1178        assert!(parsed.is_success());
1179        assert!(parsed.data().is_none());
1180
1181        // Test with empty arrays and objects
1182        let empty_response = json!({
1183            "code": 0,
1184            "msg": "success",
1185            "data": {
1186                "items": [],
1187                "metadata": {}
1188            }
1189        });
1190
1191        // This would fail to parse as TestData, but we can test the JSON structure
1192        let parsed_value: Value = serde_json::from_value(empty_response).unwrap();
1193        assert_eq!(parsed_value["data"]["items"].as_array().unwrap().len(), 0);
1194        assert!(parsed_value["data"]["metadata"]
1195            .as_object()
1196            .unwrap()
1197            .is_empty());
1198
1199        // Test with unexpected additional fields
1200        let extra_fields_response = json!({
1201            "code": 0,
1202            "msg": "success",
1203            "data": {"id": 1, "name": "test"},
1204            "unexpected_field": "should_be_ignored",
1205            "another_unexpected": {"nested": "data"}
1206        });
1207
1208        let parsed_extra: OptimizedBaseResponse<TestData> =
1209            serde_json::from_value(extra_fields_response).unwrap();
1210        assert!(parsed_extra.is_success());
1211        assert!(parsed_extra.data().is_some());
1212    }
1213
1214    // Response format validation tests
1215    #[test]
1216    fn test_response_format_validation() {
1217        // Test different response formats and their characteristics
1218        let test_cases = vec![
1219            (ResponseFormat::Data, "data", true),
1220            (ResponseFormat::Flatten, "flatten", false),
1221            (ResponseFormat::Binary, "binary", false),
1222        ];
1223
1224        for (format, expected_str, supports_data) in test_cases {
1225            // Test format string representation
1226            let format_str = match format {
1227                ResponseFormat::Data => "data",
1228                ResponseFormat::Flatten => "flatten",
1229                ResponseFormat::Binary => "binary",
1230                ResponseFormat::Text => "text",
1231                ResponseFormat::Custom => "custom",
1232            };
1233            assert_eq!(format_str, expected_str);
1234
1235            // Test format characteristics
1236            match format {
1237                ResponseFormat::Data => assert!(supports_data),
1238                ResponseFormat::Flatten => assert!(!supports_data),
1239                ResponseFormat::Binary => assert!(!supports_data),
1240                ResponseFormat::Text => assert!(supports_data),
1241                ResponseFormat::Custom => assert!(supports_data),
1242            }
1243        }
1244    }
1245
1246    // Binary response handling edge cases
1247    #[test]
1248    fn test_binary_response_edge_cases() {
1249        // Test with very large binary data
1250        let large_binary = vec![0u8; 1_000_000]; // 1MB
1251        let large_binary_data = TestBinaryData {
1252            file_name: "large_file.bin".to_string(),
1253            content: large_binary,
1254        };
1255        assert_eq!(large_binary_data.content.len(), 1_000_000);
1256
1257        // Test with empty binary data
1258        let empty_binary_data = TestBinaryData {
1259            file_name: "empty_file.txt".to_string(),
1260            content: vec![],
1261        };
1262        assert!(empty_binary_data.content.is_empty());
1263
1264        // Test with special characters in filename
1265        let special_filename_data = TestBinaryData {
1266            file_name: "测试文件@#$%.txt".to_string(),
1267            content: b"test content".to_vec(),
1268        };
1269        assert_eq!(special_filename_data.file_name, "测试文件@#$%.txt");
1270    }
1271
1272    // Complex error detail scenarios
1273    #[test]
1274    fn test_complex_error_detail_scenarios() {
1275        // Test with nested error details
1276        let complex_error = ErrorInfo {
1277            log_id: Some("complex_error_123".to_string()),
1278            details: vec![
1279                ErrorDetail {
1280                    key: Some("validation".to_string()),
1281                    value: Some("email格式不正确".to_string()),
1282                    description: Some("邮箱地址格式验证失败".to_string()),
1283                },
1284                ErrorDetail {
1285                    key: Some("required_field".to_string()),
1286                    value: None,
1287                    description: Some("必填字段缺失".to_string()),
1288                },
1289                ErrorDetail {
1290                    key: Some("constraint".to_string()),
1291                    value: Some("长度超过限制".to_string()),
1292                    description: Some("字段长度超出最大限制".to_string()),
1293                },
1294            ],
1295        };
1296
1297        // Test serialization and deserialization
1298        let json = serde_json::to_string(&complex_error).unwrap();
1299        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
1300
1301        assert_eq!(deserialized.log_id, complex_error.log_id);
1302        assert_eq!(deserialized.details.len(), 3);
1303        assert_eq!(
1304            deserialized.details[0].description,
1305            Some("邮箱地址格式验证失败".to_string())
1306        );
1307        assert_eq!(deserialized.details[1].value, None);
1308        assert_eq!(deserialized.details[2].key, Some("constraint".to_string()));
1309    }
1310
1311    // Response tracker integration simulation
1312    #[test]
1313    fn test_response_tracker_integration_simulation() {
1314        // Simulate response tracker behavior
1315        let tracker_calls = [
1316            ("start", "json_data", Some(1024)),
1317            ("parsing_complete", "", None),
1318            ("validation_complete", "", None),
1319            ("success", "", None),
1320        ];
1321
1322        // Verify tracking sequence
1323        assert_eq!(tracker_calls.len(), 4);
1324        assert_eq!(tracker_calls[0].0, "start");
1325        assert_eq!(tracker_calls[0].1, "json_data");
1326        assert_eq!(tracker_calls[0].2, Some(1024));
1327
1328        // Test error tracking simulation
1329        let error_tracker_calls = [
1330            ("start", "json_flatten", Some(512)),
1331            ("error", "解析失败", None),
1332        ];
1333
1334        assert_eq!(error_tracker_calls.len(), 2);
1335        assert_eq!(error_tracker_calls[1].0, "error");
1336        assert_eq!(error_tracker_calls[1].1, "解析失败");
1337    }
1338
1339    // Real-world response pattern tests
1340    #[test]
1341    fn test_real_world_response_patterns() {
1342        use serde_json::json;
1343
1344        // Pattern 1: Pagination response
1345        let pagination_response = json!({
1346            "code": 0,
1347            "msg": "success",
1348            "data": {
1349                "items": [
1350                    {"id": 1, "name": "item1"},
1351                    {"id": 2, "name": "item2"}
1352                ],
1353                "page_token": "next_page_token",
1354                "has_more": true
1355            }
1356        });
1357
1358        let pagination_parsed: Value = serde_json::from_value(pagination_response).unwrap();
1359        assert_eq!(
1360            pagination_parsed["data"]["items"].as_array().unwrap().len(),
1361            2
1362        );
1363        assert!(pagination_parsed["data"]["has_more"].as_bool().unwrap());
1364
1365        // Pattern 2: Nested data response
1366        let nested_response = json!({
1367            "code": 0,
1368            "msg": "success",
1369            "data": {
1370                "user": {
1371                    "id": "user_123",
1372                    "profile": {
1373                        "name": "张三",
1374                        "department": "技术部"
1375                    }
1376                },
1377                "permissions": ["read", "write"]
1378            }
1379        });
1380
1381        let nested_parsed: Value = serde_json::from_value(nested_response).unwrap();
1382        assert_eq!(nested_parsed["data"]["user"]["profile"]["name"], "张三");
1383        assert_eq!(
1384            nested_parsed["data"]["permissions"]
1385                .as_array()
1386                .unwrap()
1387                .len(),
1388            2
1389        );
1390
1391        // Pattern 3: Error with detailed validation info
1392        let validation_error_response = json!({
1393            "code": 400,
1394            "msg": "参数验证失败",
1395            "error": {
1396                "log_id": "validation_error_456",
1397                "details": [
1398                    {
1399                        "field": "email",
1400                        "error_code": "INVALID_FORMAT",
1401                        "message": "邮箱格式不正确"
1402                    }
1403                ]
1404            }
1405        });
1406
1407        let validation_parsed: Value = serde_json::from_value(validation_error_response).unwrap();
1408        assert_eq!(validation_parsed["code"], 400);
1409        assert!(!validation_parsed["error"]["details"]
1410            .as_array()
1411            .unwrap()
1412            .is_empty());
1413    }
1414
1415    // OptimizedBaseResponse performance characteristics
1416    #[test]
1417    fn test_optimized_response_performance_characteristics() {
1418        use std::time::Instant;
1419
1420        // Test creation performance
1421        let start = Instant::now();
1422        let mut responses = Vec::new();
1423
1424        for i in 0..1000 {
1425            responses.push(OptimizedBaseResponse {
1426                code: if i % 10 == 0 { 400 } else { 0 },
1427                msg: if i % 10 == 0 {
1428                    "error".to_string()
1429                } else {
1430                    "success".to_string()
1431                },
1432                error: if i % 10 == 0 {
1433                    Some(ErrorInfo {
1434                        log_id: Some(format!("log_{}", i)),
1435                        details: vec![],
1436                    })
1437                } else {
1438                    None
1439                },
1440                data: if i % 10 != 0 {
1441                    Some(TestData {
1442                        id: i,
1443                        name: format!("test_{}", i),
1444                    })
1445                } else {
1446                    None
1447                },
1448            });
1449        }
1450
1451        let creation_time = start.elapsed();
1452        assert_eq!(responses.len(), 1000);
1453        assert!(creation_time.as_millis() < 100); // Should complete quickly
1454
1455        // Test filtering performance
1456        let start = Instant::now();
1457        let successful_responses: Vec<_> = responses.iter().filter(|r| r.is_success()).collect();
1458
1459        let filter_time = start.elapsed();
1460        assert_eq!(successful_responses.len(), 900);
1461        assert!(filter_time.as_millis() < 10); // Should be very fast
1462    }
1463}
1464
1465/// 使用示例
1466///
1467/// 在RequestExecutor中使用改进的响应处理器:
1468/// ```rust,ignore
1469/// impl RequestExecutor {
1470///     pub async fn execute_improved<T: ApiResponseTrait + DeserializeOwned>(
1471///         // ... 参数
1472///     ) -> SDKResult<OptimizedBaseResponse<T>> {
1473///         // ... 构建请求
1474///         let response = http_client.send(request).await?;
1475///         ImprovedResponseHandler::handle_response(response).await
1476///     }
1477/// }
1478///
1479/// // 使用新的响应格式
1480/// let result = RequestExecutor::execute_improved::<MessageData>(...).await?;
1481///
1482/// match result.into_data() {
1483///     Ok(data) => println!("Success: {:?}", data),
1484///     Err(e) => println!("Error: {:?}", e),
1485/// }
1486/// ```
1487mod usage_examples {}