1use ascii::{AsAsciiStrError, AsciiChar, AsciiStr, AsciiString, ToAsciiChar, ToAsciiCharError};
2use std::ascii::AsciiExt;
3use std::borrow::{Borrow, BorrowMut};
4use std::cmp::Ordering;
5use std::convert::{AsRef, AsMut, From, Into};
6use std::error::Error;
7use std::hash::{Hash, Hasher};
8use std::iter::{ExactSizeIterator, FromIterator, IntoIterator};
9use std::ops::{Deref, DerefMut};
10use std::str::{self, FromStr};
11use std::{fmt, mem, ptr, slice};
12use ::{PascalStr, PASCAL_STRING_BUF_SIZE};
13
14#[derive(Eq)]
19pub struct PascalString {
20 len: u8,
22 chars: [AsciiChar; PASCAL_STRING_BUF_SIZE]
24}
25
26impl PascalString {
27 #[inline]
29 pub fn new() -> Self {
30 Default::default()
31 }
32
33 #[inline]
37 pub fn from_fixed_ascii_array<C>(string_len: u8, char_array: [C; PASCAL_STRING_BUF_SIZE])
38 -> Result<Self, PascalStringCreateError>
39 where C: ToAsciiChar + Clone {
40 let mut pstring = PascalString::new();
41 pstring.len = string_len;
42 for i in 0..(pstring.len as usize) {
43 pstring[i] = try!(AsciiChar::from(char_array[i].clone()));
44 }
45 Ok(pstring)
46 }
47
48 #[inline]
53 pub fn from<B: AsRef<[u8]>>(bytes: B) -> Result<Self, PascalStringCreateError> {
54 PascalString::_from(bytes.as_ref())
55 }
56
57 fn _from(bytes: &[u8]) -> Result<Self, PascalStringCreateError> {
58 let len = bytes.len();
59 if len > PASCAL_STRING_BUF_SIZE {
60 return Err(PascalStringCreateError::InputTooLong);
61 }
62 let ascii = try!(AsciiStr::from_ascii(bytes));
64
65 let mut string = PascalString::new();
66 string.len = len as u8;
67 for i in 0..len {
68 string[i] = ascii[i];
69 }
70 Ok(string)
71 }
72
73 #[inline]
79 pub fn push<C: ToAsciiChar>(&mut self, character: C) {
80 self.try_push(character).unwrap();
81 }
82
83 #[inline]
88 pub fn try_push<C: ToAsciiChar>(&mut self, character: C) -> Result<(), PascalStringAppendError> {
89 self._try_push(try!(AsciiChar::from(character)))
90 }
91
92 fn _try_push(&mut self, ch: AsciiChar) -> Result<(), PascalStringAppendError> {
93 if self.is_full() {
94 return Err(PascalStringAppendError::NoRoom)
95 }
96 self.len += 1;
97 let idx = self.len - 1;
98 self[idx] = ch;
99 self.set_trailing_byte_to_null();
100 Ok(())
101 }
102
103 #[inline]
109 pub fn push_str<S: AsRef<str>>(&mut self, s: S) {
110 self.try_push_str(s).unwrap();
111 }
112
113 #[inline]
117 pub fn try_push_str<S: AsRef<str>>(&mut self, s: S) -> Result<(), PascalStringAppendError> {
118 self._try_push_str(s.as_ref())
119 }
120
121 fn _try_push_str(&mut self, s: &str) -> Result<(), PascalStringAppendError> {
122 let ascii: &[AsciiChar] = try!(AsciiStr::from_ascii(s)).as_ref();
123 let slen = self.len();
124 let alen = ascii.len();
125 if slen + alen > PASCAL_STRING_BUF_SIZE {
126 return Err(PascalStringAppendError::NoRoom);
127 }
128 for i in 0..alen {
129 self.chars[(i + slen)] = ascii[i];
130 }
131 self.len += alen as u8;
132 Ok(())
133 }
134
135 pub fn pop(&mut self) -> Option<AsciiChar> {
139 if self.is_empty() {
140 return None;
141 }
142 let c = self.chars[self.len as usize];
143 self.len -= 1;
144 self.set_trailing_byte_to_null();
145 Some(c)
146 }
147
148 pub fn remove(&mut self, index: u8) -> AsciiChar {
154 assert!(self.len > index);
155 assert!(!self.is_empty());
156 let len = self.len as usize;
157 let index = index as usize;
158 let c = self[index];
159 unsafe {
162 let ptr = self.as_mut_ptr().offset(index as isize);
163 ptr::copy(ptr.offset(1), ptr, len - index - 1);
164 }
165 self.len -= 1;
166 self.set_trailing_byte_to_null();
167 c
168 }
169
170 #[inline]
176 pub fn insert<C: ToAsciiChar>(&mut self, ch: C, index: u8) {
177 self._insert(AsciiChar::from(ch).unwrap(), index)
178 }
179
180 fn _insert(&mut self, ch: AsciiChar, index: u8) {
181 assert!(self.len > index);
182 assert!(!self.is_full());
183 let len = self.len as usize;
184 let index = index as isize;
185 unsafe {
188 let ptr = self.as_mut_ptr().offset(index);
189 ptr::copy(ptr, ptr.offset(1), len - index.abs() as usize - 1);
190 }
191 self[len] = ch;
192 self.len += 1;
193 self.set_trailing_byte_to_null();
194 }
195
196 #[inline]
200 pub fn clear(&mut self) {
201 self.len = 0;
202 self.set_trailing_byte_to_null();
203 }
204
205 #[inline]
211 pub fn to_array(self) -> [u8; PASCAL_STRING_BUF_SIZE + 1] {
212 self.into()
213 }
214
215 #[inline]
219 fn set_trailing_byte_to_null(&mut self) {
220 if !self.is_full() {
221 self.chars[self.len as usize] = AsciiChar::Null;
222 }
223 }
224}
225
226impl Default for PascalString {
227 #[inline]
228 fn default() -> Self {
229 PascalString {
230 len: 0,
231 chars: [AsciiChar::Null; PASCAL_STRING_BUF_SIZE]
232 }
233 }
234}
235
236impl Clone for PascalString {
237 fn clone(&self) -> Self {
238 let mut clone = PascalString::default();
239 clone.len = self.len;
240 unsafe {
241 ptr::copy_nonoverlapping(&self.chars, &mut clone.chars, PASCAL_STRING_BUF_SIZE);
242 }
243 clone
244 }
245}
246
247impl<S: AsRef<PascalStr> + ?Sized> PartialEq<S> for PascalString {
248 fn eq(&self, other: &S) -> bool {
249 let other = other.as_ref();
250 if self.len() != other.len() {
251 return false;
252 }
253 self.chars().zip(other.chars()).all(|(c0, c1)| c0 == c1)
254 }
255}
256
257impl Ord for PascalString {
258 #[inline]
259 fn cmp(&self, other: &Self) -> Ordering {
260 let ascii0: &[AsciiChar] = &self.chars;
261 let ascii1: &[AsciiChar] = &other.chars;
262 ascii0.cmp(ascii1)
263 }
264}
265
266impl<S: AsRef<PascalStr> + ?Sized> PartialOrd<S> for PascalString {
267 fn partial_cmp(&self, other: &S) -> Option<Ordering> {
268 let other: &AsciiStr = other.as_ref().as_ref();
269 let self_asciistr: &AsciiStr = self.as_ref();
270 self_asciistr.partial_cmp(&other)
271 }
272}
273
274impl Hash for PascalString {
275 #[inline]
276 fn hash<H: Hasher>(&self, state: &mut H) {
277 state.write_u8(self.len);
278 state.write(self.as_ref());
279 }
280}
281
282impl AsciiExt for PascalString {
283 type Owned = Self;
284
285 fn is_ascii(&self) -> bool {
286 true
287 }
288
289 fn to_ascii_uppercase(&self) -> Self::Owned {
290 let mut upper = self.clone();
291 upper.make_ascii_uppercase();
292 upper
293 }
294
295 fn to_ascii_lowercase(&self) -> Self::Owned {
296 let mut lower = self.clone();
297 lower.make_ascii_lowercase();
298 lower
299 }
300
301 fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
302 self.chars().zip(other.chars()).all(|(c0, c1)| c0.eq_ignore_ascii_case(&c1))
303 }
304
305 #[inline]
306 fn make_ascii_uppercase(&mut self) {
307 for c in self.chars_mut() {
308 c.make_ascii_uppercase();
309 }
310 }
311
312 #[inline]
313 fn make_ascii_lowercase(&mut self) {
314 for c in self.chars_mut() {
315 c.make_ascii_lowercase();
316 }
317 }
318}
319
320impl fmt::Debug for PascalString {
321 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
322 write!(fmtr, "{}", self)
323 }
324}
325
326impl fmt::Display for PascalString {
327 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
328 fmtr.pad(self.as_ref())
329 }
330}
331
332impl Deref for PascalString {
333 type Target = PascalStr;
334 fn deref(&self) -> &Self::Target {
335 let ascii_str: &[AsciiChar] = self.as_ref();
336 unsafe {
337 mem::transmute(ascii_str)
338 }
339 }
340}
341
342impl DerefMut for PascalString {
343 fn deref_mut(&mut self) -> &mut Self::Target {
344 let ascii_str: &mut [AsciiChar] = self.as_mut();
345 unsafe {
346 mem::transmute(ascii_str)
347 }
348 }
349}
350
351impl AsRef<PascalStr> for PascalString {
352 fn as_ref(&self) -> &PascalStr {
353 self.deref()
354 }
355}
356
357impl AsRef<str> for PascalString {
358 fn as_ref(&self) -> &str {
359 let bytes: &[u8] = self.as_ref();
360 str::from_utf8(bytes).unwrap()
361 }
362}
363
364impl AsRef<[u8]> for PascalString {
365 fn as_ref(&self) -> &[u8] {
366 unsafe {
367 slice::from_raw_parts(self.chars.as_ptr() as *const u8, self.len as usize)
368 }
369 }
370}
371
372impl AsRef<AsciiStr> for PascalString {
373 fn as_ref(&self) -> &AsciiStr {
374 let bytes: &[u8] = self.as_ref();
375 AsciiStr::from_ascii(bytes).unwrap()
376 }
377}
378
379impl AsRef<[AsciiChar]> for PascalString {
380 fn as_ref(&self) -> &[AsciiChar] {
381 unsafe {
382 slice::from_raw_parts(self.chars.as_ptr(), self.len as usize)
383 }
384 }
385}
386
387impl AsMut<[AsciiChar]> for PascalString {
388 fn as_mut(&mut self) -> &mut [AsciiChar] {
389 unsafe {
390 slice::from_raw_parts_mut(self.chars.as_mut_ptr(), self.len as usize)
391 }
392 }
393}
394
395impl Borrow<PascalStr> for PascalString {
396 #[inline]
397 fn borrow(&self) -> &PascalStr {
398 self.deref()
399 }
400}
401
402impl BorrowMut<PascalStr> for PascalString {
403 #[inline]
404 fn borrow_mut(&mut self) -> &mut PascalStr {
405 self.deref_mut()
406 }
407}
408
409impl Borrow<str> for PascalString {
410 #[inline]
411 fn borrow(&self) -> &str {
412 self.as_ref()
413 }
414}
415
416impl Borrow<[u8]> for PascalString {
417 #[inline]
418 fn borrow(&self) -> &[u8] {
419 self.as_ref()
420 }
421}
422
423impl Borrow<AsciiStr> for PascalString {
424 #[inline]
425 fn borrow(&self) -> &AsciiStr {
426 self.as_ref()
427 }
428}
429
430impl Borrow<[AsciiChar]> for PascalString {
431 #[inline]
432 fn borrow(&self) -> &[AsciiChar] {
433 self.as_ref()
434 }
435}
436
437impl BorrowMut<[AsciiChar]> for PascalString {
438 #[inline]
439 fn borrow_mut(&mut self) -> &mut [AsciiChar] {
440 self.as_mut()
441 }
442}
443
444impl Into<[u8; PASCAL_STRING_BUF_SIZE + 1]> for PascalString {
445 fn into(self) -> [u8; PASCAL_STRING_BUF_SIZE + 1] {
446 let mut array = [0u8; PASCAL_STRING_BUF_SIZE + 1];
447 array[0] = self.len;
448 unsafe {
449 let chars_ptr = &self.chars as *const _ as *const [u8; PASCAL_STRING_BUF_SIZE];
450 let array_ptr = (&mut array as *mut _).offset(1) as *mut [u8; PASCAL_STRING_BUF_SIZE];
451 ptr::copy_nonoverlapping(chars_ptr, array_ptr, PASCAL_STRING_BUF_SIZE);
452 }
453 array
454 }
455}
456
457impl Into<String> for PascalString {
458 #[inline]
459 fn into(self) -> String {
460 String::from_utf8_lossy(self.as_ref()).into_owned()
461 }
462}
463
464impl Into<Vec<u8>> for PascalString {
465 fn into(self) -> Vec<u8> {
466 let mut v = Vec::with_capacity(self.len());
467 v.extend_from_slice(self.as_ref());
468 v
469 }
470}
471
472impl Into<Vec<AsciiChar>> for PascalString {
473 fn into(self) -> Vec<AsciiChar> {
474 let mut v = Vec::with_capacity(self.len());
475 v.extend_from_slice(self.as_ref());
476 v
477 }
478}
479
480impl Into<AsciiString> for PascalString {
481 fn into(self) -> AsciiString {
482 AsciiString::from_ascii(self).unwrap()
483 }
484}
485
486impl FromStr for PascalString {
487 type Err = PascalStringCreateError;
488 fn from_str(s: &str) -> Result<Self, Self::Err> {
489 PascalString::from(s)
490 }
491}
492
493impl FromIterator<AsciiChar> for PascalString {
494 fn from_iter<I: IntoIterator<Item = AsciiChar>>(iter: I) -> Self {
495 let mut iter = iter.into_iter();
496 let mut pstring = PascalString::new();
497 while let Some(ch) = iter.next() {
498 let _ = pstring.try_push(ch);
501 }
502 pstring
503 }
504}
505
506impl IntoIterator for PascalString {
507 type Item = AsciiChar;
508 type IntoIter = IntoChars;
509 fn into_iter(self) -> Self::IntoIter {
510 IntoChars(self)
511 }
512}
513
514#[derive(Debug)]
516pub struct IntoChars(PascalString);
517
518impl Iterator for IntoChars {
519 type Item = AsciiChar;
520 fn next(&mut self) -> Option<Self::Item> {
521 if !self.0.is_empty() {
522 Some(self.0.remove(0))
523 } else {
524 None
525 }
526 }
527}
528
529impl ExactSizeIterator for IntoChars {
530 fn len(&self) -> usize {
531 self.0.len()
532 }
533}
534
535#[derive(Debug, PartialEq)]
537pub enum PascalStringCreateError {
538 InputTooLong,
540 NotValidAscii(AsciiError)
542}
543
544impl fmt::Display for PascalStringCreateError {
545 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
546 match *self {
547 PascalStringCreateError::InputTooLong => fmtr.pad(self.description()),
548 PascalStringCreateError::NotValidAscii(ref e) => write!(fmtr, "{}: {}", self.description(), e)
549 }
550 }
551}
552
553impl Error for PascalStringCreateError {
554 fn description(&self) -> &str {
555 match *self {
556 PascalStringCreateError::InputTooLong => "the input data is longer than what a PascalString can store",
557 PascalStringCreateError::NotValidAscii(_) =>"could not convert input data to ascii"
558 }
559 }
560
561 fn cause(&self) -> Option<&Error> {
562 if let PascalStringCreateError::NotValidAscii(ref e) = *self {
563 Some(e)
564 } else {
565 None
566 }
567 }
568}
569
570impl<E: Into<AsciiError>> From<E> for PascalStringCreateError {
571 #[inline]
572 fn from(e: E) -> Self {
573 PascalStringCreateError::NotValidAscii(e.into())
574 }
575}
576
577#[derive(Debug, PartialEq)]
579pub enum PascalStringAppendError {
580 NoRoom,
582 NotValidAscii(AsciiError)
584}
585
586impl fmt::Display for PascalStringAppendError {
587 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
588 match *self {
589 PascalStringAppendError::NoRoom => fmtr.pad(self.description()),
590 PascalStringAppendError::NotValidAscii(ref e) => write!(fmtr, "{}: {}", self.description(), e)
591 }
592 }
593}
594
595impl Error for PascalStringAppendError {
596 fn description(&self) -> &str {
597 match *self {
598 PascalStringAppendError::NoRoom => "there is no space left in the string to append the data",
599 PascalStringAppendError::NotValidAscii(_) =>"could not convert string to ascii"
600 }
601 }
602
603 fn cause(&self) -> Option<&Error> {
604 if let PascalStringAppendError::NotValidAscii(ref e) = *self {
605 Some(e)
606 } else {
607 None
608 }
609 }
610}
611
612impl<E: Into<AsciiError>> From<E> for PascalStringAppendError {
613 #[inline]
614 fn from(e: E) -> Self {
615 PascalStringAppendError::NotValidAscii(e.into())
616 }
617}
618
619#[derive(Debug, PartialEq)]
621pub enum AsciiError {
622 Char(ToAsciiCharError),
624 Str(AsAsciiStrError)
626}
627
628impl fmt::Display for AsciiError {
629 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
630 match *self {
631 AsciiError::Char(ref e) => write!(fmtr, "{}: {}", self.description(), e),
632 AsciiError::Str(ref e) => write!(fmtr, "{}: {}", self.description(), e)
633 }
634 }
635}
636
637impl Error for AsciiError {
638 fn description(&self) -> &str {
639 match *self {
640 AsciiError::Char(_) => "could not convert character to ascii: {}",
641 AsciiError::Str(_) =>"could not convert string to ascii: {}"
642 }
643 }
644
645 fn cause(&self) -> Option<&Error> {
646 match *self {
647 AsciiError::Char(ref e) => Some(e),
648 AsciiError::Str(ref e) => Some(e)
649 }
650 }
651}
652
653impl From<ToAsciiCharError> for AsciiError {
654 #[inline]
655 fn from(e: ToAsciiCharError) -> Self {
656 AsciiError::Char(e)
657 }
658}
659
660impl From<AsAsciiStrError> for AsciiError {
661 #[inline]
662 fn from(e: AsAsciiStrError) -> Self {
663 AsciiError::Str(e)
664 }
665}