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::display_object::{DisplayObject, MovieClip, TDisplayObject, TDisplayObjectContainer};
|
||||
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::vminterface::Instantiator;
|
||||
use crate::{avm_error, avm_warn};
|
||||
|
@ -866,10 +866,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
|
|||
action
|
||||
.strings
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let wstr = decode_swf_str(s, self.encoding());
|
||||
AvmString::new(self.context.gc_context, wstr).into()
|
||||
})
|
||||
.map(|s| AvmString::new(self.context.gc_context, s.decode(self.encoding())).into())
|
||||
.collect(),
|
||||
));
|
||||
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>> {
|
||||
let target = decode_swf_str(action.target, self.encoding());
|
||||
let url = decode_swf_str(action.url, self.encoding());
|
||||
let target = action.target.decode(self.encoding());
|
||||
let url = action.url.decode(self.encoding());
|
||||
// TODO: Use `StageObject::get_level_by_path`.
|
||||
if target.starts_with(WStr::from_units(b"_level")) && target.len() > 6 {
|
||||
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>> {
|
||||
if let Some(clip) = self.target_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) {
|
||||
clip.goto_frame(&mut self.context, frame, true);
|
||||
} else {
|
||||
|
@ -1805,8 +1802,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
|
|||
SwfValue::Float(v) => v.into(),
|
||||
SwfValue::Double(v) => v.into(),
|
||||
SwfValue::Str(v) => {
|
||||
let v = decode_swf_str(v, self.encoding());
|
||||
AvmString::new(self.context.gc_context, v).into()
|
||||
AvmString::new(self.context.gc_context, v.decode(self.encoding())).into()
|
||||
}
|
||||
SwfValue::Register(v) => self.current_register(v),
|
||||
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>> {
|
||||
let target = decode_swf_str(action.target, self.encoding());
|
||||
let target = action.target.decode(self.encoding());
|
||||
self.set_target(&target)
|
||||
}
|
||||
|
||||
|
@ -2219,8 +2215,10 @@ impl<'a, 'gc> Activation<'a, 'gc> {
|
|||
|
||||
match catch_vars {
|
||||
CatchVar::Var(name) => {
|
||||
let name = decode_swf_str(name, activation.encoding());
|
||||
let name = AvmString::new(activation.context.gc_context, name);
|
||||
let name = AvmString::new(
|
||||
activation.context.gc_context,
|
||||
name.decode(activation.encoding()),
|
||||
);
|
||||
activation.set_variable(name, value.to_owned())?
|
||||
}
|
||||
CatchVar::Register(id) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::avm1::scope::Scope;
|
|||
use crate::avm1::value::Value;
|
||||
use crate::avm1::{ArrayObject, Object, ObjectPtr, ScriptObject, TObject};
|
||||
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 gc_arena::{Collect, Gc, GcCell, MutationContext};
|
||||
use std::{borrow::Cow, fmt, num::NonZeroU8};
|
||||
|
@ -96,19 +96,18 @@ impl<'gc> Avm1Function<'gc> {
|
|||
let name = if swf_function.name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let name = decode_swf_str(swf_function.name, encoding);
|
||||
Some(AvmString::new(gc_context, name))
|
||||
Some(AvmString::new(
|
||||
gc_context,
|
||||
swf_function.name.decode(encoding),
|
||||
))
|
||||
};
|
||||
|
||||
let params = swf_function
|
||||
.params
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let name = decode_swf_str(p.name, encoding);
|
||||
Param {
|
||||
register: p.register_index,
|
||||
name: AvmString::new(gc_context, name),
|
||||
}
|
||||
.map(|p| Param {
|
||||
register: p.register_index,
|
||||
name: AvmString::new(gc_context, p.name.decode(encoding)),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult, KeyCode};
|
|||
use crate::font::{round_down_to_pixel, Glyph, TextRenderSettings};
|
||||
use crate::html::{BoxBounds, FormatSpans, LayoutBox, LayoutContent, LayoutMetrics, TextFormat};
|
||||
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::vminterface::{AvmObject, Instantiator};
|
||||
use chrono::Utc;
|
||||
|
@ -198,10 +198,9 @@ impl<'gc> EditText<'gc> {
|
|||
swf_movie: Arc<SwfMovie>,
|
||||
swf_tag: swf::EditText,
|
||||
) -> 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 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() {
|
||||
FormatSpans::from_html(&text, default_format, swf_tag.is_multiline())
|
||||
|
@ -263,7 +262,7 @@ impl<'gc> EditText<'gc> {
|
|||
layout: swf_tag.layout().cloned(),
|
||||
initial_text: swf_tag
|
||||
.initial_text()
|
||||
.map(|s| decode_swf_str(s, encoding).into_owned()),
|
||||
.map(|s| s.decode(encoding).into_owned()),
|
||||
},
|
||||
),
|
||||
flags,
|
||||
|
|
|
@ -31,7 +31,7 @@ use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult};
|
|||
use crate::font::Font;
|
||||
use crate::limits::ExecutionLimit;
|
||||
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::vminterface::{AvmObject, Instantiator};
|
||||
use core::fmt;
|
||||
|
@ -771,9 +771,7 @@ impl<'gc> MovieClip<'gc> {
|
|||
if !do_abc.data.is_empty() {
|
||||
let movie = self.movie();
|
||||
let domain = context.library.library_for_movie_mut(movie).avm2_domain();
|
||||
|
||||
let name = decode_swf_str(do_abc.name, reader.encoding());
|
||||
let name = AvmString::new(context.gc_context, name);
|
||||
let name = AvmString::new(context.gc_context, do_abc.name.decode(reader.encoding()));
|
||||
|
||||
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());
|
||||
|
@ -800,8 +798,10 @@ impl<'gc> MovieClip<'gc> {
|
|||
|
||||
for _ in 0..num_symbols {
|
||||
let id = reader.read_u16()?;
|
||||
let class_name = decode_swf_str(reader.read_str()?, reader.encoding());
|
||||
let class_name = AvmString::new(activation.context.gc_context, class_name);
|
||||
let class_name = AvmString::new(
|
||||
activation.context.gc_context,
|
||||
reader.read_str()?.decode(reader.encoding()),
|
||||
);
|
||||
|
||||
let name = Avm2QName::from_qualified_name(class_name, &mut activation);
|
||||
let library = activation
|
||||
|
@ -897,9 +897,8 @@ impl<'gc> MovieClip<'gc> {
|
|||
.map(|fld| fld.frame_num as u16 + 1)
|
||||
.unwrap_or_else(|| static_data.total_frames + 1);
|
||||
|
||||
let label = decode_swf_str(label, reader.encoding());
|
||||
let scene = Scene {
|
||||
name: label.into_owned(),
|
||||
name: label.decode(reader.encoding()).into_owned(),
|
||||
start,
|
||||
length: end - start,
|
||||
};
|
||||
|
@ -914,7 +913,7 @@ impl<'gc> MovieClip<'gc> {
|
|||
}
|
||||
|
||||
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
|
||||
.frame_labels
|
||||
.push((frame_num as u16 + 1, label.clone()));
|
||||
|
@ -1558,9 +1557,8 @@ impl<'gc> MovieClip<'gc> {
|
|||
child.apply_place_object(context, place_object);
|
||||
if let Some(name) = &place_object.name {
|
||||
let encoding = swf::SwfStr::encoding_for_version(self.swf_version());
|
||||
let name = decode_swf_str(name, encoding);
|
||||
child
|
||||
.set_name(context.gc_context, AvmString::new(context.gc_context, name));
|
||||
let name = AvmString::new(context.gc_context, name.decode(encoding));
|
||||
child.set_name(context.gc_context, name);
|
||||
child.set_has_explicit_name(context.gc_context, true);
|
||||
}
|
||||
if let Some(clip_depth) = place_object.clip_depth {
|
||||
|
@ -3789,7 +3787,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
|||
) -> Result<(), Error> {
|
||||
let exports = reader.read_export_assets()?;
|
||||
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 character = context
|
||||
.library
|
||||
|
@ -3823,7 +3821,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
|||
}
|
||||
|
||||
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.
|
||||
if !context.is_action_script_3() {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::context::UpdateContext;
|
||||
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 gc_arena::Collect;
|
||||
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_class = et
|
||||
.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())))
|
||||
.unwrap_or_else(|| WString::from_utf8("Times New Roman"));
|
||||
let align = et.layout().map(|l| l.align);
|
||||
|
|
|
@ -5,11 +5,17 @@ use std::ops::Deref;
|
|||
use gc_arena::{Collect, Gc, MutationContext};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Converts a SWF-encoded string into a `WStr`.
|
||||
pub fn decode_swf_str<'a>(s: &'a swf::SwfStr, encoding: &'static swf::Encoding) -> Cow<'a, WStr> {
|
||||
match s.to_str_lossy(encoding) {
|
||||
Cow::Borrowed(utf8) => from_utf8(utf8),
|
||||
Cow::Owned(utf8) => WString::from_utf8_owned(utf8).into(),
|
||||
pub trait SwfStrExt {
|
||||
/// Converts a SWF-encoded string into a `WStr`.
|
||||
fn decode(&self, encoding: &'static swf::Encoding) -> Cow<'_, WStr>;
|
||||
}
|
||||
|
||||
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> {
|
||||
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>>>(
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
string: S,
|
||||
|
@ -49,12 +61,6 @@ impl<'gc> AvmString<'gc> {
|
|||
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 {
|
||||
match &self.source {
|
||||
Source::Owned(s) => &s.0,
|
||||
|
|
Loading…
Reference in New Issue