avm2: use WString in QName methods

This commit is contained in:
Moulins 2021-10-03 02:33:19 +02:00 committed by kmeisthax
parent 5ca911209b
commit 053758d77c
5 changed files with 65 additions and 61 deletions

View File

@ -3,7 +3,6 @@
use crate::avm2::object::TObject;
use crate::avm2::QName;
use crate::avm2::{Activation, Error, Object, Value};
use crate::string::AvmString;
pub mod bytearray;
pub mod compression_algorithm;
@ -42,15 +41,12 @@ pub fn get_qualified_class_name<'gc>(
},
};
Ok(AvmString::new(
activation.context.gc_context,
class
.inner_class_definition()
.read()
.name()
.to_qualified_name(),
)
.into())
Ok(class
.inner_class_definition()
.read()
.name()
.to_qualified_name(activation.context.gc_context)
.into())
}
/// Implements `flash.utils.getQualifiedSuperclassName`
@ -73,15 +69,12 @@ pub fn get_qualified_super_class_name<'gc>(
};
if let Some(super_class) = class.superclass_object() {
Ok(AvmString::new(
activation.context.gc_context,
super_class
.inner_class_definition()
.read()
.name()
.to_qualified_name(),
)
.into())
Ok(super_class
.inner_class_definition()
.read()
.name()
.to_qualified_name(activation.context.gc_context)
.into())
} else {
Ok(Value::Null)
}
@ -98,6 +91,6 @@ pub fn get_definition_by_name<'gc>(
.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_string(activation)?;
let qname = QName::from_qualified_name(&name, activation.context.gc_context);
let qname = QName::from_qualified_name(name, activation.context.gc_context);
appdomain.get_defined_value(activation, qname)
}

View File

@ -4,7 +4,7 @@ use crate::avm2::activation::Activation;
use crate::avm2::script::TranslationUnit;
use crate::avm2::value::Value;
use crate::avm2::Error;
use crate::string::AvmString;
use crate::string::{AvmString, BorrowWStr, WStr, WString};
use gc_arena::{Collect, MutationContext};
use swf::avm2::types::{
AbcFile, Index, Multiname as AbcMultiname, Namespace as AbcNamespace,
@ -206,32 +206,34 @@ impl<'gc> QName<'gc> {
/// NAMESPACE::LOCAL_NAME
/// NAMESPACE.LOCAL_NAME (Where the LAST dot is used to split the namespace & local_name)
/// LOCAL_NAME (Use the public namespace)
pub fn from_qualified_name(name: &str, mc: MutationContext<'gc, '_>) -> Self {
if let Some((package_name, local_name)) = name.rsplit_once("::") {
pub fn from_qualified_name(name: AvmString<'gc>, mc: MutationContext<'gc, '_>) -> Self {
let parts = name
.rsplit_once(WStr::from_units(b"::"))
.or_else(|| name.rsplit_once(WStr::from_units(b".")));
if let Some((package_name, local_name)) = parts {
Self {
ns: Namespace::Package(AvmString::new(mc, package_name.to_string())),
name: AvmString::new(mc, local_name.to_string()),
}
} else if let Some((package_name, local_name)) = name.rsplit_once('.') {
Self {
ns: Namespace::Package(AvmString::new(mc, package_name.to_string())),
name: AvmString::new(mc, local_name.to_string()),
ns: Namespace::Package(AvmString::new_ucs2(mc, package_name.into())),
name: AvmString::new_ucs2(mc, local_name.into()),
}
} else {
Self {
ns: Namespace::public(),
name: AvmString::new(mc, name.to_string()),
name,
}
}
}
/// Converts this `QName` to a fully qualified name.
pub fn to_qualified_name(&self) -> String {
pub fn to_qualified_name(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
let uri = self.namespace().as_uri();
let name = self.local_name();
uri.is_empty()
.then(|| name.to_string())
.unwrap_or_else(|| format!("{}::{}", uri, name))
uri.is_empty().then(|| name).unwrap_or_else(|| {
let mut buf = WString::from(uri.borrow());
buf.push_str(WStr::from_units(b"::"));
buf.push_str(name.borrow());
AvmString::new_ucs2(mc, buf)
})
}
pub fn local_name(&self) -> AvmString<'gc> {
@ -244,31 +246,25 @@ impl<'gc> QName<'gc> {
/// Get the string value of this QName, including the namespace URI.
pub fn as_uri(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
match self.ns {
Namespace::Namespace(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::Package(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::PackageInternal(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::Protected(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::Explicit(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::StaticProtected(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::Private(s) if s != "" => {
AvmString::new(mc, format!("{}::{}", &*s, &*self.name))
}
Namespace::Any => AvmString::new(mc, format!("*::{}", &*self.name)),
_ => self.name,
let ns = match &self.ns {
Namespace::Namespace(s) => s.borrow(),
Namespace::Package(s) => s.borrow(),
Namespace::PackageInternal(s) => s.borrow(),
Namespace::Protected(s) => s.borrow(),
Namespace::Explicit(s) => s.borrow(),
Namespace::StaticProtected(s) => s.borrow(),
Namespace::Private(s) => s.borrow(),
Namespace::Any => WStr::from_units(b"*"),
};
if ns.is_empty() {
return self.name;
}
let mut uri = WString::from(ns);
uri.push_str(WStr::from_units(b"::"));
uri.push_str(self.name.borrow());
AvmString::new_ucs2(mc, uri)
}
}

View File

@ -586,8 +586,9 @@ impl<'gc> MovieClip<'gc> {
for _ in 0..num_symbols {
let id = reader.read_u16()?;
let class_name = reader.read_str()?.to_string_lossy(reader.encoding());
let class_name = AvmString::new(activation.context.gc_context, class_name);
let name = Avm2QName::from_qualified_name(&class_name, activation.context.gc_context);
let name = Avm2QName::from_qualified_name(class_name, activation.context.gc_context);
let library = activation
.context
.library

View File

@ -204,13 +204,19 @@ macro_rules! impl_str_methods {
crate::string::ops::str_split($deref, separator)
}
/// Analogue of [`str::split_at`]
/// Analogue of [`str::split_at`].
#[inline]
pub fn split_at($self: $receiver, index: usize) -> (crate::string::WStr<$lt>, crate::string::WStr<$lt>) {
let s = $deref;
(s.slice(..index), s.slice(index..))
}
/// Analogue of [`str::rsplit_once`].
#[inline]
pub fn rsplit_once<$($pat_gen)* P: crate::string::Pattern<$pat_lt>>($self: $pat_self, pattern: P) -> Option<(WStr<$pat_lt>, WStr<$pat_lt>)> {
crate::string::ops::str_rsplit_once($deref, pattern)
}
/// Analogue of [`str::trim_matches`].
#[inline]
pub fn trim_matches<$($pat_gen)* P: crate::string::Pattern<$pat_lt>>($self: $pat_self, pattern: P) -> WStr<$pat_lt> {

View File

@ -212,6 +212,14 @@ pub fn str_split<'a, P: Pattern<'a>>(string: WStr<'a>, pattern: P) -> Split<'a,
}
}
pub fn str_rsplit_once<'a, P: Pattern<'a>>(
string: WStr<'a>,
pattern: P,
) -> Option<(WStr<'a>, WStr<'a>)> {
let (start, end) = pattern.into_searcher(string).next_match_back()?;
Some((string.slice(..start), string.slice(end..)))
}
pub fn starts_with<'a, P: Pattern<'a>>(string: WStr<'a>, pattern: P) -> bool {
matches!(
pattern.into_searcher(string).next(),