Impl `toString`

This commit is contained in:
David Wendt 2019-12-26 15:59:21 -07:00
parent 513460e4e0
commit 19ca11b08c
2 changed files with 87 additions and 1 deletions

View File

@ -9,6 +9,8 @@ use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value};
use crate::xml::{XMLDocument, XMLNode}; use crate::xml::{XMLDocument, XMLNode};
use enumset::EnumSet; use enumset::EnumSet;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use quick_xml::Writer;
use std::io::Cursor;
/// XMLNode constructor /// XMLNode constructor
pub fn xmlnode_constructor<'gc>( pub fn xmlnode_constructor<'gc>(
@ -169,6 +171,25 @@ pub fn xmlnode_remove_node<'gc>(
Ok(Value::Undefined.into()) Ok(Value::Undefined.into())
} }
#[allow(unused_must_use)]
pub fn xmlnode_to_string<'gc>(
_avm: &mut Avm1<'gc>,
_ac: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
let mut result = Vec::new();
if let Some(node) = this.as_xml_node() {
let mut writer = Writer::new(Cursor::new(&mut result));
node.write_node_to_event_writer(&mut writer);
}
Ok(String::from_utf8(result)
.unwrap_or_else(|_| "".to_string())
.into())
}
/// Construct the prototype for `XMLNode`. /// Construct the prototype for `XMLNode`.
pub fn create_xmlnode_proto<'gc>( pub fn create_xmlnode_proto<'gc>(
gc_context: MutationContext<'gc, '_>, gc_context: MutationContext<'gc, '_>,
@ -483,6 +504,16 @@ pub fn create_xmlnode_proto<'gc>(
EnumSet::empty(), EnumSet::empty(),
Some(fn_proto), Some(fn_proto),
); );
xmlnode_proto
.as_script_object()
.unwrap()
.force_set_function(
"toString",
xmlnode_to_string,
gc_context,
EnumSet::empty(),
Some(fn_proto),
);
xmlnode_proto xmlnode_proto
} }

View File

@ -6,10 +6,13 @@ use crate::avm1::Object;
use crate::xml; use crate::xml;
use crate::xml::{Error, XMLDocument, XMLName}; use crate::xml::{Error, XMLDocument, XMLName};
use gc_arena::{Collect, GcCell, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
use quick_xml::events::{BytesStart, BytesText}; use quick_xml::events::attributes::Attribute;
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
use quick_xml::Writer;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; use std::fmt;
use std::io::Write;
use std::mem::swap; use std::mem::swap;
/// Represents a node in the XML tree. /// Represents a node in the XML tree.
@ -932,6 +935,58 @@ impl<'gc> XMLNode<'gc> {
None None
} }
} }
pub fn write_node_to_event_writer<W>(self, writer: &mut Writer<W>) -> Result<(), Error>
where
W: Write,
{
match &*self.0.read() {
XMLNodeData::DocumentRoot { .. } => Ok(0),
XMLNodeData::Element {
tag_name,
attributes,
..
} => {
let mut bs = BytesStart::owned_name(tag_name.node_name());
let key_values: Vec<(String, &str)> = attributes
.iter()
.map(|(name, value)| (name.node_name(), value.as_str()))
.collect();
bs.extend_attributes(
key_values
.iter()
.map(|(name, value)| Attribute::from((name.as_str(), *value))),
);
writer.write(&Event::Start(bs))
}
XMLNodeData::Text { contents, .. } => {
writer.write(&Event::Text(BytesText::from_escaped_str(contents.as_str())))
}
XMLNodeData::Comment { contents, .. } => writer.write(&Event::Comment(
BytesText::from_escaped_str(contents.as_str()),
)),
}?;
if let Some(children) = self.children() {
for child in children {
child.write_node_to_event_writer(writer)?;
}
}
match &*self.0.read() {
XMLNodeData::DocumentRoot { .. } => Ok(0),
XMLNodeData::Element { tag_name, .. } => {
let bs = BytesEnd::owned(tag_name.node_name().into());
writer.write(&Event::End(bs))
}
XMLNodeData::Text { .. } => Ok(0),
XMLNodeData::Comment { .. } => Ok(0),
}?;
Ok(())
}
} }
impl<'gc> fmt::Debug for XMLNode<'gc> { impl<'gc> fmt::Debug for XMLNode<'gc> {