Skip to content

Commit c351e7e

Browse files
author
Thomas Bahn
committed
Merge pull request #17 from tormol/into_ascii
Add traits IntoAscii* to replace (Owned)AsciiCast
2 parents 082c577 + a6c80f7 commit c351e7e

File tree

5 files changed

+359
-23
lines changed

5 files changed

+359
-23
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ before_script:
1515
script:
1616
- |
1717
travis-cargo build &&
18-
travis-cargo test &&
18+
travis-cargo --skip 1.1.0 test &&
1919
travis-cargo --only stable doc
2020
2121
after_success:

src/ascii.rs

+88-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::mem::transmute;
22
use std::fmt;
3-
#[cfg(feature="unstable")]
3+
use std::error::Error;
44
use std::ascii::AsciiExt;
55

66
use AsciiCast;
@@ -279,7 +279,7 @@ pub enum Ascii {
279279
}
280280

281281
impl Ascii {
282-
/// Constructs an Ascii character from a `char`.
282+
/// Constructs an ASCII character from a `u8`, `char` or other character type.
283283
///
284284
/// # Failure
285285
///
@@ -292,11 +292,13 @@ impl Ascii {
292292
/// assert_eq!(a.as_char(), 'g');
293293
/// ```
294294
#[inline]
295-
pub fn from(ch: char) -> Result<Ascii, ()> {
296-
unsafe{if ch as u32 <= 0x7F {
297-
return Ok(ch.to_ascii_nocheck());
298-
}}
299-
Err(())
295+
pub fn from<C:IntoAscii>(ch: C) -> Result<Self, ()> {
296+
ch.into_ascii().map_err(|_| () )
297+
}
298+
299+
/// Constructs an ASCII character from a `char` or `u8` without any checks.
300+
pub unsafe fn from_unchecked<C:IntoAscii>(ch: C) -> Self {
301+
ch.into_ascii_unchecked()
300302
}
301303

302304
/// Constructs an Ascii character from a `u8`.
@@ -530,10 +532,79 @@ impl<'a> AsciiCast<'a> for char {
530532
}
531533
}
532534

535+
536+
/// Error returned by `IntoAscii`.
537+
#[derive(PartialEq)]
538+
pub struct IntoAsciiError(());
539+
540+
const ERRORMSG_CHAR: &'static str = "not an ASCII character";
541+
542+
impl fmt::Debug for IntoAsciiError {
543+
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
544+
write!(fmtr, "{}", ERRORMSG_CHAR)
545+
}
546+
}
547+
548+
impl fmt::Display for IntoAsciiError {
549+
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
550+
write!(fmtr, "{}", ERRORMSG_CHAR)
551+
}
552+
}
553+
554+
impl Error for IntoAsciiError {
555+
fn description(&self) -> &'static str {
556+
ERRORMSG_CHAR
557+
}
558+
}
559+
560+
561+
/// Convert `char`, `u8` and other character types to `Ascii`.
562+
pub trait IntoAscii : AsciiExt {
563+
/// Convert to `Ascii` without checking that it is an ASCII character.
564+
unsafe fn into_ascii_unchecked(self) -> Ascii;
565+
/// Convert to `Ascii`.
566+
fn into_ascii(self) -> Result<Ascii,IntoAsciiError>;
567+
}
568+
569+
#[cfg(feature = "unstable")]
570+
impl IntoAscii for Ascii {
571+
fn into_ascii(self) -> Result<Ascii,IntoAsciiError> {
572+
Ok(self)
573+
}
574+
unsafe fn into_ascii_unchecked(self) -> Ascii {
575+
self
576+
}
577+
}
578+
579+
impl IntoAscii for u8 {
580+
fn into_ascii(self) -> Result<Ascii,IntoAsciiError> {
581+
unsafe{if self <= 0x7F {
582+
return Ok(self.into_ascii_unchecked());
583+
}}
584+
Err(IntoAsciiError(()))
585+
}
586+
unsafe fn into_ascii_unchecked(self) -> Ascii {
587+
transmute(self)
588+
}
589+
}
590+
591+
impl IntoAscii for char {
592+
fn into_ascii(self) -> Result<Ascii,IntoAsciiError> {
593+
unsafe{if self as u32 <= 0x7F {
594+
return Ok(self.into_ascii_unchecked());
595+
}}
596+
Err(IntoAsciiError(()))
597+
}
598+
unsafe fn into_ascii_unchecked(self) -> Ascii {
599+
(self as u8).into_ascii_unchecked()
600+
}
601+
}
602+
603+
533604
#[cfg(test)]
534605
mod tests {
535606
use AsciiCast;
536-
use super::Ascii;
607+
use super::{Ascii,IntoAscii,IntoAsciiError};
537608

538609
#[test]
539610
fn to_ascii() {
@@ -544,6 +615,15 @@ mod tests {
544615
assert_eq!('λ'.to_ascii(), Err(()));
545616
}
546617

618+
#[test]
619+
fn into_ascii() {
620+
fn generic<C:IntoAscii>(c: C) -> Result<Ascii,IntoAsciiError> {
621+
c.into_ascii()
622+
}
623+
assert_eq!(generic('A'), Ok(Ascii::A));
624+
assert_eq!(generic(b'A'), Ok(Ascii::A));
625+
}
626+
547627
#[test]
548628
fn as_byte() {
549629
assert_eq!(65u8.to_ascii().unwrap().as_byte(), 65u8);

0 commit comments

Comments
 (0)