1use std::ptr;
2
3use encoding_rs::GB18030;
4use std::borrow::Cow;
5
6pub fn copy_str_to_i8_array(dst: &mut [i8], src: &str) {
7 if dst.is_empty() {
9 return;
10 }
11
12 let bytes = src.as_bytes();
14
15 let len = usize::min(bytes.len(), dst.len() - 1);
17
18 unsafe {
19 ptr::copy_nonoverlapping(bytes.as_ptr(), dst.as_mut_ptr() as *mut u8, len);
20 }
21
22 dst[len] = 0;
24
25 }
27
28#[macro_export]
29macro_rules! print_rsp_info {
30 ($p:expr) => {
31 if let Some(p) = $p {
32 println!(
33 "ErrorID[{}] Message[{}]",
34 p.ErrorID,
35 gb18030_cstr_i8_to_str(&p.ErrorMsg).unwrap().to_string()
36 );
37 }
38 };
39}
40
41pub fn gb18030_cstr_i8_to_str<'a>(
46 c_chars: &'a [std::os::raw::c_char],
47) -> Result<Cow<'a, str>, String> {
48 let len = c_chars
50 .iter()
51 .position(|&c| c == 0)
52 .unwrap_or(c_chars.len());
53 let bytes = &c_chars[..len];
54
55 let bytes = unsafe { &*(bytes as *const [std::os::raw::c_char] as *const [u8]) };
57
58 if bytes.is_ascii() {
60 return std::str::from_utf8(bytes)
61 .map(Cow::Borrowed)
62 .map_err(|e| format!("Invalid UTF-8: {}", e));
63 }
64
65 let (decoded, _, had_errors) = GB18030.decode(bytes);
67 if had_errors {
68 return Err("Failed to decode GB18030 string".to_string());
69 }
70
71 Ok(Cow::Owned(decoded.into_owned()))
72}
73
74pub trait AssignFromString {
75 fn assign_from_str(&mut self, s: &str);
78}
79
80impl<const N: usize> AssignFromString for [i8; N] {
81 fn assign_from_str(&mut self, s: &str) {
82 copy_str_to_i8_array(self, s);
83 }
84}
85
86impl<const N: usize> AssignFromString for &mut [i8; N] {
87 fn assign_from_str(&mut self, s: &str) {
88 copy_str_to_i8_array(*self, s);
89 }
90}
91
92pub trait SetString {
93 fn set_str(&mut self, s: &str);
96}
97
98impl<const N: usize> SetString for [i8; N] {
99 fn set_str(&mut self, s: &str) {
100 copy_str_to_i8_array(self, s);
101 }
102}
103
104impl<const N: usize> SetString for &mut [i8; N] {
105 fn set_str(&mut self, s: &str) {
106 copy_str_to_i8_array(*self, s);
107 }
108}
109
110pub trait WrapToString {
111 fn to_string(&self) -> String;
112}
113
114impl<const N: usize> WrapToString for [i8; N] {
115 fn to_string(&self) -> String {
116 let str_ = gb18030_cstr_i8_to_str(self);
117 str_.unwrap().to_string()
118 }
119}
120
121impl<const N: usize> WrapToString for &[i8; N] {
122 fn to_string(&self) -> String {
123 let str_ = gb18030_cstr_i8_to_str(*self);
124 str_.unwrap().to_string()
125 }
126}
127
128#[derive(Debug, Clone)]
129pub struct WrapString(pub String); impl<const N: usize> From<[i8; N]> for WrapString {
132 fn from(value: [i8; N]) -> Self {
133 let str_ = gb18030_cstr_i8_to_str(&value).expect("failed to decode");
134 WrapString(str_.into())
135 }
136}
137
138impl<const N: usize> From<&[i8; N]> for WrapString {
139 fn from(value: &[i8; N]) -> Self {
140 let str_ = gb18030_cstr_i8_to_str(value).expect("failed to decode");
141 WrapString(str_.into())
142 }
143}
144
145pub trait WrapFrom<T> {
146 fn wrap_from(value: T) -> Self;
147}
148
149pub trait WrapInto<T>: Sized {
151 fn wrap_into(self) -> T;
152}
153
154impl<T, U> WrapInto<U> for T
156where
157 U: WrapFrom<T>,
158{
159 fn wrap_into(self) -> U {
160 U::wrap_from(self)
161 }
162}
163
164impl WrapFrom<&[i8]> for String {
165 fn wrap_from(bytes: &[i8]) -> Self {
166 let u8_bytes: Vec<u8> = bytes.iter().map(|&b| b as u8).collect();
167 String::from_utf8(u8_bytes).expect("Invalid UTF-8 sequence")
168 }
169}
170
171impl<const N: usize> WrapFrom<[i8; N]> for String {
172 fn wrap_from(value: [i8; N]) -> Self {
173 let str_ = gb18030_cstr_i8_to_str(&value).expect("failed to decode");
174 str_.into()
175 }
176}
177
178impl<const N: usize> WrapFrom<&[i8; N]> for String {
179 fn wrap_from(value: &[i8; N]) -> Self {
180 let str_ = gb18030_cstr_i8_to_str(value).expect("failed to decode");
181 str_.into()
182 }
183}