core: replace `string::decode_swf_str` by a `SwfStrExt` extention trait
This commit is contained in:
parent
e9a16ff5fe
commit
cfde53cde2
|
@ -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) => {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue