Skip to content

Commit 8198f04

Browse files
committed
Add AsciiStr::from_ascii_str() and from_ascii_bytes()
As `const fn` alternatives to the trait-based from_ascii(). Closes #84
1 parent 875d06a commit 8198f04

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

Diff for: src/ascii_str.rs

+47
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,53 @@ impl AsciiStr {
125125
bytes.as_ref().as_ascii_str()
126126
}
127127

128+
/// Convert a byte slice innto an `AsciiStr`.
129+
///
130+
/// [`from_ascii()`](#method.from_ascii) should be preferred outside of `const` contexts
131+
/// as it might be faster due to using functions that are not `const fn`.
132+
///
133+
/// # Errors
134+
/// Returns `Err` if not all bytes are valid ASCII values.
135+
///
136+
/// # Examples
137+
/// ```
138+
/// # use ascii::AsciiStr;
139+
/// assert!(AsciiStr::from_ascii_bytes(b"\x00\x22\x44").is_ok());
140+
/// assert!(AsciiStr::from_ascii_bytes(b"\x66\x77\x88").is_err());
141+
/// ```
142+
pub const fn from_ascii_bytes(b: &[u8]) -> Result<&Self, AsAsciiStrError> {
143+
#![allow(clippy::indexing_slicing)] // .get() is not const yes (as of Rust 1.61)
144+
let mut valid = 0;
145+
loop {
146+
if valid == b.len() {
147+
// SAFETY: `is_ascii` having returned true for all bytes guarantees all bytes are within ascii range.
148+
return unsafe { Ok(mem::transmute(b)) };
149+
} else if b[valid].is_ascii() {
150+
valid += 1;
151+
} else {
152+
return Err(AsAsciiStrError(valid));
153+
}
154+
}
155+
}
156+
157+
/// Convert a `str` innto an `AsciiStr`.
158+
///
159+
/// [`from_ascii()`](#method.from_ascii) should be preferred outside of `const` contexts
160+
/// as it might be faster due to using functions that are not `const fn`.
161+
///
162+
/// # Errors
163+
/// Returns `Err` if it contains non-ASCII codepoints.
164+
///
165+
/// # Examples
166+
/// ```
167+
/// # use ascii::AsciiStr;
168+
/// assert!(AsciiStr::from_ascii_str("25 C").is_ok());
169+
/// assert!(AsciiStr::from_ascii_str("35°C").is_err());
170+
/// ```
171+
pub const fn from_ascii_str(s: &str) -> Result<&Self, AsAsciiStrError> {
172+
Self::from_ascii_bytes(s.as_bytes())
173+
}
174+
128175
/// Converts anything that can be represented as a byte slice to an `AsciiStr` without checking
129176
/// for non-ASCII characters..
130177
///

0 commit comments

Comments
 (0)