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:
parent
1bff5c517a
commit
3bbbf2f764
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue