core: replace `string::decode_swf_str` by a `SwfStrExt` extention trait

This commit is contained in:
Moulins 2023-04-10 17:20:07 +02:00 committed by Nathan Adams
parent e9a16ff5fe
commit cfde53cde2
6 changed files with 53 additions and 53 deletions

View File

@ -10,7 +10,7 @@ use crate::backend::navigator::{NavigationMethod, Request};
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::display_object::{DisplayObject, MovieClip, TDisplayObject, TDisplayObjectContainer}; use crate::display_object::{DisplayObject, MovieClip, TDisplayObject, TDisplayObjectContainer};
use crate::ecma_conversions::f64_to_wrapping_u32; use crate::ecma_conversions::f64_to_wrapping_u32;
use crate::string::{decode_swf_str, AvmString, WStr, WString}; use crate::string::{AvmString, SwfStrExt as _, WStr, WString};
use crate::tag_utils::SwfSlice; use crate::tag_utils::SwfSlice;
use crate::vminterface::Instantiator; use crate::vminterface::Instantiator;
use crate::{avm_error, avm_warn}; use crate::{avm_error, avm_warn};
@ -866,10 +866,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
action action
.strings .strings
.iter() .iter()
.map(|s| { .map(|s| AvmString::new(self.context.gc_context, s.decode(self.encoding())).into())
let wstr = decode_swf_str(s, self.encoding());
AvmString::new(self.context.gc_context, wstr).into()
})
.collect(), .collect(),
)); ));
self.set_constant_pool(self.context.avm1.constant_pool()); self.set_constant_pool(self.context.avm1.constant_pool());
@ -1184,8 +1181,8 @@ impl<'a, 'gc> Activation<'a, 'gc> {
} }
fn action_get_url(&mut self, action: GetUrl) -> Result<FrameControl<'gc>, Error<'gc>> { fn action_get_url(&mut self, action: GetUrl) -> Result<FrameControl<'gc>, Error<'gc>> {
let target = decode_swf_str(action.target, self.encoding()); let target = action.target.decode(self.encoding());
let url = decode_swf_str(action.url, self.encoding()); let url = action.url.decode(self.encoding());
// TODO: Use `StageObject::get_level_by_path`. // TODO: Use `StageObject::get_level_by_path`.
if target.starts_with(WStr::from_units(b"_level")) && target.len() > 6 { if target.starts_with(WStr::from_units(b"_level")) && target.len() > 6 {
match target[6..].parse::<i32>() { match target[6..].parse::<i32>() {
@ -1411,7 +1408,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
fn action_goto_label(&mut self, action: GotoLabel) -> Result<FrameControl<'gc>, Error<'gc>> { fn action_goto_label(&mut self, action: GotoLabel) -> Result<FrameControl<'gc>, Error<'gc>> {
if let Some(clip) = self.target_clip() { if let Some(clip) = self.target_clip() {
if let Some(clip) = clip.as_movie_clip() { if let Some(clip) = clip.as_movie_clip() {
let label = decode_swf_str(action.label, self.encoding()); let label = action.label.decode(self.encoding());
if let Some(frame) = clip.frame_label_to_number(&label, &self.context) { if let Some(frame) = clip.frame_label_to_number(&label, &self.context) {
clip.goto_frame(&mut self.context, frame, true); clip.goto_frame(&mut self.context, frame, true);
} else { } else {
@ -1805,8 +1802,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
SwfValue::Float(v) => v.into(), SwfValue::Float(v) => v.into(),
SwfValue::Double(v) => v.into(), SwfValue::Double(v) => v.into(),
SwfValue::Str(v) => { SwfValue::Str(v) => {
let v = decode_swf_str(v, self.encoding()); AvmString::new(self.context.gc_context, v.decode(self.encoding())).into()
AvmString::new(self.context.gc_context, v).into()
} }
SwfValue::Register(v) => self.current_register(v), SwfValue::Register(v) => self.current_register(v),
SwfValue::ConstantPool(i) => { SwfValue::ConstantPool(i) => {
@ -1917,7 +1913,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
} }
fn action_set_target(&mut self, action: SetTarget) -> Result<FrameControl<'gc>, Error<'gc>> { fn action_set_target(&mut self, action: SetTarget) -> Result<FrameControl<'gc>, Error<'gc>> {
let target = decode_swf_str(action.target, self.encoding()); let target = action.target.decode(self.encoding());
self.set_target(&target) self.set_target(&target)
} }
@ -2219,8 +2215,10 @@ impl<'a, 'gc> Activation<'a, 'gc> {
match catch_vars { match catch_vars {
CatchVar::Var(name) => { CatchVar::Var(name) => {
let name = decode_swf_str(name, activation.encoding()); let name = AvmString::new(
let name = AvmString::new(activation.context.gc_context, name); activation.context.gc_context,
name.decode(activation.encoding()),
);
activation.set_variable(name, value.to_owned())? activation.set_variable(name, value.to_owned())?
} }
CatchVar::Register(id) => { CatchVar::Register(id) => {

View File

@ -8,7 +8,7 @@ use crate::avm1::scope::Scope;
use crate::avm1::value::Value; use crate::avm1::value::Value;
use crate::avm1::{ArrayObject, Object, ObjectPtr, ScriptObject, TObject}; use crate::avm1::{ArrayObject, Object, ObjectPtr, ScriptObject, TObject};
use crate::display_object::{DisplayObject, TDisplayObject}; use crate::display_object::{DisplayObject, TDisplayObject};
use crate::string::{decode_swf_str, AvmString}; use crate::string::{AvmString, SwfStrExt as _};
use crate::tag_utils::SwfSlice; use crate::tag_utils::SwfSlice;
use gc_arena::{Collect, Gc, GcCell, MutationContext}; use gc_arena::{Collect, Gc, GcCell, MutationContext};
use std::{borrow::Cow, fmt, num::NonZeroU8}; use std::{borrow::Cow, fmt, num::NonZeroU8};
@ -96,19 +96,18 @@ impl<'gc> Avm1Function<'gc> {
let name = if swf_function.name.is_empty() { let name = if swf_function.name.is_empty() {
None None
} else { } else {
let name = decode_swf_str(swf_function.name, encoding); Some(AvmString::new(
Some(AvmString::new(gc_context, name)) gc_context,
swf_function.name.decode(encoding),
))
}; };
let params = swf_function let params = swf_function
.params .params
.iter() .iter()
.map(|p| { .map(|p| Param {
let name = decode_swf_str(p.name, encoding); register: p.register_index,
Param { name: AvmString::new(gc_context, p.name.decode(encoding)),
register: p.register_index,
name: AvmString::new(gc_context, name),
}
}) })
.collect(); .collect();

View File

@ -21,7 +21,7 @@ use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode};
use crate::font::{round_down_to_pixel, Glyph, TextRenderSettings}; use crate::font::{round_down_to_pixel, Glyph, TextRenderSettings};
use crate::html::{BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, TextFormat}; use crate::html::{BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, TextFormat};
use crate::prelude::*; use crate::prelude::*;
use crate::string::{decode_swf_str, utils as string_utils, AvmString, WStr, WString}; use crate::string::{utils as string_utils, AvmString, SwfStrExt as _, WStr, WString};
use crate::tag_utils::SwfMovie; use crate::tag_utils::SwfMovie;
use crate::vminterface::{AvmObject, Instantiator}; use crate::vminterface::{AvmObject, Instantiator};
use chrono::Utc; use chrono::Utc;
@ -198,10 +198,9 @@ impl<'gc> EditText<'gc> {
swf_movie: Arc<SwfMovie>, swf_movie: Arc<SwfMovie>,
swf_tag: swf::EditText, swf_tag: swf::EditText,
) -> Self { ) -> Self {
let text = swf_tag.initial_text().unwrap_or_default();
let default_format = TextFormat::from_swf_tag(swf_tag.clone(), swf_movie.clone(), context); let default_format = TextFormat::from_swf_tag(swf_tag.clone(), swf_movie.clone(), context);
let encoding = swf_movie.encoding(); let encoding = swf_movie.encoding();
let text = decode_swf_str(text, encoding); let text = swf_tag.initial_text().unwrap_or_default().decode(encoding);
let mut text_spans = if swf_tag.is_html() { let mut text_spans = if swf_tag.is_html() {
FormatSpans::from_html(&text, default_format, swf_tag.is_multiline()) FormatSpans::from_html(&text, default_format, swf_tag.is_multiline())
@ -263,7 +262,7 @@ impl<'gc> EditText<'gc> {
layout: swf_tag.layout().cloned(), layout: swf_tag.layout().cloned(),
initial_text: swf_tag initial_text: swf_tag
.initial_text() .initial_text()
.map(|s| decode_swf_str(s, encoding).into_owned()), .map(|s| s.decode(encoding).into_owned()),
}, },
), ),
flags, flags,

View File

@ -31,7 +31,7 @@ use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult};
use crate::font::Font; use crate::font::Font;
use crate::limits::ExecutionLimit; use crate::limits::ExecutionLimit;
use crate::prelude::*; use crate::prelude::*;
use crate::string::{decode_swf_str, AvmString, WStr, WString}; use crate::string::{AvmString, SwfStrExt as _, WStr, WString};
use crate::tag_utils::{self, ControlFlow, DecodeResult, Error, SwfMovie, SwfSlice, SwfStream}; use crate::tag_utils::{self, ControlFlow, DecodeResult, Error, SwfMovie, SwfSlice, SwfStream};
use crate::vminterface::{AvmObject, Instantiator}; use crate::vminterface::{AvmObject, Instantiator};
use core::fmt; use core::fmt;
@ -771,9 +771,7 @@ impl<'gc> MovieClip<'gc> {
if !do_abc.data.is_empty() { if !do_abc.data.is_empty() {
let movie = self.movie(); let movie = self.movie();
let domain = context.library.library_for_movie_mut(movie).avm2_domain(); let domain = context.library.library_for_movie_mut(movie).avm2_domain();
let name = AvmString::new(context.gc_context, do_abc.name.decode(reader.encoding()));
let name = decode_swf_str(do_abc.name, reader.encoding());
let name = AvmString::new(context.gc_context, name);
if let Err(e) = Avm2::do_abc(context, do_abc.data, Some(name), do_abc.flags, domain) { if let Err(e) = Avm2::do_abc(context, do_abc.data, Some(name), do_abc.flags, domain) {
let mut activation = Avm2Activation::from_nothing(context.reborrow()); let mut activation = Avm2Activation::from_nothing(context.reborrow());
@ -800,8 +798,10 @@ impl<'gc> MovieClip<'gc> {
for _ in 0..num_symbols { for _ in 0..num_symbols {
let id = reader.read_u16()?; let id = reader.read_u16()?;
let class_name = decode_swf_str(reader.read_str()?, reader.encoding()); let class_name = AvmString::new(
let class_name = AvmString::new(activation.context.gc_context, class_name); activation.context.gc_context,
reader.read_str()?.decode(reader.encoding()),
);
let name = Avm2QName::from_qualified_name(class_name, &mut activation); let name = Avm2QName::from_qualified_name(class_name, &mut activation);
let library = activation let library = activation
@ -897,9 +897,8 @@ impl<'gc> MovieClip<'gc> {
.map(|fld| fld.frame_num as u16 + 1) .map(|fld| fld.frame_num as u16 + 1)
.unwrap_or_else(|| static_data.total_frames + 1); .unwrap_or_else(|| static_data.total_frames + 1);
let label = decode_swf_str(label, reader.encoding());
let scene = Scene { let scene = Scene {
name: label.into_owned(), name: label.decode(reader.encoding()).into_owned(),
start, start,
length: end - start, length: end - start,
}; };
@ -914,7 +913,7 @@ impl<'gc> MovieClip<'gc> {
} }
for FrameLabelData { frame_num, label } in sfl_data.frame_labels { for FrameLabelData { frame_num, label } in sfl_data.frame_labels {
let label = decode_swf_str(label, reader.encoding()).into_owned(); let label = label.decode(reader.encoding()).into_owned();
static_data static_data
.frame_labels .frame_labels
.push((frame_num as u16 + 1, label.clone())); .push((frame_num as u16 + 1, label.clone()));
@ -1558,9 +1557,8 @@ impl<'gc> MovieClip<'gc> {
child.apply_place_object(context, place_object); child.apply_place_object(context, place_object);
if let Some(name) = &place_object.name { if let Some(name) = &place_object.name {
let encoding = swf::SwfStr::encoding_for_version(self.swf_version()); let encoding = swf::SwfStr::encoding_for_version(self.swf_version());
let name = decode_swf_str(name, encoding); let name = AvmString::new(context.gc_context, name.decode(encoding));
child child.set_name(context.gc_context, name);
.set_name(context.gc_context, AvmString::new(context.gc_context, name));
child.set_has_explicit_name(context.gc_context, true); child.set_has_explicit_name(context.gc_context, true);
} }
if let Some(clip_depth) = place_object.clip_depth { if let Some(clip_depth) = place_object.clip_depth {
@ -3789,7 +3787,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
) -> Result<(), Error> { ) -> Result<(), Error> {
let exports = reader.read_export_assets()?; let exports = reader.read_export_assets()?;
for export in exports { for export in exports {
let name = decode_swf_str(export.name, reader.encoding()); let name = export.name.decode(reader.encoding());
let name = AvmString::new(context.gc_context, name); let name = AvmString::new(context.gc_context, name);
let character = context let character = context
.library .library
@ -3823,7 +3821,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
} }
let frame_label = reader.read_frame_label()?; let frame_label = reader.read_frame_label()?;
let mut label = decode_swf_str(frame_label.label, reader.encoding()).into_owned(); let mut label = frame_label.label.decode(reader.encoding()).into_owned();
// In AVM1, frame labels are case insensitive (ASCII), but in AVM2 they are case sensitive. // In AVM1, frame labels are case insensitive (ASCII), but in AVM2 they are case sensitive.
if !context.is_action_script_3() { if !context.is_action_script_3() {

View File

@ -2,7 +2,7 @@
use crate::context::UpdateContext; use crate::context::UpdateContext;
use crate::html::iterators::TextSpanIter; use crate::html::iterators::TextSpanIter;
use crate::string::{decode_swf_str, Integer, Units, WStr, WString}; use crate::string::{Integer, SwfStrExt as _, Units, WStr, WString};
use crate::tag_utils::SwfMovie; use crate::tag_utils::SwfMovie;
use gc_arena::Collect; use gc_arena::Collect;
use quick_xml::{escape::escape, events::Event, Reader}; use quick_xml::{escape::escape, events::Event, Reader};
@ -145,7 +145,7 @@ impl TextFormat {
let font = et.font_id().and_then(|fid| movie_library.get_font(fid)); let font = et.font_id().and_then(|fid| movie_library.get_font(fid));
let font_class = et let font_class = et
.font_class() .font_class()
.map(|s| decode_swf_str(s, encoding).into_owned()) .map(|s| s.decode(encoding).into_owned())
.or_else(|| font.map(|font| WString::from_utf8(font.descriptor().class()))) .or_else(|| font.map(|font| WString::from_utf8(font.descriptor().class())))
.unwrap_or_else(|| WString::from_utf8("Times New Roman")); .unwrap_or_else(|| WString::from_utf8("Times New Roman"));
let align = et.layout().map(|l| l.align); let align = et.layout().map(|l| l.align);

View File

@ -5,11 +5,17 @@ use std::ops::Deref;
use gc_arena::{Collect, Gc, MutationContext}; use gc_arena::{Collect, Gc, MutationContext};
use std::borrow::Cow; use std::borrow::Cow;
/// Converts a SWF-encoded string into a `WStr`. pub trait SwfStrExt {
pub fn decode_swf_str<'a>(s: &'a swf::SwfStr, encoding: &'static swf::Encoding) -> Cow<'a, WStr> { /// Converts a SWF-encoded string into a `WStr`.
match s.to_str_lossy(encoding) { fn decode(&self, encoding: &'static swf::Encoding) -> Cow<'_, WStr>;
Cow::Borrowed(utf8) => from_utf8(utf8), }
Cow::Owned(utf8) => WString::from_utf8_owned(utf8).into(),
impl SwfStrExt for swf::SwfStr {
fn decode(&self, encoding: &'static swf::Encoding) -> Cow<'_, WStr> {
match self.to_str_lossy(encoding) {
Cow::Borrowed(utf8) => from_utf8(utf8),
Cow::Owned(utf8) => WString::from_utf8_owned(utf8).into(),
}
} }
} }
@ -31,6 +37,12 @@ pub struct AvmString<'gc> {
} }
impl<'gc> AvmString<'gc> { impl<'gc> AvmString<'gc> {
pub fn new<S: Into<WString>>(gc_context: MutationContext<'gc, '_>, string: S) -> Self {
Self {
source: Source::Owned(Gc::allocate(gc_context, OwnedWStr(string.into()))),
}
}
pub fn new_utf8<'s, S: Into<Cow<'s, str>>>( pub fn new_utf8<'s, S: Into<Cow<'s, str>>>(
gc_context: MutationContext<'gc, '_>, gc_context: MutationContext<'gc, '_>,
string: S, string: S,
@ -49,12 +61,6 @@ impl<'gc> AvmString<'gc> {
Self::new(gc_context, buf.into_owned()) Self::new(gc_context, buf.into_owned())
} }
pub fn new<S: Into<WString>>(gc_context: MutationContext<'gc, '_>, string: S) -> Self {
Self {
source: Source::Owned(Gc::allocate(gc_context, OwnedWStr(string.into()))),
}
}
pub fn as_wstr(&self) -> &WStr { pub fn as_wstr(&self) -> &WStr {
match &self.source { match &self.source {
Source::Owned(s) => &s.0, Source::Owned(s) => &s.0,