pascal_string/
pascal_str.rs1use ascii::{AsciiChar, AsciiStr};
2use std::ascii::AsciiExt;
3use std::borrow::{Cow, ToOwned};
4use std::cmp::Ordering;
5use std::convert::AsRef;
6use std::error::Error;
7use std::ffi::{CStr, CString};
8use std::iter::{ExactSizeIterator, Iterator};
9use std::ops::{Index, IndexMut, Range, RangeFull, RangeFrom, RangeTo};
10use std::slice::{Iter, IterMut};
11use std::{fmt, isize};
12use ::{PASCAL_STRING_BUF_SIZE, PascalString};
13
14#[derive(Eq, Hash, Ord)]
16pub struct PascalStr {
17 string: AsciiStr
19}
20
21impl PascalStr {
22 #[inline]
24 pub fn as_ptr(&self) -> *const AsciiChar {
25 self.string.as_ptr()
26 }
27
28 #[inline]
30 pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
31 self.string.as_mut_ptr()
32 }
33
34 #[inline]
36 pub fn as_str(&self) -> &str {
37 self.string.as_str()
38 }
39
40 #[inline]
45 pub fn as_cstr(&self) -> Result<Cow<CStr>, InteriorNullError> {
46 match self.chars().position(|&c| c == AsciiChar::Null) {
47 Some(pos) if pos != (self.len() - 1) => Err(InteriorNullError(pos)),
48 _ if self.is_full() && self.string[PASCAL_STRING_BUF_SIZE - 1] != AsciiChar::Null => {
49 let str_clone = self.to_owned();
50 Ok(Cow::Owned(CString::new(str_clone).unwrap()))
51 }
52 _ => Ok(Cow::Borrowed(CStr::from_bytes_with_nul(self.as_ref()).unwrap()))
53 }
54 }
55
56 #[inline]
58 pub fn len(&self) -> usize {
59 self.string.len()
60 }
61
62 #[inline]
64 pub fn is_empty(&self) -> bool {
65 self.len() == 0
66 }
67
68 #[inline]
72 pub fn is_full(&self) -> bool {
73 self.len() == PASCAL_STRING_BUF_SIZE
74 }
75
76 #[inline]
78 pub fn chars<'a>(&'a self) -> Chars<'a> {
79 Chars(self.string.as_slice().iter())
80 }
81
82 #[inline]
84 pub fn chars_mut<'a>(&'a mut self) -> CharsMut<'a> {
85 CharsMut(self.string.as_mut_slice().iter_mut())
86 }
87
88 #[inline]
90 pub fn lines(&self) -> Lines {
91 Lines {
92 current_index: 0,
93 string: &self
94 }
95 }
96
97 #[inline]
108 pub fn get_unchecked(&self, index: usize) -> AsciiChar {
109 assert!(index < PASCAL_STRING_BUF_SIZE);
110 let ptr = self.as_ptr();
111 unsafe {
112 *ptr.offset(index as isize)
113 }
114 }
115}
116
117impl<S: AsRef<PascalStr> + ?Sized> PartialEq<S> for PascalStr {
118 fn eq(&self, other: &S) -> bool {
119 let other = other.as_ref();
120 self.string.eq(&other.string)
121 }
122}
123
124impl<S: AsRef<PascalStr> + ?Sized> PartialOrd<S> for PascalStr {
125 fn partial_cmp(&self, other: &S) -> Option<Ordering> {
126 let other = other.as_ref();
127 self.string.partial_cmp(&other.string)
128 }
129}
130
131impl AsciiExt for PascalStr {
132 type Owned = PascalString;
133
134 fn is_ascii(&self) -> bool {
135 true
136 }
137
138 fn to_ascii_uppercase(&self) -> Self::Owned {
139 let bytes: &[u8] = self.as_ref();
140 let mut upper = PascalString::from(bytes).unwrap();
141 upper.make_ascii_uppercase();
142 upper
143 }
144
145 fn to_ascii_lowercase(&self) -> Self::Owned {
146 let bytes: &[u8] = self.as_ref();
147 let mut lower = PascalString::from(bytes).unwrap();
148 lower.make_ascii_lowercase();
149 lower
150 }
151
152 fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
153 self.string.eq_ignore_ascii_case(&other.string)
154 }
155
156 fn make_ascii_uppercase(&mut self) {
157 self.string.make_ascii_uppercase()
158 }
159
160 fn make_ascii_lowercase(&mut self) {
161 self.string.make_ascii_lowercase()
162 }
163}
164
165impl fmt::Debug for PascalStr {
166 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
167 fmtr.pad(self.as_ref())
168 }
169}
170
171impl fmt::Display for PascalStr {
172 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
173 fmtr.pad(self.as_ref())
174 }
175}
176
177impl ToOwned for PascalStr {
178 type Owned = PascalString;
179 fn to_owned(&self) -> Self::Owned {
180 PascalString::from(&self.string).unwrap()
181 }
182}
183
184impl AsRef<PascalStr> for PascalStr {
185 fn as_ref(&self) -> &Self {
186 &self
187 }
188}
189
190impl AsRef<str> for PascalStr {
191 fn as_ref(&self) -> &str {
192 self.string.as_ref()
193 }
194}
195
196impl AsRef<[u8]> for PascalStr {
197 fn as_ref(&self) -> &[u8] {
198 self.string.as_ref()
199 }
200}
201
202impl AsRef<AsciiStr> for PascalStr {
203 fn as_ref(&self) -> &AsciiStr {
204 &self.string
205 }
206}
207
208impl AsMut<AsciiStr> for PascalStr {
209 fn as_mut(&mut self) -> &mut AsciiStr {
210 &mut self.string
211 }
212}
213
214impl AsRef<[AsciiChar]> for PascalStr {
215 fn as_ref(&self) -> &[AsciiChar] {
216 self.string.as_ref()
217 }
218}
219
220impl AsMut<[AsciiChar]> for PascalStr {
221 fn as_mut(&mut self) -> &mut [AsciiChar] {
222 self.string.as_mut()
223 }
224}
225
226impl Index<u8> for PascalStr {
227 type Output = AsciiChar;
228 fn index(&self, index: u8) -> &Self::Output {
229 let index = index as usize;
230 assert!(index < self.len());
231 &self.string[index]
232 }
233}
234
235impl IndexMut<u8> for PascalStr {
236 fn index_mut(&mut self, index: u8) -> &mut Self::Output {
237 let index = index as usize;
238 assert!(index < self.len());
239 &mut self.string[index]
240 }
241}
242
243impl Index<usize> for PascalStr {
244 type Output = AsciiChar;
245 fn index(&self, index: usize) -> &Self::Output {
246 assert!(index < self.len());
247 &self.string[index]
248 }
249}
250
251impl IndexMut<usize> for PascalStr {
252 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
253 assert!(index < self.len());
254 &mut self.string[index]
255 }
256}
257
258impl Index<i32> for PascalStr {
259 type Output = AsciiChar;
260 fn index(&self, index: i32) -> &Self::Output {
261 assert!(index >= 0);
262 assert!((index as usize) < self.len());
263 &self.string[index as usize]
264 }
265}
266
267impl IndexMut<i32> for PascalStr {
268 fn index_mut(&mut self, index: i32) -> &mut Self::Output {
269 assert!(index >= 0);
270 assert!((index as usize) < self.len());
271 &mut self.string[index as usize]
272 }
273}
274
275impl Index<RangeFull> for PascalStr {
276 type Output = [AsciiChar];
277 fn index(&self, _: RangeFull) -> &Self::Output {
278 let char_array: &[AsciiChar] = self.string.as_ref();
279 &char_array[..]
280 }
281}
282
283impl IndexMut<RangeFull> for PascalStr {
284 fn index_mut(&mut self, _: RangeFull) -> &mut Self::Output {
285 let char_array: &mut [AsciiChar] = self.string.as_mut();
286 &mut char_array[..]
287 }
288}
289
290impl Index<Range<u8>> for PascalStr {
291 type Output = [AsciiChar];
292 fn index(&self, range: Range<u8>) -> &Self::Output {
293 assert!((range.end as usize) < self.len());
294 let char_array: &[AsciiChar] = self.string.as_ref();
295 &char_array[range.start as usize..range.end as usize]
296 }
297}
298
299impl IndexMut<Range<u8>> for PascalStr {
300 fn index_mut(&mut self, range: Range<u8>) -> &mut Self::Output {
301 assert!((range.end as usize) < self.len());
302 let char_array: &mut [AsciiChar] = self.string.as_mut();
303 &mut char_array[range.start as usize..range.end as usize]
304 }
305}
306
307impl Index<Range<usize>> for PascalStr {
308 type Output = [AsciiChar];
309 fn index(&self, range: Range<usize>) -> &Self::Output {
310 assert!(range.end < self.len());
311 let char_array: &[AsciiChar] = self.string.as_ref();
312 &char_array[range.start..range.end]
313 }
314}
315
316impl IndexMut<Range<usize>> for PascalStr {
317 fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
318 assert!(range.end < self.len());
319 let char_array: &mut [AsciiChar] = self.string.as_mut();
320 &mut char_array[range.start..range.end]
321 }
322}
323
324impl Index<Range<i32>> for PascalStr {
325 type Output = [AsciiChar];
326 fn index(&self, range: Range<i32>) -> &Self::Output {
327 assert!(range.start >= 0);
328 assert!((range.start as usize) < self.len());
329 assert!(range.end >= 0);
330 assert!((range.end as usize) < self.len());
331 let char_array: &[AsciiChar] = self.string.as_ref();
332 &char_array[range.start as usize..]
333 }
334}
335
336impl IndexMut<Range<i32>> for PascalStr {
337 fn index_mut(&mut self, range: Range<i32>) -> &mut Self::Output {
338 assert!(range.start >= 0);
339 assert!((range.start as usize) < self.len());
340 assert!(range.end >= 0);
341 assert!((range.end as usize) < self.len());
342 let char_array: &mut [AsciiChar] = self.string.as_mut();
343 &mut char_array[range.start as usize..]
344 }
345}
346
347impl Index<RangeFrom<u8>> for PascalStr {
348 type Output = [AsciiChar];
349 fn index(&self, range: RangeFrom<u8>) -> &Self::Output {
350 assert!((range.start as usize) < self.len());
351 let char_array: &[AsciiChar] = self.string.as_ref();
352 &char_array[range.start as usize..]
353 }
354}
355
356impl IndexMut<RangeFrom<u8>> for PascalStr {
357 fn index_mut(&mut self, range: RangeFrom<u8>) -> &mut Self::Output {
358 assert!((range.start as usize) < self.len());
359 let char_array: &mut [AsciiChar] = self.string.as_mut();
360 &mut char_array[range.start as usize..]
361 }
362}
363
364impl Index<RangeFrom<usize>> for PascalStr {
365 type Output = [AsciiChar];
366 fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
367 assert!(range.start < self.len());
368 let char_array: &[AsciiChar] = self.string.as_ref();
369 &char_array[range.start..]
370 }
371}
372
373impl IndexMut<RangeFrom<usize>> for PascalStr {
374 fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
375 assert!(range.start < self.len());
376 let char_array: &mut [AsciiChar] = self.string.as_mut();
377 &mut char_array[range.start..]
378 }
379}
380
381impl Index<RangeFrom<i32>> for PascalStr {
382 type Output = [AsciiChar];
383 fn index(&self, range: RangeFrom<i32>) -> &Self::Output {
384 assert!(range.start >= 0);
385 assert!((range.start as usize) < self.len());
386 let char_array: &[AsciiChar] = self.string.as_ref();
387 &char_array[range.start as usize..]
388 }
389}
390
391impl IndexMut<RangeFrom<i32>> for PascalStr {
392 fn index_mut(&mut self, range: RangeFrom<i32>) -> &mut Self::Output {
393 assert!(range.start >= 0);
394 assert!((range.start as usize) < self.len());
395 let char_array: &mut [AsciiChar] = self.string.as_mut();
396 &mut char_array[range.start as usize..]
397 }
398}
399
400impl Index<RangeTo<u8>> for PascalStr {
401 type Output = [AsciiChar];
402 fn index(&self, range: RangeTo<u8>) -> &Self::Output {
403 assert!((range.end as usize) < self.len());
404 let char_array: &[AsciiChar] = self.string.as_ref();
405 &char_array[..range.end as usize]
406 }
407}
408
409impl IndexMut<RangeTo<u8>> for PascalStr {
410 fn index_mut(&mut self, range: RangeTo<u8>) -> &mut Self::Output {
411 assert!((range.end as usize) < self.len());
412 let char_array: &mut [AsciiChar] = self.string.as_mut();
413 &mut char_array[..range.end as usize]
414 }
415}
416
417impl Index<RangeTo<usize>> for PascalStr {
418 type Output = [AsciiChar];
419 fn index(&self, range: RangeTo<usize>) -> &Self::Output {
420 assert!(range.end < self.len());
421 let char_array: &[AsciiChar] = self.string.as_ref();
422 &char_array[..range.end]
423 }
424}
425
426impl IndexMut<RangeTo<usize>> for PascalStr {
427 fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
428 assert!(range.end < self.len());
429 let char_array: &mut [AsciiChar] = self.string.as_mut();
430 &mut char_array[..range.end]
431 }
432}
433
434impl Index<RangeTo<i32>> for PascalStr {
435 type Output = [AsciiChar];
436 fn index(&self, range: RangeTo<i32>) -> &Self::Output {
437 assert!(range.end >= 0);
438 assert!((range.end as usize) < self.len());
439 let char_array: &[AsciiChar] = self.string.as_ref();
440 &char_array[..range.end as usize]
441 }
442}
443
444impl IndexMut<RangeTo<i32>> for PascalStr {
445 fn index_mut(&mut self, range: RangeTo<i32>) -> &mut Self::Output {
446 assert!(range.end >= 0);
447 assert!((range.end as usize) < self.len());
448 let char_array: &mut [AsciiChar] = self.string.as_mut();
449 &mut char_array[..range.end as usize]
450 }
451}
452
453impl<'a> IntoIterator for &'a PascalStr {
454 type Item = &'a AsciiChar;
455 type IntoIter = Chars<'a>;
456 fn into_iter(self) -> Self::IntoIter {
457 self.chars()
458 }
459}
460
461impl<'a> IntoIterator for &'a mut PascalStr {
462 type Item = &'a mut AsciiChar;
463 type IntoIter = CharsMut<'a>;
464 fn into_iter(self) -> Self::IntoIter {
465 self.chars_mut()
466 }
467}
468
469#[derive(Debug)]
471pub struct Chars<'a>(Iter<'a, AsciiChar>);
472
473impl<'a> Iterator for Chars<'a> {
474 type Item = &'a AsciiChar;
475
476 #[inline]
477 fn next(&mut self) -> Option<Self::Item> {
478 self.0.next()
479 }
480}
481
482impl<'a> ExactSizeIterator for Chars<'a> {
483 #[inline]
484 fn len(&self) -> usize {
485 self.0.len()
486 }
487}
488
489#[derive(Debug)]
491pub struct CharsMut<'a>(IterMut<'a, AsciiChar>);
492
493impl<'a> Iterator for CharsMut<'a> {
494 type Item = &'a mut AsciiChar;
495
496 #[inline]
497 fn next(&mut self) -> Option<Self::Item> {
498 self.0.next()
499 }
500}
501
502impl<'a> ExactSizeIterator for CharsMut<'a> {
503 #[inline]
504 fn len(&self) -> usize {
505 self.0.len()
506 }
507}
508
509#[derive(Debug)]
511pub struct Lines<'a> {
512 current_index: usize,
513 string: &'a PascalStr
514}
515
516impl<'a> Iterator for Lines<'a> {
517 type Item = &'a AsciiStr;
518
519 fn next(&mut self) -> Option<Self::Item> {
520 let curr_idx = self.current_index;
521 let len = self.string.len();
522 if curr_idx >= len {
523 return None;
524 }
525
526 let mut next_idx = None;
527 for i in curr_idx..len {
528 if self.string[i] == AsciiChar::LineFeed {
529 next_idx = Some(i);
530 break;
531 }
532 }
533 let next_idx = match next_idx {
534 Some(i) => i,
535 None => return None
536 };
537 let line: &AsciiStr = From::from(&self.string[curr_idx..next_idx]);
538
539 self.current_index = next_idx + 1; Some(line)
541 }
542}
543
544impl<'a> ExactSizeIterator for Lines<'a> {
545 #[inline]
546 fn len(&self) -> usize {
547 self.string.chars().skip(self.current_index).filter(|&&c| c == AsciiChar::LineFeed).count()
548 }
549}
550
551#[derive(Clone, Debug, Hash)]
552pub struct InteriorNullError(usize);
553
554impl InteriorNullError {
555 #[inline]
556 pub fn interior_null_index(&self) -> usize {
557 self.0
558 }
559}
560
561impl fmt::Display for InteriorNullError {
562 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
563 write!(fmtr, "interior null at {}", self.0)
564 }
565}
566
567impl Error for InteriorNullError {
568 fn description(&self) -> &str {
569 "an interior null was found when creating a CStr from a pascal string"
570 }
571}