cobia/
cape_string_impl_win32.rs

1use crate::cape_data_traits::*;
2use crate::C;
3use crate::cape_result_value::*;
4use std::fmt;
5
6/// Default ICapeString implementation
7///
8/// For COBIA, strings go over the pipeline
9///  as null terminated. For Windows, COBIA requires UTF-16 encoding.
10///
11/// Rust uses non-null-terminated strings that are UTF-8 encoded.
12///
13/// Because this translation is always required, there is no 
14/// read-only string implementation that refers to a string slice.
15///
16/// This implementation uses a `Vec<u16>` to store the string data.
17/// In case the string is empty, the vector may remain empty, so
18/// care must be taken to add a null terminated string in this scenario.
19///
20
21#[derive(Debug,Clone)]
22pub struct CapeStringImpl {
23	data: Vec<C::CapeCharacter>, //we allow the vec to remain empty (no trailing 0) if uninitialized. This implies some checks need to be done for the empty case.
24}
25
26impl CapeStringImpl {
27
28	const EMPTY_STRING : C::CapeCharacter = 0;
29
30	///Default constructor
31	///
32	/// # Examples
33	///
34	/// ```
35	/// use cobia;
36	/// let s=cobia::CapeStringImpl::new();
37	/// assert_eq!(s.as_string(),"");
38	/// ```
39	pub fn new() -> Self {
40		CapeStringImpl {
41			data: Vec::new(),
42		}
43	}
44	///Construct from string
45	///
46	/// # Arguments
47	///
48	/// * `s` - A string slice to be converted to a CapeStringImpl
49	///
50	/// # Examples
51	///
52	/// ```
53	/// use cobia;
54	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
55	/// ```
56	pub fn from_string<T:AsRef<str>>(s: T) -> Self {
57		let mut cs = CapeStringImpl::new();
58		let s=s.as_ref();
59		cs.data.reserve(s.len() + 1);
60		for c in s.encode_utf16() { //todo, change to s.encode_utf16().collect_into(&cs.data);
61			cs.data.push(c);
62		}
63		cs.data.push(0);
64		cs
65	}
66	///Construct from raw data
67	///
68	/// # Arguments
69	///
70	/// * `data` - A pointer to the string data
71	/// * `size` - The size of the string data
72	///
73	pub unsafe fn from_raw_data(data: *const C::CapeCharacter, size: C::CapeSize) -> Self {
74		let mut cs = CapeStringImpl::new();
75		cs.data.reserve(size as usize + 1);
76		let slice = unsafe { std::slice::from_raw_parts(data, size as usize) };
77		cs.data.extend_from_slice(&slice);
78		cs.data.push(0);
79		cs
80	}
81
82	///Return as string
83	///
84	/// # Examples
85	///
86	/// ```
87	/// use cobia;
88	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
89	/// assert_eq!(s.as_string(),"idealGasEnthalpy");
90	/// ```
91	pub fn as_string(&self) -> String {
92		if self.data.is_empty() {
93			String::new()
94		} else {
95			let len = self.data.len() - 1;
96			String::from_utf16_lossy(&self.data[..len])
97		}
98	}
99
100	///Set string
101	///
102	/// # Arguments
103	///
104	/// * `s` - Any CAPE-OPEN string type
105	///
106	/// # Examples
107	///
108	/// ```
109	/// use cobia;
110	/// let mut s=cobia::CapeStringImpl::new();
111	/// s.set(&cobia::CapeStringImpl::from_string("idealGasEnthalpy"));
112	/// assert_eq!(s.as_string(),"idealGasEnthalpy");
113	/// ```
114
115	pub fn set<T: CapeStringConstProvider>(&mut self, s: &T) {
116		let(ptr,size)=s.as_capechar_const_with_length();
117		self.data.clear();
118		self.data.reserve(size as usize + 1);
119		let slice=unsafe { std::slice::from_raw_parts(ptr, size as usize) };
120		self.data.extend_from_slice(&slice);
121		self.data.push(0);
122	}
123
124	///Set string
125	///
126	/// # Arguments
127	///
128	/// * `s` - A string slice to be set
129	///
130	/// # Examples
131	///
132	/// ```
133	/// use cobia;
134	/// let mut s=cobia::CapeStringImpl::new();
135	/// s.set_string("idealGasEnthalpy");
136	/// assert_eq!(s.as_string(),"idealGasEnthalpy");
137	/// ```
138
139	pub fn set_string<T: AsRef<str>>(&mut self, s: T) {
140		let s = s.as_ref();
141		self.data.clear();
142		self.data.reserve(s.len() + 1);
143		for c in s.encode_utf16() { //todo, change to s.encode_utf16().collect_into(&cs.data);
144			self.data.push(c);
145		}
146		self.data.push(0);
147	}
148
149	/// Check empty
150	///
151	/// Returns true if the string is empty (no data, or only the null terminator).
152	///
153	/// # Examples
154	///
155	/// ```
156	/// use cobia;
157	/// let s=cobia::CapeStringImpl::new();
158	/// assert_eq!(s.is_empty(),true);
159	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
160	/// assert_eq!(s.is_empty(),false);
161	/// ```
162	pub fn is_empty(&self) -> bool {
163		self.data.is_empty() || self.data[0] == 0
164	}
165
166	extern "C" fn string_get(
167		me: *mut ::std::os::raw::c_void,
168		data: *mut *const C::CapeCharacter,
169		size: *mut C::CapeSize,
170	) {
171		let p = me as *mut CapeStringImpl;
172		let s: &mut CapeStringImpl = unsafe { &mut *p };
173		if s.data.is_empty() {
174			unsafe {
175				*data = &Self::EMPTY_STRING;
176				*size = 0;
177			}
178		} else {
179			unsafe {
180				*data = s.data.as_ptr() as *const C::CapeCharacter;
181				*size = s.data.len() as C::CapeSize - 1; //exclude null terminator
182			}
183		}
184	}
185
186	extern "C" fn string_set(
187		me: *mut ::std::os::raw::c_void,
188		data: *const C::CapeCharacter,
189		size: C::CapeSize,
190	) -> C::CapeResult {
191		let p = me as *mut CapeStringImpl;
192		let s: &mut CapeStringImpl = unsafe { &mut *p };
193		s.data.clear();
194		if size > 0 {
195			let slice=unsafe { std::slice::from_raw_parts(data, size as usize) };
196			s.data.reserve(slice.len() + 1);
197			s.data.extend_from_slice(&slice);
198			s.data.push(0); //null terminator
199		}
200		COBIAERR_NOERROR
201	}
202
203	const CAPE_STRING_VTABLE: C::ICapeString_VTable = C::ICapeString_VTable {
204		get: Some(CapeStringImpl::string_get),
205		set: Some(CapeStringImpl::string_set),
206	};
207
208	/// Convert character to lower case
209	///
210	/// # Arguments
211	///
212	/// * `c` - A UTF-16 character to convert to lower case
213	///
214
215	pub(crate) fn to_lower_case(c: C::CapeCharacter) -> C::CapeCharacter {
216		#![allow(non_contiguous_range_endpoints)]
217		//https://www.ibm.com/docs/en/i/7.5?topic=tables-unicode-uppercase-lowercase-conversion-mapping-table
218		//note that all characters live in the U+0000 to U+D7FF and U+E000 to U+FFFF range 
219		// https://en.wikipedia.org/wiki/UTF-16
220		//so that there is no need to check for the surrogate pair range (or for 4-byte UTF-16 characters)
221		match c {
222			65..90 | 192..214 | 216..222 | 913..929 | 931..939 | 1040..1071 | 65313..65338 => c+32,
223			256 | 258 | 260 | 262 | 264 | 266 | 268 | 270 | 272 | 274 | 276 | 278 | 280 | 282 | 284 | 286 | 288 | 290 | 292 | 294 | 296 | 298 | 300 | 302 | 306 | 308 | 310 | 313 | 315 | 317 | 319 | 321 | 323 | 325 | 327 | 330 | 332 | 334 | 336 | 338 | 340 | 342 | 344 | 346 | 348 | 350 | 352 | 354 | 356 | 358 | 360 | 362 | 364 | 366 | 368 | 370 | 372 | 374 | 377 | 379 | 381 | 386 | 388 | 391 | 395 | 401 | 408 | 416 | 418 | 420 | 423 | 428 | 431 | 435 | 437 | 440 | 444 | 453 | 456 | 459 | 461 | 463 | 465 | 467 | 469 | 471 | 473 | 475 | 478 | 480 | 482 | 484 | 486 | 488 | 490 | 492 | 494 | 500 | 506 | 508 | 510 | 512 | 514 | 516 | 518 | 520 | 522 | 524 | 526 | 528 | 530 | 532 | 534 | 994 | 996 | 998 | 1000 | 1002 | 1004 | 1006 | 1120 | 1122 | 1124 | 1126 | 1128 | 1130 | 1132 | 1134 | 1136 | 1138 | 1140 | 1142 | 1144 | 1146 | 1148 | 1150 | 1152 | 1168 | 1170 | 1172 | 1174 | 1176 | 1178 | 1180 | 1182 | 1184 | 1186 | 1188 | 1190 | 1192 | 1194 | 1196 | 1198 | 1200 | 1202 | 1204 | 1206 | 1208 | 1210 | 1212 | 1214 | 1217 | 1219 | 1223 | 1227 | 1232 | 1234 | 1236 | 1238 | 1240 | 1242 | 1244 | 1246 | 1248 | 1250 | 1252 | 1254 | 1256 | 1258 | 1262 | 1264 | 1266 | 1268 | 1272 | 7680 | 7682 | 7684 | 7686 | 7688 | 7690 | 7692 | 7694 | 7696 | 7698 | 7700 | 7702 | 7704 | 7706 | 7708 | 7710 | 7712 | 7714 | 7716 | 7718 | 7720 | 7722 | 7724 | 7726 | 7728 | 7730 | 7732 | 7734 | 7736 | 7738 | 7740 | 7742 | 7744 | 7746 | 7748 | 7750 | 7752 | 7754 | 7756 | 7758 | 7760 | 7762 | 7764 | 7766 | 7768 | 7770 | 7772 | 7774 | 7776 | 7778 | 7780 | 7782 | 7784 | 7786 | 7788 | 7790 | 7792 | 7794 | 7796 | 7798 | 7800 | 7802 | 7804 | 7806 | 7808 | 7810 | 7812 | 7814 | 7816 | 7818 | 7820 | 7822 | 7824 | 7826 | 7828 | 7840 | 7842 | 7844 | 7846 | 7848 | 7850 | 7852 | 7854 | 7856 | 7858 | 7860 | 7862 | 7864 | 7866 | 7868 | 7870 | 7872 | 7874 | 7876 | 7878 | 7880 | 7882 | 7884 | 7886 | 7888 | 7890 | 7892 | 7894 | 7896 | 7898 | 7900 | 7902 | 7904 | 7906 | 7908 | 7910 | 7912 | 7914 | 7916 | 7918 | 7920 | 7922 | 7924 | 7926 | 7928 => c+1,
224			304 => c-199,
225			376 => c-121,
226			385 => c+210,
227			390 => c+206,
228			394 | 403 => c+205,
229			398..399 => c+202,
230			400 => c+203,
231			404 => c+207,
232			406 | 412 => c+211,
233			407 => c+209,
234			413 => c+213,
235			415 => c+214,
236			425 | 430 => c+218,
237			433..434 => c+217,
238			439 => c+219,
239			452 | 455 | 458 | 497 => c+2,
240			902 => c+38,
241			904..906 => c+37,
242			908 => c+64,
243			910..911 => c+63,
244			1025..1036 | 1038..1039 => c+80,
245			1329..1366 | 4256..4293 => c+48,
246			7944..7951 | 7960..7965 | 7976..7983 | 7992..7999 | 8008..8013 | 8025 | 8027 | 8029 | 8031 | 8040..8047 | 8072..8079 | 8088..8095 | 8104..8111 | 8120..8121 | 8152..8153 | 8168..8169 => c-8,
247			9398..9423 => c+26,
248			_ => c
249		}
250	}
251
252	/// Convert character to upper case
253	///
254	/// # Arguments
255	///
256	/// * `c` - A UTF-16 character to convert to upper case
257	///
258
259	pub(crate) fn to_upper_case(c: C::CapeCharacter) -> C::CapeCharacter {
260		#![allow(non_contiguous_range_endpoints)]
261		//coded as invers of to_lower_case, with exception of 
262		// 0130	0069	LATIN CAPITAL LETTER I WITH DOT ABOVE	LATIN SMALL LETTER I
263		// because latin small letter I maps to latin capital letter I without dot
264		//https://www.ibm.com/docs/en/i/7.5?topic=tables-unicode-uppercase-lowercase-conversion-mapping-table
265		match c {
266			97..122 | 224..246 | 248..254 | 945..961 | 963..971 | 1072..1103 | 65345..65370 => c-32,
267			257 | 259 | 261 | 263 | 265 | 267 | 269 | 271 | 273 | 275 | 277 | 279 | 281 | 283 | 285 | 287 | 289 | 291 | 293 | 295 | 297 | 299 | 301 | 303 | 307 | 309 | 311 | 314 | 316 | 318 | 320 | 322 | 324 | 326 | 328 | 331 | 333 | 335 | 337 | 339 | 341 | 343 | 345 | 347 | 349 | 351 | 353 | 355 | 357 | 359 | 361 | 363 | 365 | 367 | 369 | 371 | 373 | 375 | 378 | 380 | 382 | 387 | 389 | 392 | 396 | 402 | 409 | 417 | 419 | 421 | 424 | 429 | 432 | 436 | 438 | 441 | 445 | 462 | 464 | 466 | 468 | 470 | 472 | 474 | 476 | 479 | 481 | 483 | 485 | 487 | 489 | 491 | 493 | 495 | 501 | 507 | 509 | 511 | 513 | 515 | 517 | 519 | 521 | 523 | 525 | 527 | 529 | 531 | 533 | 535 | 995 | 997 | 999 | 1001 | 1003 | 1005 | 1007 | 1121 | 1123 | 1125 | 1127 | 1129 | 1131 | 1133 | 1135 | 1137 | 1139 | 1141 | 1143 | 1145 | 1147 | 1149 | 1151 | 1153 | 1169 | 1171 | 1173 | 1175 | 1177 | 1179 | 1181 | 1183 | 1185 | 1187 | 1189 | 1191 | 1193 | 1195 | 1197 | 1199 | 1201 | 1203 | 1205 | 1207 | 1209 | 1211 | 1213 | 1215 | 1218 | 1220 | 1224 | 1228 | 1233 | 1235 | 1237 | 1239 | 1241 | 1243 | 1245 | 1247 | 1249 | 1251 | 1253 | 1255 | 1257 | 1259 | 1263 | 1265 | 1267 | 1269 | 1273 | 7681 | 7683 | 7685 | 7687 | 7689 | 7691 | 7693 | 7695 | 7697 | 7699 | 7701 | 7703 | 7705 | 7707 | 7709 | 7711 | 7713 | 7715 | 7717 | 7719 | 7721 | 7723 | 7725 | 7727 | 7729 | 7731 | 7733 | 7735 | 7737 | 7739 | 7741 | 7743 | 7745 | 7747 | 7749 | 7751 | 7753 | 7755 | 7757 | 7759 | 7761 | 7763 | 7765 | 7767 | 7769 | 7771 | 7773 | 7775 | 7777 | 7779 | 7781 | 7783 | 7785 | 7787 | 7789 | 7791 | 7793 | 7795 | 7797 | 7799 | 7801 | 7803 | 7805 | 7807 | 7809 | 7811 | 7813 | 7815 | 7817 | 7819 | 7821 | 7823 | 7825 | 7827 | 7829 | 7841 | 7843 | 7845 | 7847 | 7849 | 7851 | 7853 | 7855 | 7857 | 7859 | 7861 | 7863 | 7865 | 7867 | 7869 | 7871 | 7873 | 7875 | 7877 | 7879 | 7881 | 7883 | 7885 | 7887 | 7889 | 7891 | 7893 | 7895 | 7897 | 7899 | 7901 | 7903 | 7905 | 7907 | 7909 | 7911 | 7913 | 7915 | 7917 | 7919 | 7921 | 7923 | 7925 | 7927 | 7929 => c-1,
268			255 => c+121,
269			595 => c-210,
270			596 => c-206,
271			599 | 608 => c-205,
272			600..601 => c-202,
273			603 => c-203,
274			611 => c-207,
275			617 | 623 => c-211,
276			616 => c-209,
277			626 => c-213,
278			629 => c-214,
279			643 | 648 => c-218,
280			650..651 => c-217,
281			658 => c-219,
282			454 | 457 | 460 | 499 => c-2,
283			940 => c-38,
284			941..943 => c-37,
285			972 => c-64,
286			973..974 => c-63,
287			1105..1116 | 1118..1119 => c-80,
288			1377..1414 | 4304..4341 => c-48,
289			7936..7943 | 7952..7957 | 7968..7975 | 7984..7991 | 8000..8005 | 8017 | 8019 | 8021 | 8023 | 8032..8039 | 8064..8071 | 8080..8087 | 8096..8103 | 8112..8113 | 8144..8145 | 8160..8161 => c+8,
290			9424..9449 => c-26,
291			_ => c
292		}
293	}
294
295	/// Convert to lower case.
296	///
297	/// Most CAPE-OPEN string comparisons are case insensitive. By allowing converson to lower
298	/// case, we can use this in conjuntion with Eq, PartialEq, Hash, etc to make lookup tables
299	/// and comparisons without the need to convert to Rust's utf-8 encoded string (on Windows,
300	/// CapeString is UTF-16 encoded and null terminated).
301	///
302	/// Note that this is a simple conversion of the first character of each code point.
303	///
304	/// # Examples
305	///
306	/// ```
307	/// use cobia;
308	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
309	/// assert_eq!(s.to_lowercase(),cobia::CapeStringImpl::from_string("idealgasenthalpy"));
310	/// ```
311
312	pub fn to_lowercase(&self) -> Self {
313		let mut cs = CapeStringImpl::new();
314		cs.data.reserve(self.data.len());
315		for c in self.data.iter() {
316			cs.data.push(Self::to_lower_case(*c));
317		}
318		cs
319	}
320
321	/// Convert to upper case.
322	///
323	/// Most CAPE-OPEN string comparisons are case insensitive. By allowing converson to upper
324	/// case, we can use this in conjuntion with Eq, PartialEq, Hash, etc to make lookup tables
325	/// and comparisons without the need to convert to Rust's utf-8 encoded string (on Windows,
326	/// CapeString is UTF-16 encoded and null terminated).
327	///
328	/// Note that this is a simple conversion of the first character of each code point.
329	///
330	/// # Examples
331	///
332	/// ```
333	/// use cobia;
334	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
335	/// assert_eq!(s.to_uppercase(),cobia::CapeStringImpl::from_string("IDEALGASENTHALPY"));
336	/// ```
337
338	pub fn to_uppercase(&self) -> Self {
339		let mut cs = CapeStringImpl::new();
340		cs.data.reserve(self.data.len());
341		for c in self.data.iter() {
342			cs.data.push(Self::to_upper_case(*c));
343		}
344		cs
345	}
346
347	/// Case insentitive comparison
348	/// 
349	/// # Arguments
350	///	
351	/// * `other` - The other string to compare to
352	///
353	/// # Examples
354	///
355	/// ```
356	/// use cobia;
357	/// let s1=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
358	/// let s2=cobia::CapeStringImpl::from_string("IDEALGASENTHALPY");
359	/// assert_eq!(s1.eq_ignore_case(&s2),true);
360	/// ```
361	pub fn eq_ignore_case<T:CapeStringConstProvider>(&self, other: &T) -> bool {
362		let (ptr,len)=other.as_capechar_const_with_length();
363		let mut self_len:usize=self.data.len();
364		if self_len>0 {self_len-=1;}
365		let len=len as usize;
366		if self_len == len {
367			let mut ptr1=ptr;
368			for i in 0..len {
369				if CapeStringImpl::to_lower_case(unsafe { *ptr1 }) != CapeStringImpl::to_lower_case(self.data[i]) {
370					return false;
371				}
372				ptr1=unsafe { ptr1.add(1) };
373			}
374			return true;			
375		}
376		false
377	}
378
379}
380
381impl CapeStringConstProvider for CapeStringImpl {
382	///Return as CapeCharacter const pointer with length
383	///
384	/// The caller must ensure that the lifetime of the CapeStringImpl
385	/// is longer than the pointer returned.
386	///
387	/// # Examples
388	///
389	/// ```
390	/// use cobia;
391	/// use cobia::prelude::*;
392	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy"); //must remain in scope....
393	/// let (ptr,len)=s.as_capechar_const_with_length(); ///... while ptr is used
394	/// assert_eq!(len,16);
395	/// ```
396	fn as_capechar_const_with_length(&self) -> (*const C::CapeCharacter, C::CapeSize) {
397		if self.data.is_empty() {
398			("\0\0".as_ptr() as *const C::CapeCharacter, 0) //need just the terminating null
399		} else {
400			(self.data.as_ptr() as *const C::CapeCharacter, (self.data.len() - 1) as C::CapeSize) //length without the terminating null
401		}
402	}
403	///Return as CapeCharacter const pointer with length
404	///
405	/// The caller must ensure that the lifetime of the CapeStringImpl
406	/// is longer than the pointer returned.
407	///
408	/// # Examples
409	///
410	/// ```
411	/// use cobia;
412	/// use cobia::prelude::*;
413	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy"); //must remain in scope....
414	/// let ptr=s.as_capechar_const(); ///... while ptr is used
415	/// assert_eq!(unsafe{*ptr},'i' as u16);
416	/// ```
417	fn as_capechar_const(&self) -> *const C::CapeCharacter {
418		if self.data.is_empty() {
419			"\0\0".as_ptr() as *const C::CapeCharacter //need just the terminating null
420		} else {
421			self.data.as_ptr() as *const C::CapeCharacter
422		}
423	}
424}
425
426impl fmt::Display for CapeStringImpl {
427	/// Formats the CapeStringImpl error using the given formatter.
428	///
429	/// # Examples
430	///
431	/// ```
432	/// use cobia;
433	/// let s=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
434	/// assert_eq!(format!("{}",s),"idealGasEnthalpy");
435	/// ```
436	///
437	/// ```
438	/// use cobia;
439	/// let s=cobia::CapeStringImpl::new();
440	/// assert_eq!(format!("{}",s),"");
441	/// ```
442	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
443		if self.data.is_empty() {
444			write!(f, "")
445		} else {
446			let len = self.data.len() - 1;
447			write!(f, "{}", String::from_utf16_lossy(&self.data[..len]))
448		}
449	}
450}
451
452impl CapeStringProviderIn for CapeStringImpl {
453	fn as_cape_string_in(&self) -> C::ICapeString {
454		C::ICapeString {
455			vTbl:(&CapeStringImpl::CAPE_STRING_VTABLE as *const C::ICapeString_VTable).cast_mut(),
456			me:(self as *const CapeStringImpl).cast_mut() as *mut ::std::os::raw::c_void
457		}
458	}
459}
460
461impl CapeStringProviderOut for CapeStringImpl {
462	fn as_cape_string_out(&mut self) -> C::ICapeString {
463		C::ICapeString {
464			vTbl:(&CapeStringImpl::CAPE_STRING_VTABLE as *const C::ICapeString_VTable).cast_mut(),
465			me:(self as *const CapeStringImpl).cast_mut() as *mut ::std::os::raw::c_void
466		}
467	}
468}
469
470impl<T:CapeStringConstProvider> PartialEq<T> for CapeStringImpl {
471
472	/// Case sensitive comparison
473	///
474	/// # Arguments
475	/// * other - The other string to compare to
476	///
477	/// # Return
478	/// * true if the strings are equal, false otherwise.
479	///
480	/// # Examples
481	/// 
482	/// ```
483	/// use cobia;
484	/// let s1=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
485	/// let s2=cobia::CapeStringImpl::from_string("idealGasEnthalpy");
486	/// assert_eq!(s1==s2,true);
487	/// let s3=cobia::CapeStringImpl::from_string("IdealGasEnthalpy");
488	/// assert_eq!(s1==s3,false);
489	/// ```
490	fn eq(&self, other: &T) -> bool {
491		let (ptr,len)=other.as_capechar_const_with_length();
492		let mut self_len:usize=self.data.len();
493		if self_len>0 {self_len-=1;}
494		let len=len as usize;
495		if self_len == len {
496			let mut ptr1=ptr;
497			for i in 0..len {
498				if unsafe { *ptr1 } != self.data[i] {
499					return false;
500				}
501				ptr1=unsafe { ptr1.add(1) };
502			}
503			return true;			
504		}
505		false
506	}
507}
508
509impl Eq for CapeStringImpl {
510}
511
512impl std::hash::Hash for CapeStringImpl {
513	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
514		self.data.hash(state);
515	}
516}