wstr: make the crate no_std

This requires removing the Error impl of ParseNumError, because the
Error trait is std-only.
This commit is contained in:
Moulins 2022-03-24 11:53:25 +01:00 committed by Mike Welsh
parent 1bff5c517a
commit 3bbbf2f764
9 changed files with 50 additions and 39 deletions

View File

@ -1,6 +1,10 @@
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use alloc::borrow::ToOwned;
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use core::mem::{self, ManuallyDrop};
use core::ops::{Deref, DerefMut};
use core::ptr::{self, NonNull};
use super::utils::split_ascii_prefix;
use super::{Units, WStr, MAX_STRING_LEN};
@ -178,8 +182,8 @@ impl WString {
// SAFETY: we disable the Drop impl, so we can put the ManuallyDrop'd buffer back
unsafe {
let buffer = ManuallyDrop::take(&mut self.buffer);
std::ptr::write(self.source, WString::from_buf(buffer));
std::mem::forget(self);
ptr::write(self.source, WString::from_buf(buffer));
mem::forget(self);
}
}
}
@ -188,7 +192,7 @@ impl WString {
fn drop(&mut self) {
// SAFETY: something has gone wrong, replace the buffer with an empty one and drop it.
unsafe {
std::ptr::write(self.source, WString::new());
ptr::write(self.source, WString::new());
ManuallyDrop::drop(&mut self.buffer);
}
}
@ -209,7 +213,7 @@ impl WString {
if let Units::Bytes(buf) = units {
// Convert into wide string if necessary.
if wide() {
let buf = std::mem::take(buf);
let buf = mem::take(buf);
*units = Units::Wide(buf.into_iter().map(|c| c.into()).collect());
}
}
@ -380,15 +384,15 @@ impl AsMut<WStr> for WString {
}
}
impl std::fmt::Write for WString {
impl fmt::Write for WString {
#[inline]
fn write_str(&mut self, s: &str) -> std::fmt::Result {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_utf8(s);
Ok(())
}
#[inline]
fn write_char(&mut self, c: char) -> std::fmt::Result {
fn write_char(&mut self, c: char) -> fmt::Result {
self.push_char(c);
Ok(())
}

View File

@ -1,6 +1,8 @@
use super::{ptr, FromWStr, Pattern, WStr, WString, MAX_STRING_LEN};
use alloc::vec::Vec;
use core::ops::{Bound, Index, IndexMut, Range, RangeBounds};
use super::{ptr, FromWStr, Pattern, WStr, WString, MAX_STRING_LEN};
#[cold]
pub(super) fn panic_on_invalid_length(len: usize) -> ! {
panic!("Too many code units in Ruffle string (len = {})", len)
@ -312,7 +314,7 @@ impl WStr {
///
/// Unpaired surrogates are replaced by the replacement character.
#[inline]
pub fn to_utf8_lossy(&self) -> std::borrow::Cow<'_, str> {
pub fn to_utf8_lossy(&self) -> alloc::borrow::Cow<'_, str> {
super::ops::WStrToUtf8::new(self).to_utf8_lossy()
}

View File

@ -1,3 +1,4 @@
#![no_std]
//! Provides UCS2 string types for usage in AVM1 and AVM2.
//!
//! Internally, these types are represeted by a sequence of 1-byte or 2-bytes (wide) code units,
@ -6,6 +7,9 @@
//! To match Flash behavior, the string length is limited to 2³¹-1 code units;
//! any attempt to create a longer string will panic.
#[cfg_attr(test, macro_use)]
extern crate alloc;
#[macro_use]
mod common;
@ -27,7 +31,7 @@ pub use parse::{FromWStr, Integer};
pub use pattern::Pattern;
pub use ptr::{WStr, MAX_STRING_LEN};
use std::borrow::Borrow;
use core::borrow::Borrow;
use common::panic_on_invalid_length;

View File

@ -1,7 +1,9 @@
use std::borrow::{Borrow, Cow};
use std::fmt::{self, Write};
use std::hash::Hasher;
use std::slice::Iter as SliceIter;
use alloc::borrow::{Borrow, Cow};
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::{self, Write};
use core::hash::Hasher;
use core::slice::Iter as SliceIter;
use super::pattern::{SearchStep, Searcher};
use super::{utils, Pattern, Units, WStr, WString};
@ -32,7 +34,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> {
}
}
pub type Chars<'a> = std::char::DecodeUtf16<Iter<'a>>;
pub type Chars<'a> = core::char::DecodeUtf16<Iter<'a>>;
pub struct CharIndices<'a> {
chars: Chars<'a>,
@ -40,7 +42,7 @@ pub struct CharIndices<'a> {
}
impl<'a> Iterator for CharIndices<'a> {
type Item = (usize, Result<char, std::char::DecodeUtf16Error>);
type Item = (usize, Result<char, core::char::DecodeUtf16Error>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
@ -85,7 +87,7 @@ pub fn str_fmt(s: &WStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
pub fn str_debug_fmt(s: &WStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
for c in std::char::decode_utf16(s.iter()) {
for c in core::char::decode_utf16(s.iter()) {
match c {
Ok(c) => c.escape_debug().try_for_each(|c| f.write_char(c))?,
Err(err) => write!(f, "\\u{{{:x}}}", err.unpaired_surrogate())?,
@ -96,7 +98,7 @@ pub fn str_debug_fmt(s: &WStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
pub fn str_eq(left: &WStr, right: &WStr) -> bool {
if std::ptr::eq(left, right) {
if core::ptr::eq(left, right) {
return true;
}
@ -123,7 +125,7 @@ pub fn str_eq_ignore_case(left: &WStr, right: &WStr) -> bool {
left.eq(right)
}
pub fn str_cmp(left: &WStr, right: &WStr) -> std::cmp::Ordering {
pub fn str_cmp(left: &WStr, right: &WStr) -> core::cmp::Ordering {
let (bytes, wide, rev) = match (left.units(), right.units()) {
(Units::Bytes(a), Units::Bytes(b)) => return a.cmp(b),
(Units::Wide(a), Units::Wide(b)) => return a.cmp(b),
@ -141,7 +143,7 @@ pub fn str_cmp(left: &WStr, right: &WStr) -> std::cmp::Ordering {
}
}
pub fn str_cmp_ignore_case(left: &WStr, right: &WStr) -> std::cmp::Ordering {
pub fn str_cmp_ignore_case(left: &WStr, right: &WStr) -> core::cmp::Ordering {
let left = left.iter().map(utils::swf_to_lowercase);
let right = right.iter().map(utils::swf_to_lowercase);
left.cmp(right)
@ -168,7 +170,7 @@ pub fn str_offset_in(s: &WStr, other: &WStr) -> Option<usize> {
}
(Units::Wide(a), Units::Wide(b)) => (a.as_ptr() as usize)
.checked_sub(b.as_ptr() as usize)
.map(|n| n / std::mem::size_of::<u16>()),
.map(|n| n / core::mem::size_of::<u16>()),
_ => None,
};
@ -396,7 +398,7 @@ impl<'a, P: Pattern<'a>> Iterator for Split<'a, P> {
match self.searcher.next_match() {
Some((start, end)) => {
let end = std::mem::replace(&mut self.prev_end, end);
let end = core::mem::replace(&mut self.prev_end, end);
Some(&string[end..start])
}
None => {

View File

@ -1,5 +1,5 @@
use std::fmt;
use std::num::Wrapping;
use core::fmt;
use core::num::Wrapping;
use super::WStr;
@ -20,8 +20,6 @@ impl fmt::Display for ParseNumError {
}
}
impl std::error::Error for ParseNumError {}
/// Trait implemented for all integer types that can be parsed from a [`WStr`].
pub trait Integer: FromWStr<Err = ParseNumError> {
fn from_wstr_radix(s: &WStr, radix: u32) -> Result<Self, Self::Err>;

View File

@ -209,7 +209,7 @@ impl<'a, T: Searcher<'a>, U: Searcher<'a>> Searcher<'a> for Either<T, U> {
}
pub struct EmptySearcher {
range: std::ops::Range<usize>,
range: core::ops::Range<usize>,
}
impl EmptySearcher {

View File

@ -1,5 +1,5 @@
use std::ops::Range;
use std::ptr::slice_from_raw_parts_mut;
use core::ops::Range;
use core::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
use super::Units;
@ -102,7 +102,7 @@ pub unsafe fn is_wide(ptr: *mut WStr) -> bool {
#[inline]
pub unsafe fn from_raw_parts(data: *mut (), len: usize, is_wide: bool) -> *mut WStr {
let raw_len = len | if is_wide { WIDE_MASK } else { 0 };
let slice = std::ptr::slice_from_raw_parts(data, raw_len);
let slice = slice_from_raw_parts(data, raw_len);
slice as *mut WStr
}

View File

@ -1,7 +1,8 @@
use super::pattern::Searcher;
use super::*;
use std::fmt::Debug;
use alloc::vec::Vec;
use core::fmt::Debug;
macro_rules! bstr {
($str:literal) => {
@ -146,7 +147,7 @@ fn test_pattern<'a, P: Pattern<'a> + Clone + Debug>(
backwards: Option<&[(usize, usize)]>,
) {
let mut searcher = pattern.clone().into_searcher(haystack);
let mut actual: Vec<_> = std::iter::from_fn(|| searcher.next_match()).collect();
let mut actual: Vec<_> = core::iter::from_fn(|| searcher.next_match()).collect();
assert_eq!(
actual, forwards,
"incorrect forwards matching: haystack={:?}; pattern={:?}",
@ -154,7 +155,7 @@ fn test_pattern<'a, P: Pattern<'a> + Clone + Debug>(
);
searcher = pattern.clone().into_searcher(haystack);
actual = std::iter::from_fn(|| searcher.next_match_back()).collect();
actual = core::iter::from_fn(|| searcher.next_match_back()).collect();
actual.reverse();
assert_eq!(
actual,

View File

@ -53,7 +53,7 @@ pub fn split_ascii_prefix_bytes(slice: &[u8]) -> (&str, &[u8]) {
let first_non_ascii = slice.iter().position(|c| *c >= 0x80);
let (head, tail) = slice.split_at(first_non_ascii.unwrap_or(0));
// SAFETY: `head` only contains ASCII.
let head = unsafe { std::str::from_utf8_unchecked(head) };
let head = unsafe { core::str::from_utf8_unchecked(head) };
(head, tail)
}
@ -62,14 +62,14 @@ pub fn split_ascii_prefix_bytes(slice: &[u8]) -> (&str, &[u8]) {
pub fn split_ascii_prefix(slice: &str) -> (&[u8], &str) {
let (head, tail) = split_ascii_prefix_bytes(slice.as_bytes());
// SAFETY: `split_ascii_prefix_bytes` always split on a char boundary.
let tail = unsafe { std::str::from_utf8_unchecked(tail) };
let tail = unsafe { core::str::from_utf8_unchecked(tail) };
(head.as_bytes(), tail)
}
/// Maps a UTF-16 code unit into a `char`.
/// TODO: Surrogate characters will get replaced with the Unicode replacement character.
pub fn utf16_code_unit_to_char(c: u16) -> char {
char::decode_utf16(std::iter::once(c))
char::decode_utf16(core::iter::once(c))
.next()
.unwrap()
.unwrap_or(char::REPLACEMENT_CHARACTER)