Rustfmt pass

This commit is contained in:
Mike Welsh 2019-04-23 00:31:12 -07:00
parent 64dd94b1db
commit 76c5c2bbc4
14 changed files with 1246 additions and 2750 deletions

View File

@ -1,7 +1,7 @@
#![allow(clippy::useless_attribute)] #![allow(clippy::useless_attribute)]
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug,PartialEq,Clone,Copy,FromPrimitive)] #[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
pub enum OpCode { pub enum OpCode {
End = 0x00, End = 0x00,

View File

@ -1,7 +1,7 @@
#![allow(clippy::unreadable_literal)] #![allow(clippy::unreadable_literal)]
use crate::avm1::types::*;
use crate::avm1::opcode::OpCode; use crate::avm1::opcode::OpCode;
use crate::avm1::types::*;
use crate::read::SwfRead; use crate::read::SwfRead;
use std::io::{Error, ErrorKind, Read, Result}; use std::io::{Error, ErrorKind, Read, Result};
@ -18,10 +18,7 @@ impl<R: Read> SwfRead<R> for Reader<R> {
impl<R: Read> Reader<R> { impl<R: Read> Reader<R> {
pub fn new(inner: R, version: u8) -> Reader<R> { pub fn new(inner: R, version: u8) -> Reader<R> {
Reader { Reader { inner, version }
inner,
version,
}
} }
pub fn read_action_list(&mut self) -> Result<Vec<Action>> { pub fn read_action_list(&mut self) -> Result<Vec<Action>> {
@ -123,13 +120,17 @@ impl<R: Read> Reader<R> {
} }
OpCode::GotoLabel => Action::GotoLabel(action_reader.read_c_string()?), OpCode::GotoLabel => Action::GotoLabel(action_reader.read_c_string()?),
OpCode::Greater => Action::Greater, OpCode::Greater => Action::Greater,
OpCode::If => Action::If { offset: action_reader.read_i16()? }, OpCode::If => Action::If {
offset: action_reader.read_i16()?,
},
OpCode::ImplementsOp => Action::ImplementsOp, OpCode::ImplementsOp => Action::ImplementsOp,
OpCode::Increment => Action::Increment, OpCode::Increment => Action::Increment,
OpCode::InitArray => Action::InitArray, OpCode::InitArray => Action::InitArray,
OpCode::InitObject => Action::InitObject, OpCode::InitObject => Action::InitObject,
OpCode::InstanceOf => Action::InstanceOf, OpCode::InstanceOf => Action::InstanceOf,
OpCode::Jump => Action::Jump { offset: action_reader.read_i16()? }, OpCode::Jump => Action::Jump {
offset: action_reader.read_i16()?,
},
OpCode::Less => Action::Less, OpCode::Less => Action::Less,
OpCode::Less2 => Action::Less2, OpCode::Less2 => Action::Less2,
OpCode::MBAsciiToChar => Action::MBAsciiToChar, OpCode::MBAsciiToChar => Action::MBAsciiToChar,
@ -195,7 +196,9 @@ impl<R: Read> Reader<R> {
(&mut action_reader.inner as &mut Read).take(code_length.into()), (&mut action_reader.inner as &mut Read).take(code_length.into()),
self.version, self.version,
); );
Action::With { actions: with_reader.read_action_list()? } Action::With {
actions: with_reader.read_action_list()?,
}
} }
OpCode::WaitForFrame2 => Action::WaitForFrame2 { OpCode::WaitForFrame2 => Action::WaitForFrame2 {
num_actions_to_skip: action_reader.read_u8()?, num_actions_to_skip: action_reader.read_u8()?,
@ -221,10 +224,7 @@ impl<R: Read> Reader<R> {
fn read_unknown_action(&mut self, opcode: u8, length: usize) -> Result<Action> { fn read_unknown_action(&mut self, opcode: u8, length: usize) -> Result<Action> {
let mut data = vec![0u8; length]; let mut data = vec![0u8; length];
self.inner.read_exact(&mut data)?; self.inner.read_exact(&mut data)?;
Ok(Action::Unknown { Ok(Action::Unknown { opcode, data })
opcode,
data,
})
} }
fn read_push_value(&mut self) -> Result<Value> { fn read_push_value(&mut self) -> Result<Value> {
@ -363,8 +363,7 @@ pub mod tests {
// Failed, result doesn't match. // Failed, result doesn't match.
panic!( panic!(
"Incorrectly parsed action.\nRead:\n{:?}\n\nExpected:\n{:?}", "Incorrectly parsed action.\nRead:\n{:?}\n\nExpected:\n{:?}",
parsed_action, parsed_action, expected_action
expected_action
); );
} }
} }

View File

@ -38,7 +38,10 @@ pub enum Action {
GetMember, GetMember,
GetProperty, GetProperty,
GetTime, GetTime,
GetUrl { url: String, target: String }, GetUrl {
url: String,
target: String,
},
GetUrl2 { GetUrl2 {
send_vars_method: SendVarsMethod, send_vars_method: SendVarsMethod,
is_target_sprite: bool, is_target_sprite: bool,
@ -52,13 +55,17 @@ pub enum Action {
}, },
GotoLabel(String), GotoLabel(String),
Greater, Greater,
If { offset: i16 }, If {
offset: i16,
},
ImplementsOp, ImplementsOp,
Increment, Increment,
InitArray, InitArray,
InitObject, InitObject,
InstanceOf, InstanceOf,
Jump { offset: i16 }, Jump {
offset: i16,
},
Less, Less,
Less2, Less2,
MBAsciiToChar, MBAsciiToChar,
@ -107,10 +114,20 @@ pub enum Action {
Trace, Trace,
Try(TryBlock), Try(TryBlock),
TypeOf, TypeOf,
WaitForFrame { frame: u16, num_actions_to_skip: u8 }, WaitForFrame {
WaitForFrame2 { num_actions_to_skip: u8 }, frame: u16,
With { actions: Vec<Action> }, num_actions_to_skip: u8,
Unknown { opcode: u8, data: Vec<u8> }, },
WaitForFrame2 {
num_actions_to_skip: u8,
},
With {
actions: Vec<Action>,
},
Unknown {
opcode: u8,
data: Vec<u8>,
},
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]

View File

@ -1,7 +1,7 @@
#![allow(clippy::cyclomatic_complexity, clippy::unreadable_literal)] #![allow(clippy::cyclomatic_complexity, clippy::unreadable_literal)]
use crate::avm1::types::*;
use crate::avm1::opcode::OpCode; use crate::avm1::opcode::OpCode;
use crate::avm1::types::*;
use crate::write::SwfWrite; use crate::write::SwfWrite;
use std::io::{Result, Write}; use std::io::{Result, Write};
@ -18,10 +18,7 @@ impl<W: Write> SwfWrite<W> for Writer<W> {
impl<W: Write> Writer<W> { impl<W: Write> Writer<W> {
pub fn new(inner: W, version: u8) -> Writer<W> { pub fn new(inner: W, version: u8) -> Writer<W> {
Writer { Writer { inner, version }
inner,
version,
}
} }
pub fn write_action_list(&mut self, actions: &[Action]) -> Result<()> { pub fn write_action_list(&mut self, actions: &[Action]) -> Result<()> {
@ -69,8 +66,12 @@ impl<W: Write> Writer<W> {
let mut fn_writer = Writer::new(&mut action_buf, self.version); let mut fn_writer = Writer::new(&mut action_buf, self.version);
fn_writer.write_action_list(actions)?; fn_writer.write_action_list(actions)?;
} }
let len = name.len() + 1 + 2 + params.iter().map(|p| p.len() + 1).sum::<usize>() + let len = name.len()
2 + action_buf.len(); + 1
+ 2
+ params.iter().map(|p| p.len() + 1).sum::<usize>()
+ 2
+ action_buf.len();
self.write_action_header(OpCode::DefineFunction, len)?; self.write_action_header(OpCode::DefineFunction, len)?;
self.write_c_string(name)?; self.write_c_string(name)?;
self.write_u16(params.len() as u16)?; self.write_u16(params.len() as u16)?;
@ -86,12 +87,16 @@ impl<W: Write> Writer<W> {
let mut fn_writer = Writer::new(&mut action_buf, self.version); let mut fn_writer = Writer::new(&mut action_buf, self.version);
fn_writer.write_action_list(&function.actions)?; fn_writer.write_action_list(&function.actions)?;
} }
let len = function.name.len() + 1 + 3 + let len = function.name.len()
function + 1
+ 3
+ function
.params .params
.iter() .iter()
.map(|p| p.name.len() + 2) .map(|p| p.name.len() + 2)
.sum::<usize>() + 4 + action_buf.len(); .sum::<usize>()
+ 4
+ action_buf.len();
let num_registers = function let num_registers = function
.params .params
.iter() .iter()
@ -101,26 +106,25 @@ impl<W: Write> Writer<W> {
self.write_c_string(&function.name)?; self.write_c_string(&function.name)?;
self.write_u16(function.params.len() as u16)?; self.write_u16(function.params.len() as u16)?;
self.write_u8(num_registers)?; self.write_u8(num_registers)?;
let flags = let flags = if function.preload_global {
if function.preload_global { 0b1_00000000
0b1_00000000 } else {
0
} | if function.preload_parent {
0b10000000
} else {
0
} | if function.preload_root { 0b1000000 } else { 0 }
| if function.suppress_super { 0b100000 } else { 0 }
| if function.preload_super { 0b10000 } else { 0 }
| if function.suppress_arguments {
0b1000
} else { } else {
0 0
} | }
if function.preload_parent { | if function.preload_arguments { 0b100 } else { 0 }
0b10000000 | if function.suppress_this { 0b10 } else { 0 }
} else { | if function.preload_this { 0b1 } else { 0 };
0
} | if function.preload_root { 0b1000000 } else { 0 } |
if function.suppress_super { 0b100000 } else { 0 } |
if function.preload_super { 0b10000 } else { 0 } |
if function.suppress_arguments {
0b1000
} else {
0
} | if function.preload_arguments { 0b100 } else { 0 } |
if function.suppress_this { 0b10 } else { 0 } |
if function.preload_this { 0b1 } else { 0 };
self.write_u16(flags)?; self.write_u16(flags)?;
for param in &function.params { for param in &function.params {
self.write_u8(if let Some(n) = param.register_index { self.write_u8(if let Some(n) = param.register_index {
@ -162,12 +166,12 @@ impl<W: Write> Writer<W> {
} => { } => {
self.write_action_header(OpCode::GetUrl2, 1)?; self.write_action_header(OpCode::GetUrl2, 1)?;
let flags = (match send_vars_method { let flags = (match send_vars_method {
SendVarsMethod::None => 0, SendVarsMethod::None => 0,
SendVarsMethod::Get => 1, SendVarsMethod::Get => 1,
SendVarsMethod::Post => 2, SendVarsMethod::Post => 2,
} << 6) | } << 6)
if is_target_sprite { 0b10 } else { 0 } | | if is_target_sprite { 0b10 } else { 0 }
if is_load_vars { 0b1 } else { 0 }; | if is_load_vars { 0b1 } else { 0 };
self.write_u8(flags)?; self.write_u8(flags)?;
} }
Action::GetVariable => self.write_action_header(OpCode::GetVariable, 0)?, Action::GetVariable => self.write_action_header(OpCode::GetVariable, 0)?,
@ -228,8 +232,7 @@ impl<W: Write> Writer<W> {
.map(|v| match *v { .map(|v| match *v {
Value::Str(ref string) => string.len() + 2, Value::Str(ref string) => string.len() + 2,
Value::Null | Value::Undefined => 1, Value::Null | Value::Undefined => 1,
Value::Register(_) | Value::Register(_) | Value::Bool(_) => 2,
Value::Bool(_) => 2,
Value::Double(_) => 9, Value::Double(_) => 9,
Value::Float(_) | Value::Int(_) => 5, Value::Float(_) | Value::Int(_) => 5,
Value::ConstantPool(v) => { Value::ConstantPool(v) => {
@ -299,8 +302,9 @@ impl<W: Write> Writer<W> {
} }
finally_length = fn_writer.inner.len() - (try_length + catch_length); finally_length = fn_writer.inner.len() - (try_length + catch_length);
} }
let len = 7 + action_buf.len() + let len = 7
if let Some((CatchVar::Var(ref name), _)) = try_block.catch { + action_buf.len()
+ if let Some((CatchVar::Var(ref name), _)) = try_block.catch {
name.len() + 1 name.len() + 1
} else { } else {
1 1
@ -311,8 +315,8 @@ impl<W: Write> Writer<W> {
0b100 0b100
} else { } else {
0 0
} | if try_block.finally.is_some() { 0b10 } else { 0 } | } | if try_block.finally.is_some() { 0b10 } else { 0 }
if try_block.catch.is_some() { 0b1 } else { 0 }, | if try_block.catch.is_some() { 0b1 } else { 0 },
)?; )?;
self.write_u16(try_length as u16)?; self.write_u16(try_length as u16)?;
self.write_u16(catch_length as u16)?; self.write_u16(catch_length as u16)?;
@ -333,7 +337,9 @@ impl<W: Write> Writer<W> {
self.write_u16(frame)?; self.write_u16(frame)?;
self.write_u8(num_actions_to_skip)?; self.write_u8(num_actions_to_skip)?;
} }
Action::WaitForFrame2 { num_actions_to_skip } => { Action::WaitForFrame2 {
num_actions_to_skip,
} => {
self.write_action_header(OpCode::WaitForFrame2, 1)?; self.write_action_header(OpCode::WaitForFrame2, 1)?;
self.write_u8(num_actions_to_skip)?; self.write_u8(num_actions_to_skip)?;
} }
@ -432,9 +438,7 @@ mod tests {
if written_bytes != expected_bytes { if written_bytes != expected_bytes {
panic!( panic!(
"Error writing action.\nTag:\n{:?}\n\nWrote:\n{:?}\n\nExpected:\n{:?}", "Error writing action.\nTag:\n{:?}\n\nWrote:\n{:?}\n\nExpected:\n{:?}",
action, action, written_bytes, expected_bytes
written_bytes,
expected_bytes
); );
} }
} }

View File

@ -1,5 +1,5 @@
pub mod types;
pub mod read; pub mod read;
pub mod types;
pub mod write; pub mod write;
mod opcode; mod opcode;

View File

@ -1,7 +1,7 @@
#![allow(clippy::useless_attribute)] #![allow(clippy::useless_attribute)]
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug,PartialEq,Clone,Copy,FromPrimitive)] #[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
pub enum OpCode { pub enum OpCode {
Add = 0xA0, Add = 0xA0,
AddI = 0xC5, AddI = 0xC5,

View File

@ -90,10 +90,9 @@ impl<R: Read> Reader<R> {
} }
fn read_i24(&mut self) -> Result<i32> { fn read_i24(&mut self) -> Result<i32> {
Ok( Ok(i32::from(self.read_u8()?)
i32::from(self.read_u8()?) | (i32::from(self.read_u8()?) << 8) | | (i32::from(self.read_u8()?) << 8)
(i32::from(self.read_u8()?) << 16), | (i32::from(self.read_u8()?) << 16))
)
} }
fn read_i32(&mut self) -> Result<i32> { fn read_i32(&mut self) -> Result<i32> {
let mut n: i32 = 0; let mut n: i32 = 0;
@ -114,7 +113,10 @@ impl<R: Read> Reader<R> {
fn read_string(&mut self) -> Result<String> { fn read_string(&mut self) -> Result<String> {
let len = self.read_u30()? as usize; let len = self.read_u30()? as usize;
let mut s = String::with_capacity(len); let mut s = String::with_capacity(len);
self.inner.by_ref().take(len as u64).read_to_string(&mut s)?; self.inner
.by_ref()
.take(len as u64)
.read_to_string(&mut s)?;
Ok(s) Ok(s)
} }
@ -352,10 +354,7 @@ impl<R: Read> Reader<R> {
value: self.read_index()?, value: self.read_index()?,
}) })
} }
Ok(Metadata { Ok(Metadata { name, items })
name,
items,
})
} }
fn read_instance(&mut self) -> Result<Instance> { fn read_instance(&mut self) -> Result<Instance> {
@ -877,8 +876,7 @@ pub mod tests {
// Failed, result doesn't match. // Failed, result doesn't match.
panic!( panic!(
"Incorrectly parsed ABC.\nRead:\n{:?}\n\nExpected:\n{:?}", "Incorrectly parsed ABC.\nRead:\n{:?}\n\nExpected:\n{:?}",
parsed, parsed, abc_file
abc_file
); );
} }
} }

View File

@ -60,8 +60,12 @@ pub enum Multiname {
namespace: Index<Namespace>, namespace: Index<Namespace>,
name: Index<String>, name: Index<String>,
}, },
RTQName { name: Index<String> }, RTQName {
RTQNameA { name: Index<String> }, name: Index<String>,
},
RTQNameA {
name: Index<String>,
},
RTQNameL, RTQNameL,
RTQNameLA, RTQNameLA,
Multiname { Multiname {
@ -72,8 +76,12 @@ pub enum Multiname {
namespace_set: Index<NamespaceSet>, namespace_set: Index<NamespaceSet>,
name: Index<String>, name: Index<String>,
}, },
MultinameL { namespace_set: Index<NamespaceSet> }, MultinameL {
MultinameLA { namespace_set: Index<NamespaceSet> }, namespace_set: Index<NamespaceSet>,
},
MultinameLA {
namespace_set: Index<NamespaceSet>,
},
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -178,10 +186,22 @@ pub enum TraitKind {
type_name: Index<Multiname>, type_name: Index<Multiname>,
value: Option<DefaultValue>, value: Option<DefaultValue>,
}, },
Method { disp_id: u32, method: Index<Method> }, Method {
Getter { disp_id: u32, method: Index<Method> }, disp_id: u32,
Setter { disp_id: u32, method: Index<Method> }, method: Index<Method>,
Class { slot_id: u32, class: Index<Class> }, },
Getter {
disp_id: u32,
method: Index<Method>,
},
Setter {
disp_id: u32,
method: Index<Method>,
},
Class {
slot_id: u32,
class: Index<Class>,
},
Function { Function {
slot_id: u32, slot_id: u32,
function: Index<Method>, function: Index<Method>,
@ -209,14 +229,21 @@ pub struct Script {
pub enum Op { pub enum Op {
Add, Add,
AddI, AddI,
AsType { type_name: Index<Multiname> }, AsType {
type_name: Index<Multiname>,
},
AsTypeLate, AsTypeLate,
BitAnd, BitAnd,
BitNot, BitNot,
BitOr, BitOr,
BitXor, BitXor,
Call { num_args: u32 }, Call {
CallMethod { index: Index<Method>, num_args: u32 }, num_args: u32,
},
CallMethod {
index: Index<Method>,
num_args: u32,
},
CallProperty { CallProperty {
index: Index<Multiname>, index: Index<Multiname>,
num_args: u32, num_args: u32,
@ -229,7 +256,10 @@ pub enum Op {
index: Index<Multiname>, index: Index<Multiname>,
num_args: u32, num_args: u32,
}, },
CallStatic { index: Index<Method>, num_args: u32 }, CallStatic {
index: Index<Method>,
num_args: u32,
},
CallSuper { CallSuper {
index: Index<Multiname>, index: Index<Multiname>,
num_args: u32, num_args: u32,
@ -239,15 +269,21 @@ pub enum Op {
num_args: u32, num_args: u32,
}, },
CheckFilter, CheckFilter,
Coerce { index: Index<Multiname> }, Coerce {
index: Index<Multiname>,
},
CoerceA, CoerceA,
CoerceS, CoerceS,
Construct { num_args: u32 }, Construct {
num_args: u32,
},
ConstructProp { ConstructProp {
index: Index<Multiname>, index: Index<Multiname>,
num_args: u32, num_args: u32,
}, },
ConstructSuper { num_args: u32 }, ConstructSuper {
num_args: u32,
},
ConvertB, ConvertB,
ConvertD, ConvertD,
ConvertI, ConvertI,
@ -259,31 +295,63 @@ pub enum Op {
register_name: Index<String>, register_name: Index<String>,
register: u8, register: u8,
}, },
DebugFile { file_name: Index<String> }, DebugFile {
DebugLine { line_num: u32 }, file_name: Index<String>,
DecLocal { index: u32 }, },
DecLocalI { index: u32 }, DebugLine {
line_num: u32,
},
DecLocal {
index: u32,
},
DecLocalI {
index: u32,
},
Decrement, Decrement,
DecrementI, DecrementI,
DeleteProperty { index: Index<Multiname> }, DeleteProperty {
index: Index<Multiname>,
},
Divide, Divide,
Dup, Dup,
Dxns { index: Index<String> }, Dxns {
index: Index<String>,
},
DxnsLate, DxnsLate,
Equals, Equals,
EscXAttr, EscXAttr,
EscXElem, EscXElem,
FindProperty { index: Index<Multiname> }, FindProperty {
FindPropStrict { index: Index<Multiname> }, index: Index<Multiname>,
GetDescendants { index: Index<Multiname> }, },
FindPropStrict {
index: Index<Multiname>,
},
GetDescendants {
index: Index<Multiname>,
},
GetGlobalScope, GetGlobalScope,
GetGlobalSlot { index: u32 }, GetGlobalSlot {
GetLex { index: Index<Multiname> }, index: u32,
GetLocal { index: u32 }, },
GetProperty { index: Index<Multiname> }, GetLex {
GetScopeObject { index: u8 }, index: Index<Multiname>,
GetSlot { index: u32 }, },
GetSuper { index: Index<Multiname> }, GetLocal {
index: u32,
},
GetProperty {
index: Index<Multiname>,
},
GetScopeObject {
index: u8,
},
GetSlot {
index: u32,
},
GetSuper {
index: Index<Multiname>,
},
GreaterEquals, GreaterEquals,
GreaterThan, GreaterThan,
HasNext, HasNext,
@ -291,31 +359,71 @@ pub enum Op {
object_register: u32, object_register: u32,
index_register: u32, index_register: u32,
}, },
IfEq { offset: i32 }, IfEq {
IfFalse { offset: i32 }, offset: i32,
IfGe { offset: i32 }, },
IfGt { offset: i32 }, IfFalse {
IfLe { offset: i32 }, offset: i32,
IfLt { offset: i32 }, },
IfNge { offset: i32 }, IfGe {
IfNgt { offset: i32 }, offset: i32,
IfNle { offset: i32 }, },
IfNlt { offset: i32 }, IfGt {
IfNe { offset: i32 }, offset: i32,
IfStrictEq { offset: i32 }, },
IfStrictNe { offset: i32 }, IfLe {
IfTrue { offset: i32 }, offset: i32,
},
IfLt {
offset: i32,
},
IfNge {
offset: i32,
},
IfNgt {
offset: i32,
},
IfNle {
offset: i32,
},
IfNlt {
offset: i32,
},
IfNe {
offset: i32,
},
IfStrictEq {
offset: i32,
},
IfStrictNe {
offset: i32,
},
IfTrue {
offset: i32,
},
In, In,
IncLocal { index: u32 }, IncLocal {
IncLocalI { index: u32 }, index: u32,
},
IncLocalI {
index: u32,
},
Increment, Increment,
IncrementI, IncrementI,
InitProperty { index: Index<Multiname> }, InitProperty {
index: Index<Multiname>,
},
InstanceOf, InstanceOf,
IsType { index: Index<Multiname> }, IsType {
index: Index<Multiname>,
},
IsTypeLate, IsTypeLate,
Jump { offset: i32 }, Jump {
Kill { index: u32 }, offset: i32,
},
Kill {
index: u32,
},
Label, Label,
LessEquals, LessEquals,
LessThan, LessThan,
@ -330,39 +438,73 @@ pub enum Op {
Negate, Negate,
NegateI, NegateI,
NewActivation, NewActivation,
NewArray { num_args: u32 }, NewArray {
NewCatch { index: Index<Exception> }, num_args: u32,
NewClass { index: Index<Class> }, },
NewFunction { index: Index<Method> }, NewCatch {
NewObject { num_args: u32 }, index: Index<Exception>,
},
NewClass {
index: Index<Class>,
},
NewFunction {
index: Index<Method>,
},
NewObject {
num_args: u32,
},
NextName, NextName,
NextValue, NextValue,
Nop, Nop,
Not, Not,
Pop, Pop,
PopScope, PopScope,
PushByte { value: u8 }, PushByte {
PushDouble { value: Index<f64> }, value: u8,
},
PushDouble {
value: Index<f64>,
},
PushFalse, PushFalse,
PushInt { value: Index<i32> }, PushInt {
PushNamespace { value: Index<Namespace> }, value: Index<i32>,
},
PushNamespace {
value: Index<Namespace>,
},
PushNaN, PushNaN,
PushNull, PushNull,
PushScope, PushScope,
PushShort { value: u32 }, // TODO: Is this really a u30? PushShort {
PushString { value: Index<String> }, value: u32,
}, // TODO: Is this really a u30?
PushString {
value: Index<String>,
},
PushTrue, PushTrue,
PushUint { value: Index<u32> }, PushUint {
value: Index<u32>,
},
PushUndefined, PushUndefined,
PushWith, PushWith,
ReturnValue, ReturnValue,
ReturnVoid, ReturnVoid,
RShift, RShift,
SetLocal { index: u32 }, SetLocal {
SetGlobalSlot { index: u32 }, index: u32,
SetProperty { index: Index<Multiname> }, },
SetSlot { index: u32 }, SetGlobalSlot {
SetSuper { index: Index<Multiname> }, index: u32,
},
SetProperty {
index: Index<Multiname>,
},
SetSlot {
index: u32,
},
SetSuper {
index: Index<Multiname>,
},
StrictEquals, StrictEquals,
Subtract, Subtract,
SubtractI, SubtractI,

View File

@ -293,13 +293,12 @@ impl<W: Write> Writer<W> {
} }
self.write_index(&method.name)?; self.write_index(&method.name)?;
self.write_u8( self.write_u8(
if has_param_names { 0x80 } else { 0 } | if method.needs_dxns { 0x40 } else { 0 } | if has_param_names { 0x80 } else { 0 }
if num_optional_params > 0 { 0x08 } else { 0 } | if method.needs_rest { | if method.needs_dxns { 0x40 } else { 0 }
0x04 | if num_optional_params > 0 { 0x08 } else { 0 }
} else { | if method.needs_rest { 0x04 } else { 0 }
0 | if method.needs_activation { 0x02 } else { 0 }
} | if method.needs_activation { 0x02 } else { 0 } | | if method.needs_arguments_object {
if method.needs_arguments_object {
0x01 0x01
} else { } else {
0 0
@ -396,11 +395,9 @@ impl<W: Write> Writer<W> {
0x08 0x08
} else { } else {
0 0
} | if instance.is_interface { 0x04 } else { 0 } | if instance.is_final { } | if instance.is_interface { 0x04 } else { 0 }
0x02 | if instance.is_final { 0x02 } else { 0 }
} else { | if instance.is_sealed { 0x01 } else { 0 },
0
} | if instance.is_sealed { 0x01 } else { 0 },
)?; )?;
if let Some(ref namespace) = instance.protected_namespace { if let Some(ref namespace) = instance.protected_namespace {
@ -442,11 +439,12 @@ impl<W: Write> Writer<W> {
fn write_trait(&mut self, t: &Trait) -> Result<()> { fn write_trait(&mut self, t: &Trait) -> Result<()> {
self.write_index(&t.name)?; self.write_index(&t.name)?;
let flags = if !t.metadata.is_empty() { 0b0100_0000 } else { 0 } | if t.is_override { let flags = if !t.metadata.is_empty() {
0b0010_0000 0b0100_0000
} else { } else {
0 0
} | if t.is_final { 0b0001_0000 } else { 0 }; } | if t.is_override { 0b0010_0000 } else { 0 }
| if t.is_final { 0b0001_0000 } else { 0 };
match t.kind { match t.kind {
TraitKind::Slot { TraitKind::Slot {
@ -990,8 +988,7 @@ pub mod tests {
// Failed, result doesn't match. // Failed, result doesn't match.
panic!( panic!(
"Incorrectly written ABC.\nWritten:\n{:?}\n\nExpected:\n{:?}", "Incorrectly written ABC.\nWritten:\n{:?}\n\nExpected:\n{:?}",
out, out, bytes
bytes
); );
} }
} }

View File

@ -1,9 +1,9 @@
#![allow(clippy::float_cmp, clippy::inconsistent_digit_grouping, clippy::unreadable_literal)] #![allow(clippy::float_cmp, clippy::inconsistent_digit_grouping, clippy::unreadable_literal)]
use crate::types::*;
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use std::collections::HashSet; use std::collections::HashSet;
use std::io::{Error, ErrorKind, Read, Result}; use std::io::{Error, ErrorKind, Read, Result};
use crate::types::*;
/// Reads SWF data from a stream. /// Reads SWF data from a stream.
pub fn read_swf<R: Read>(input: R) -> Result<Swf> { pub fn read_swf<R: Read>(input: R) -> Result<Swf> {
@ -53,18 +53,21 @@ fn make_zlib_reader<'a, R: Read + 'a>(input: R) -> Result<Box<Read + 'a>> {
Ok(Box::new(decoder)) Ok(Box::new(decoder))
} }
#[cfg(not(any(feature = "flate2",feature = "libflate")))] #[cfg(not(any(feature = "flate2", feature = "libflate")))]
fn make_zlib_reader<'a, R: Read + 'a>(_input: R) -> Result<Box<Read + 'a>> { fn make_zlib_reader<'a, R: Read + 'a>(_input: R) -> Result<Box<Read + 'a>> {
Err(Error::new(ErrorKind::InvalidData, "Support for Zlib compressed SWFs is not enabled.")) Err(Error::new(
ErrorKind::InvalidData,
"Support for Zlib compressed SWFs is not enabled.",
))
} }
#[cfg(feature = "lzma-support")] #[cfg(feature = "lzma-support")]
fn make_lzma_reader<'a, R: Read + 'a>(mut input: R) -> Result<Box<Read + 'a>> { fn make_lzma_reader<'a, R: Read + 'a>(mut input: R) -> Result<Box<Read + 'a>> {
// Flash uses a mangled LZMA header, so we have to massage it into the normal // Flash uses a mangled LZMA header, so we have to massage it into the normal
// format. // format.
use byteorder::WriteBytesExt;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use xz2::stream::{Action, Stream}; use xz2::stream::{Action, Stream};
use byteorder::WriteBytesExt;
input.read_u32::<LittleEndian>()?; // Compressed length input.read_u32::<LittleEndian>()?; // Compressed length
let mut lzma_properties = [0u8; 5]; let mut lzma_properties = [0u8; 5];
input.read_exact(&mut lzma_properties)?; input.read_exact(&mut lzma_properties)?;
@ -78,7 +81,10 @@ fn make_lzma_reader<'a, R: Read + 'a>(mut input: R) -> Result<Box<Read + 'a>> {
#[cfg(not(feature = "lzma-support"))] #[cfg(not(feature = "lzma-support"))]
fn make_lzma_reader<'a, R: Read + 'a>(_input: R) -> Result<Box<Read + 'a>> { fn make_lzma_reader<'a, R: Read + 'a>(_input: R) -> Result<Box<Read + 'a>> {
Err(Error::new(ErrorKind::InvalidData, "Support for LZMA compressed SWFs is not enabled.")) Err(Error::new(
ErrorKind::InvalidData,
"Support for LZMA compressed SWFs is not enabled.",
))
} }
pub trait SwfRead<R: Read> { pub trait SwfRead<R: Read> {
@ -143,9 +149,8 @@ pub trait SwfRead<R: Read> {
} }
// TODO: There is probably a better way to do this. // TODO: There is probably a better way to do this.
// TODO: Verify ANSI for SWF 5 and earlier. // TODO: Verify ANSI for SWF 5 and earlier.
String::from_utf8(bytes).map_err(|_| { String::from_utf8(bytes)
Error::new(ErrorKind::InvalidData, "Invalid string data") .map_err(|_| Error::new(ErrorKind::InvalidData, "Invalid string data"))
})
} }
} }
@ -297,12 +302,7 @@ impl<R: Read> Reader<R> {
let r = self.read_u8()?; let r = self.read_u8()?;
let g = self.read_u8()?; let g = self.read_u8()?;
let b = self.read_u8()?; let b = self.read_u8()?;
Ok(Color { Ok(Color { r, g, b, a: 255 })
r,
g,
b,
a: 255,
})
} }
fn read_rgba(&mut self) -> Result<Color> { fn read_rgba(&mut self) -> Result<Color> {
@ -310,12 +310,7 @@ impl<R: Read> Reader<R> {
let g = self.read_u8()?; let g = self.read_u8()?;
let b = self.read_u8()?; let b = self.read_u8()?;
let a = self.read_u8()?; let a = self.read_u8()?;
Ok(Color { Ok(Color { r, g, b, a })
r,
g,
b,
a,
})
} }
fn read_color_transform_no_alpha(&mut self) -> Result<ColorTransform> { fn read_color_transform_no_alpha(&mut self) -> Result<ColorTransform> {
@ -452,19 +447,13 @@ impl<R: Read> Reader<R> {
let id = tag_reader.read_u16()?; let id = tag_reader.read_u16()?;
let mut jpeg_data = Vec::with_capacity(length - 2); let mut jpeg_data = Vec::with_capacity(length - 2);
tag_reader.input.read_to_end(&mut jpeg_data)?; tag_reader.input.read_to_end(&mut jpeg_data)?;
Tag::DefineBits { Tag::DefineBits { id, jpeg_data }
id,
jpeg_data,
}
} }
Some(TagCode::DefineBitsJpeg2) => { Some(TagCode::DefineBitsJpeg2) => {
let id = tag_reader.read_u16()?; let id = tag_reader.read_u16()?;
let mut jpeg_data = Vec::with_capacity(length - 2); let mut jpeg_data = Vec::with_capacity(length - 2);
tag_reader.input.read_to_end(&mut jpeg_data)?; tag_reader.input.read_to_end(&mut jpeg_data)?;
Tag::DefineBitsJpeg2 { Tag::DefineBitsJpeg2 { id, jpeg_data }
id,
jpeg_data,
}
} }
Some(TagCode::DefineBitsJpeg3) => tag_reader.read_define_bits_jpeg_3(3)?, Some(TagCode::DefineBitsJpeg3) => tag_reader.read_define_bits_jpeg_3(3)?,
Some(TagCode::DefineBitsJpeg4) => tag_reader.read_define_bits_jpeg_3(4)?, Some(TagCode::DefineBitsJpeg4) => tag_reader.read_define_bits_jpeg_3(4)?,
@ -549,9 +538,7 @@ impl<R: Read> Reader<R> {
} else { } else {
vec![] vec![]
}; };
Tag::EnableTelemetry { Tag::EnableTelemetry { password_hash }
password_hash,
}
} }
Some(TagCode::ImportAssets) => { Some(TagCode::ImportAssets) => {
let url = tag_reader.read_c_string()?; let url = tag_reader.read_c_string()?;
@ -563,10 +550,7 @@ impl<R: Read> Reader<R> {
name: tag_reader.read_c_string()?, name: tag_reader.read_c_string()?,
}); });
} }
Tag::ImportAssets { Tag::ImportAssets { url, imports }
url,
imports,
}
} }
Some(TagCode::ImportAssets2) => { Some(TagCode::ImportAssets2) => {
let url = tag_reader.read_c_string()?; let url = tag_reader.read_c_string()?;
@ -580,10 +564,7 @@ impl<R: Read> Reader<R> {
name: tag_reader.read_c_string()?, name: tag_reader.read_c_string()?,
}); });
} }
Tag::ImportAssets { Tag::ImportAssets { url, imports }
url,
imports,
}
} }
Some(TagCode::JpegTables) => { Some(TagCode::JpegTables) => {
@ -651,10 +632,7 @@ impl<R: Read> Reader<R> {
let id = tag_reader.read_u16()?; let id = tag_reader.read_u16()?;
let mut action_data = Vec::with_capacity(length); let mut action_data = Vec::with_capacity(length);
tag_reader.input.read_to_end(&mut action_data)?; tag_reader.input.read_to_end(&mut action_data)?;
Tag::DoInitAction { Tag::DoInitAction { id, action_data }
id,
action_data,
}
} }
Some(TagCode::EnableDebugger) => Tag::EnableDebugger(tag_reader.read_c_string()?), Some(TagCode::EnableDebugger) => Tag::EnableDebugger(tag_reader.read_c_string()?),
@ -724,8 +702,9 @@ impl<R: Read> Reader<R> {
Some(TagCode::FrameLabel) => { Some(TagCode::FrameLabel) => {
let label = tag_reader.read_c_string()?; let label = tag_reader.read_c_string()?;
Tag::FrameLabel { Tag::FrameLabel {
is_anchor: tag_reader.version >= 6 && length > label.len() + 1 && is_anchor: tag_reader.version >= 6
tag_reader.read_u8()? != 0, && length > label.len() + 1
&& tag_reader.read_u8()? != 0,
label, label,
} }
} }
@ -760,10 +739,7 @@ impl<R: Read> Reader<R> {
let size = length as usize; let size = length as usize;
let mut data = vec![0; size]; let mut data = vec![0; size];
tag_reader.input.read_exact(&mut data[..])?; tag_reader.input.read_exact(&mut data[..])?;
Tag::Unknown { Tag::Unknown { tag_code, data }
tag_code,
data,
}
} }
}; };
@ -799,15 +775,13 @@ impl<R: Read> Reader<R> {
id, id,
is_track_as_menu: false, is_track_as_menu: false,
records, records,
actions: vec![ actions: vec![ButtonAction {
ButtonAction { conditions: vec![ButtonActionCondition::OverDownToOverUp]
conditions: vec![ButtonActionCondition::OverDownToOverUp] .into_iter()
.into_iter() .collect(),
.collect(), key_code: None,
key_code: None, action_data: action_data,
action_data: action_data, }],
},
],
}))) })))
} }
@ -1015,10 +989,7 @@ impl<R: Read> Reader<R> {
} }
} }
Ok(Tag::DefineFont(Box::new(FontV1 { Ok(Tag::DefineFont(Box::new(FontV1 { id, glyphs })))
id,
glyphs,
})))
} }
fn read_define_font_2(&mut self, version: u8) -> Result<Tag> { fn read_define_font_2(&mut self, version: u8) -> Result<Tag> {
@ -2605,12 +2576,12 @@ impl<R: Read> Reader<R> {
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*;
use crate::tag_codes::TagCode;
use crate::test_data;
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use std::vec::Vec; use std::vec::Vec;
use super::*;
use crate::test_data;
use crate::tag_codes::TagCode;
fn reader(data: &[u8]) -> Reader<&[u8]> { fn reader(data: &[u8]) -> Reader<&[u8]> {
let default_version = 13; let default_version = 13;
@ -2731,22 +2702,8 @@ pub mod tests {
.map(|_| reader.read_bit().unwrap()) .map(|_| reader.read_bit().unwrap())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
[ [
false, false, true, false, true, false, true, false, true, false, false, true, false,
true, false, true, false, true
false,
true,
false,
true,
false,
true,
false,
false,
true,
false,
false,
true,
false,
true
] ]
); );
} }
@ -2795,13 +2752,7 @@ pub mod tests {
#[test] #[test]
fn read_fixed8() { fn read_fixed8() {
let buf = [ let buf = [
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0b10000000, 0b00000110, 0b01000000,
0b00000000,
0b00000000,
0b00000001,
0b10000000,
0b00000110,
0b01000000,
0b11101011, 0b11101011,
]; ];
let mut reader = Reader::new(&buf[..], 1); let mut reader = Reader::new(&buf[..], 1);
@ -3059,8 +3010,7 @@ pub mod tests {
// Failed, result doesn't match. // Failed, result doesn't match.
panic!( panic!(
"Incorrectly parsed tag.\nRead:\n{:?}\n\nExpected:\n{:?}", "Incorrectly parsed tag.\nRead:\n{:?}\n\nExpected:\n{:?}",
parsed_tag, parsed_tag, expected_tag
expected_tag
); );
} }
} }

View File

@ -1,7 +1,7 @@
#![allow(clippy::useless_attribute)] #![allow(clippy::useless_attribute)]
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug,PartialEq,Clone,Copy,FromPrimitive)] #[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
pub enum TagCode { pub enum TagCode {
End = 0, End = 0,
ShowFrame = 1, ShowFrame = 1,

File diff suppressed because it is too large Load Diff

View File

@ -153,7 +153,6 @@ pub enum PlaceObjectAction {
Replace(CharacterId), Replace(CharacterId),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum Filter { pub enum Filter {
DropShadowFilter(Box<DropShadowFilter>), DropShadowFilter(Box<DropShadowFilter>),
@ -318,9 +317,18 @@ pub enum Tag {
Protect(Option<String>), Protect(Option<String>),
CsmTextSettings(CsmTextSettings), CsmTextSettings(CsmTextSettings),
DefineBinaryData { id: CharacterId, data: Vec<u8> }, DefineBinaryData {
DefineBits { id: CharacterId, jpeg_data: Vec<u8> }, id: CharacterId,
DefineBitsJpeg2 { id: CharacterId, jpeg_data: Vec<u8> }, data: Vec<u8>,
},
DefineBits {
id: CharacterId,
jpeg_data: Vec<u8>,
},
DefineBitsJpeg2 {
id: CharacterId,
jpeg_data: Vec<u8>,
},
DefineBitsJpeg3(DefineBitsJpeg3), DefineBitsJpeg3(DefineBitsJpeg3),
DefineBitsLossless(DefineBitsLossless), DefineBitsLossless(DefineBitsLossless),
DefineButton(Box<Button>), DefineButton(Box<Button>),
@ -362,7 +370,9 @@ pub enum Tag {
action_data: Vec<u8>, action_data: Vec<u8>,
}, },
EnableDebugger(String), EnableDebugger(String),
EnableTelemetry { password_hash: Vec<u8> }, EnableTelemetry {
password_hash: Vec<u8>,
},
Metadata(String), Metadata(String),
ImportAssets { ImportAssets {
url: String, url: String,
@ -370,7 +380,10 @@ pub enum Tag {
}, },
JpegTables(Vec<u8>), JpegTables(Vec<u8>),
SetBackgroundColor(Color), SetBackgroundColor(Color),
SetTabIndex { depth: Depth, tab_index: u16 }, SetTabIndex {
depth: Depth,
tab_index: u16,
},
SoundStreamBlock(Vec<u8>), SoundStreamBlock(Vec<u8>),
SoundStreamHead(Box<SoundStreamInfo>), SoundStreamHead(Box<SoundStreamInfo>),
SoundStreamHead2(Box<SoundStreamInfo>), SoundStreamHead2(Box<SoundStreamInfo>),
@ -391,13 +404,19 @@ pub enum Tag {
VideoFrame(VideoFrame), VideoFrame(VideoFrame),
FileAttributes(FileAttributes), FileAttributes(FileAttributes),
FrameLabel { label: String, is_anchor: bool }, FrameLabel {
label: String,
is_anchor: bool,
},
DefineSceneAndFrameLabelData { DefineSceneAndFrameLabelData {
scenes: Vec<FrameLabel>, scenes: Vec<FrameLabel>,
frame_labels: Vec<FrameLabel>, frame_labels: Vec<FrameLabel>,
}, },
Unknown { tag_code: u16, data: Vec<u8> }, Unknown {
tag_code: u16,
data: Vec<u8>,
},
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -433,7 +452,6 @@ pub struct Sound {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct SoundInfo { pub struct SoundInfo {
pub event: SoundEvent, pub event: SoundEvent,
@ -443,7 +461,6 @@ pub struct SoundInfo {
pub envelope: Option<SoundEnvelope>, pub envelope: Option<SoundEnvelope>,
} }
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
pub enum SoundEvent { pub enum SoundEvent {
Event, Event,
@ -477,7 +494,10 @@ pub struct ShapeStyles {
pub enum ShapeRecord { pub enum ShapeRecord {
// TODO: Twips // TODO: Twips
StyleChange(StyleChangeData), StyleChange(StyleChangeData),
StraightEdge { delta_x: f32, delta_y: f32 }, StraightEdge {
delta_x: f32,
delta_y: f32,
},
CurvedEdge { CurvedEdge {
control_delta_x: f32, control_delta_x: f32,
control_delta_y: f32, control_delta_y: f32,
@ -696,7 +716,6 @@ pub struct FontV1 {
pub glyphs: Vec<Vec<ShapeRecord>>, pub glyphs: Vec<Vec<ShapeRecord>>,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Font { pub struct Font {
pub version: u8, pub version: u8,

View File

@ -1,11 +1,11 @@
#![allow(clippy::cyclomatic_complexity, clippy::float_cmp, clippy::inconsistent_digit_grouping, clippy::unreadable_literal)] #![allow(clippy::cyclomatic_complexity, clippy::float_cmp, clippy::inconsistent_digit_grouping, clippy::unreadable_literal)]
use crate::tag_codes::TagCode;
use crate::types::*;
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
use std::cmp::max; use std::cmp::max;
use std::collections::HashSet; use std::collections::HashSet;
use std::io::{Error, ErrorKind, Result, Write}; use std::io::{Error, ErrorKind, Result, Write};
use crate::tag_codes::TagCode;
use crate::types::*;
pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> { pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> {
let signature = match swf.compression { let signature = match swf.compression {
@ -53,8 +53,8 @@ pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> {
#[cfg(feature = "flate2")] #[cfg(feature = "flate2")]
fn write_zlib_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> { fn write_zlib_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> {
use flate2::Compression;
use flate2::write::ZlibEncoder; use flate2::write::ZlibEncoder;
use flate2::Compression;
let mut encoder = ZlibEncoder::new(&mut output, Compression::best()); let mut encoder = ZlibEncoder::new(&mut output, Compression::best());
encoder.write_all(&swf_body) encoder.write_all(&swf_body)
} }
@ -66,15 +66,18 @@ fn write_zlib_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> {
encoder.write_all(&swf_body) encoder.write_all(&swf_body)
} }
#[cfg(not(any(feature = "flate2",feature = "libflate")))] #[cfg(not(any(feature = "flate2", feature = "libflate")))]
fn write_zlib_swf<W: Write>(_output: W, _swf_body: &[u8]) -> Result<()> { fn write_zlib_swf<W: Write>(_output: W, _swf_body: &[u8]) -> Result<()> {
Err(Error::new(ErrorKind::InvalidData, "Support for Zlib compressed SWFs is not enabled.")) Err(Error::new(
ErrorKind::InvalidData,
"Support for Zlib compressed SWFs is not enabled.",
))
} }
#[cfg(feature = "lzma-support")] #[cfg(feature = "lzma-support")]
fn write_lzma_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> { fn write_lzma_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> {
use xz2::write::XzEncoder;
use xz2::stream::{Action, LzmaOptions, Stream}; use xz2::stream::{Action, LzmaOptions, Stream};
use xz2::write::XzEncoder;
let mut stream = Stream::new_lzma_encoder(&LzmaOptions::new_preset(9)?)?; let mut stream = Stream::new_lzma_encoder(&LzmaOptions::new_preset(9)?)?;
let mut lzma_header = [0; 13]; let mut lzma_header = [0; 13];
stream.process(&[], &mut lzma_header, Action::Run)?; stream.process(&[], &mut lzma_header, Action::Run)?;
@ -88,7 +91,10 @@ fn write_lzma_swf<W: Write>(mut output: W, swf_body: &[u8]) -> Result<()> {
#[cfg(not(feature = "lzma-support"))] #[cfg(not(feature = "lzma-support"))]
fn write_lzma_swf<W: Write>(_output: W, _swf_body: &[u8]) -> Result<()> { fn write_lzma_swf<W: Write>(_output: W, _swf_body: &[u8]) -> Result<()> {
Err(Error::new(ErrorKind::InvalidData, "Support for LZMA compressed SWFs is not enabled.")) Err(Error::new(
ErrorKind::InvalidData,
"Support for LZMA compressed SWFs is not enabled.",
))
} }
pub trait SwfWrite<W: Write> { pub trait SwfWrite<W: Write> {
@ -246,7 +252,6 @@ impl<W: Write> Writer<W> {
Ok(()) Ok(())
} }
fn write_ubits(&mut self, num_bits: u8, n: u32) -> Result<()> { fn write_ubits(&mut self, num_bits: u8, n: u32) -> Result<()> {
for i in 0..num_bits { for i in 0..num_bits {
self.write_bit(n & (1 << u32::from(num_bits - i - 1)) != 0)?; self.write_bit(n & (1 << u32::from(num_bits - i - 1)) != 0)?;
@ -284,10 +289,11 @@ impl<W: Write> Writer<W> {
rectangle.x_max, rectangle.x_max,
rectangle.y_min, rectangle.y_min,
rectangle.y_max, rectangle.y_max,
].iter() ]
.map(|x| count_sbits((*x * 20f32) as i32)) .iter()
.max() .map(|x| count_sbits((*x * 20f32) as i32))
.unwrap(); .max()
.unwrap();
self.write_ubits(5, num_bits.into())?; self.write_ubits(5, num_bits.into())?;
self.write_sbits(num_bits, (rectangle.x_min * 20f32) as i32)?; self.write_sbits(num_bits, (rectangle.x_min * 20f32) as i32)?;
self.write_sbits(num_bits, (rectangle.x_max * 20f32) as i32)?; self.write_sbits(num_bits, (rectangle.x_max * 20f32) as i32)?;
@ -318,8 +324,9 @@ impl<W: Write> Writer<W> {
fn write_color_transform_no_alpha(&mut self, color_transform: &ColorTransform) -> Result<()> { fn write_color_transform_no_alpha(&mut self, color_transform: &ColorTransform) -> Result<()> {
// TODO: Assert that alpha is 1.0? // TODO: Assert that alpha is 1.0?
self.flush_bits()?; self.flush_bits()?;
let has_mult = color_transform.r_multiply != 1f32 || color_transform.g_multiply != 1f32 || let has_mult = color_transform.r_multiply != 1f32
color_transform.b_multiply != 1f32; || color_transform.g_multiply != 1f32
|| color_transform.b_multiply != 1f32;
let has_add = let has_add =
color_transform.r_add != 0 || color_transform.g_add != 0 || color_transform.b_add != 0; color_transform.r_add != 0 || color_transform.g_add != 0 || color_transform.b_add != 0;
let multiply = [ let multiply = [
@ -347,7 +354,10 @@ impl<W: Write> Writer<W> {
if has_add { if has_add {
num_bits = max( num_bits = max(
num_bits, num_bits,
add.iter().map(|n| count_sbits(i32::from(*n))).max().unwrap(), add.iter()
.map(|n| count_sbits(i32::from(*n)))
.max()
.unwrap(),
); );
} }
self.write_ubits(4, num_bits.into())?; self.write_ubits(4, num_bits.into())?;
@ -366,11 +376,14 @@ impl<W: Write> Writer<W> {
fn write_color_transform(&mut self, color_transform: &ColorTransform) -> Result<()> { fn write_color_transform(&mut self, color_transform: &ColorTransform) -> Result<()> {
self.flush_bits()?; self.flush_bits()?;
let has_mult = color_transform.r_multiply != 1f32 || color_transform.g_multiply != 1f32 || let has_mult = color_transform.r_multiply != 1f32
color_transform.b_multiply != 1f32 || || color_transform.g_multiply != 1f32
color_transform.a_multiply != 1f32; || color_transform.b_multiply != 1f32
let has_add = color_transform.r_add != 0 || color_transform.g_add != 0 || || color_transform.a_multiply != 1f32;
color_transform.b_add != 0 || color_transform.a_add != 0; let has_add = color_transform.r_add != 0
|| color_transform.g_add != 0
|| color_transform.b_add != 0
|| color_transform.a_add != 0;
let multiply = [ let multiply = [
color_transform.r_multiply, color_transform.r_multiply,
color_transform.g_multiply, color_transform.g_multiply,
@ -397,7 +410,10 @@ impl<W: Write> Writer<W> {
if has_add { if has_add {
num_bits = max( num_bits = max(
num_bits, num_bits,
add.iter().map(|n| count_sbits(i32::from(*n))).max().unwrap(), add.iter()
.map(|n| count_sbits(i32::from(*n)))
.max()
.unwrap(),
); );
} }
self.write_ubits(4, num_bits.into())?; self.write_ubits(4, num_bits.into())?;
@ -416,7 +432,6 @@ impl<W: Write> Writer<W> {
Ok(()) Ok(())
} }
fn write_matrix(&mut self, m: &Matrix) -> Result<()> { fn write_matrix(&mut self, m: &Matrix) -> Result<()> {
self.flush_bits()?; self.flush_bits()?;
// Scale // Scale
@ -466,8 +481,9 @@ impl<W: Write> Writer<W> {
Tag::ShowFrame => self.write_tag_header(TagCode::ShowFrame, 0)?, Tag::ShowFrame => self.write_tag_header(TagCode::ShowFrame, 0)?,
Tag::ExportAssets(ref exports) => { Tag::ExportAssets(ref exports) => {
let len = exports.iter().map(|e| e.name.len() as u32 + 1).sum::<u32>() + let len = exports.iter().map(|e| e.name.len() as u32 + 1).sum::<u32>()
exports.len() as u32 * 2 + 2; + exports.len() as u32 * 2
+ 2;
self.write_tag_header(TagCode::ExportAssets, len)?; self.write_tag_header(TagCode::ExportAssets, len)?;
self.write_u16(exports.len() as u16)?; self.write_u16(exports.len() as u16)?;
for &ExportedAsset { id, ref name } in exports { for &ExportedAsset { id, ref name } in exports {
@ -686,9 +702,10 @@ impl<W: Write> Writer<W> {
Tag::DefineFontInfo(ref font_info) => { Tag::DefineFontInfo(ref font_info) => {
let use_wide_codes = self.version >= 6 || font_info.version >= 2; let use_wide_codes = self.version >= 6 || font_info.version >= 2;
let len = font_info.name.len() + let len = font_info.name.len()
if use_wide_codes { 2 } else { 1 } * font_info.code_table.len() + + if use_wide_codes { 2 } else { 1 } * font_info.code_table.len()
if font_info.version >= 2 { 1 } else { 0 } + 4; + if font_info.version >= 2 { 1 } else { 0 }
+ 4;
let tag_id = if font_info.version == 1 { let tag_id = if font_info.version == 1 {
TagCode::DefineFontInfo TagCode::DefineFontInfo
@ -702,14 +719,12 @@ impl<W: Write> Writer<W> {
self.write_u8(font_info.name.len() as u8)?; self.write_u8(font_info.name.len() as u8)?;
self.output.write_all(font_info.name.as_bytes())?; self.output.write_all(font_info.name.as_bytes())?;
self.write_u8( self.write_u8(
if font_info.is_small_text { 0b100000 } else { 0 } | if font_info.is_ansi { if font_info.is_small_text { 0b100000 } else { 0 }
0b10000 | if font_info.is_ansi { 0b10000 } else { 0 }
} else { | if font_info.is_shift_jis { 0b1000 } else { 0 }
0 | if font_info.is_italic { 0b100 } else { 0 }
} | if font_info.is_shift_jis { 0b1000 } else { 0 } | | if font_info.is_bold { 0b10 } else { 0 }
if font_info.is_italic { 0b100 } else { 0 } | | if use_wide_codes { 0b1 } else { 0 },
if font_info.is_bold { 0b10 } else { 0 } |
if use_wide_codes { 0b1 } else { 0 },
)?; )?;
// TODO(Herschel): Assert language is unknown for v1. // TODO(Herschel): Assert language is unknown for v1.
if font_info.version >= 2 { if font_info.version >= 2 {
@ -793,21 +808,25 @@ impl<W: Write> Writer<W> {
self.write_c_string(password_md5)?; self.write_c_string(password_md5)?;
} }
Tag::EnableTelemetry { ref password_hash } => if !password_hash.is_empty() { Tag::EnableTelemetry { ref password_hash } => {
self.write_tag_header(TagCode::EnableTelemetry, 34)?; if !password_hash.is_empty() {
self.write_u16(0)?; self.write_tag_header(TagCode::EnableTelemetry, 34)?;
self.output.write_all(&password_hash[0..32])?; self.write_u16(0)?;
} else { self.output.write_all(&password_hash[0..32])?;
self.write_tag_header(TagCode::EnableTelemetry, 2)?; } else {
self.write_u16(0)?; self.write_tag_header(TagCode::EnableTelemetry, 2)?;
}, self.write_u16(0)?;
}
}
Tag::ImportAssets { Tag::ImportAssets {
ref url, ref url,
ref imports, ref imports,
} => { } => {
let len = imports.iter().map(|e| e.name.len() as u32 + 3).sum::<u32>() + let len = imports.iter().map(|e| e.name.len() as u32 + 3).sum::<u32>()
url.len() as u32 + 1 + 2; + url.len() as u32
+ 1
+ 2;
// SWF v8 and later use ImportAssets2 tag. // SWF v8 and later use ImportAssets2 tag.
if self.version >= 8 { if self.version >= 8 {
self.write_tag_header(TagCode::ImportAssets2, len + 2)?; self.write_tag_header(TagCode::ImportAssets2, len + 2)?;
@ -896,13 +915,15 @@ impl<W: Write> Writer<W> {
} }
Tag::StartSound { id, ref sound_info } => { Tag::StartSound { id, ref sound_info } => {
let length = 3 + if sound_info.in_sample.is_some() { 4 } else { 0 } + let length = 3
if sound_info.out_sample.is_some() { + if sound_info.in_sample.is_some() { 4 } else { 0 }
+ if sound_info.out_sample.is_some() {
4 4
} else { } else {
0 0
} + if sound_info.num_loops > 1 { 2 } else { 0 } + }
if let Some(ref e) = sound_info.envelope { + if sound_info.num_loops > 1 { 2 } else { 0 }
+ if let Some(ref e) = sound_info.envelope {
e.len() as u32 * 8 + 1 e.len() as u32 * 8 + 1
} else { } else {
0 0
@ -916,16 +937,16 @@ impl<W: Write> Writer<W> {
ref class_name, ref class_name,
ref sound_info, ref sound_info,
} => { } => {
let length = class_name.len() as u32 + 2 + if sound_info.in_sample.is_some() { let length = class_name.len() as u32
4 + 2
} else { + if sound_info.in_sample.is_some() { 4 } else { 0 }
0 + if sound_info.out_sample.is_some() {
} + if sound_info.out_sample.is_some() { 4
4 } else {
} else { 0
0 }
} + if sound_info.num_loops > 1 { 2 } else { 0 } + + if sound_info.num_loops > 1 { 2 } else { 0 }
if let Some(ref e) = sound_info.envelope { + if let Some(ref e) = sound_info.envelope {
e.len() as u32 * 8 + 1 e.len() as u32 * 8 + 1
} else { } else {
0 0
@ -939,7 +960,8 @@ impl<W: Write> Writer<W> {
let len = symbols let len = symbols
.iter() .iter()
.map(|e| e.class_name.len() as u32 + 3) .map(|e| e.class_name.len() as u32 + 3)
.sum::<u32>() + 2; .sum::<u32>()
+ 2;
self.write_tag_header(TagCode::SymbolClass, len)?; self.write_tag_header(TagCode::SymbolClass, len)?;
self.write_u16(symbols.len() as u16)?; self.write_u16(symbols.len() as u16)?;
for &SymbolClassLink { id, ref class_name } in symbols { for &SymbolClassLink { id, ref class_name } in symbols {
@ -1012,7 +1034,7 @@ impl<W: Write> Writer<W> {
writer.write_button_record(record, 1)?; writer.write_button_record(record, 1)?;
} }
writer.write_u8(0)?; // End button records writer.write_u8(0)?; // End button records
// TODO: Assert we have some action. // TODO: Assert we have some action.
writer.output.write_all(&button.actions[0].action_data)?; writer.output.write_all(&button.actions[0].action_data)?;
} }
self.write_tag_header(TagCode::DefineButton, buf.len() as u32)?; self.write_tag_header(TagCode::DefineButton, buf.len() as u32)?;
@ -1055,63 +1077,56 @@ impl<W: Write> Writer<W> {
0b1000_0000 0b1000_0000
} else { } else {
0 0
} | } | if action
if action .conditions
.conditions .contains(&ButtonActionCondition::OutDownToIdle)
.contains(&ButtonActionCondition::OutDownToIdle) {
{ 0b100_0000
0b100_0000 } else {
} else { 0
0 } | if action
} | .conditions
if action .contains(&ButtonActionCondition::OutDownToOverDown)
.conditions {
.contains(&ButtonActionCondition::OutDownToOverDown) 0b10_0000
{ } else {
0b10_0000 0
} else { } | if action
0 .conditions
} | .contains(&ButtonActionCondition::OverDownToOutDown)
if action {
.conditions 0b1_0000
.contains(&ButtonActionCondition::OverDownToOutDown) } else {
{ 0
0b1_0000 } | if action
} else { .conditions
0 .contains(&ButtonActionCondition::OverDownToOverUp)
} | {
if action 0b1000
.conditions } else {
.contains(&ButtonActionCondition::OverDownToOverUp) 0
{ } | if action
0b1000 .conditions
} else { .contains(&ButtonActionCondition::OverUpToOverDown)
0 {
} | 0b100
if action } else {
.conditions 0
.contains(&ButtonActionCondition::OverUpToOverDown) } | if action
{ .conditions
0b100 .contains(&ButtonActionCondition::OverUpToIdle)
} else { {
0 0b10
} | } else {
if action 0
.conditions } | if action
.contains(&ButtonActionCondition::OverUpToIdle) .conditions
{ .contains(&ButtonActionCondition::IdleToOverUp)
0b10 {
} else { 0b1
0 } else {
} | 0
if action },
.conditions
.contains(&ButtonActionCondition::IdleToOverUp)
{
0b1
} else {
0
},
)?; )?;
let mut flags = if action let mut flags = if action
.conditions .conditions
@ -1136,8 +1151,8 @@ impl<W: Write> Writer<W> {
} }
fn write_define_morph_shape(&mut self, data: &DefineMorphShape) -> Result<()> { fn write_define_morph_shape(&mut self, data: &DefineMorphShape) -> Result<()> {
if data.start.fill_styles.len() != data.end.fill_styles.len() || if data.start.fill_styles.len() != data.end.fill_styles.len()
data.start.line_styles.len() != data.end.line_styles.len() || data.start.line_styles.len() != data.end.line_styles.len()
{ {
return Err(Error::new( return Err(Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
@ -1163,7 +1178,8 @@ impl<W: Write> Writer<W> {
} else { } else {
writer.write_u8(num_fill_styles as u8)?; writer.write_u8(num_fill_styles as u8)?;
} }
for (start, end) in data.start for (start, end) in data
.start
.fill_styles .fill_styles
.iter() .iter()
.zip(data.end.fill_styles.iter()) .zip(data.end.fill_styles.iter())
@ -1177,7 +1193,8 @@ impl<W: Write> Writer<W> {
} else { } else {
writer.write_u8(num_line_styles as u8)?; writer.write_u8(num_line_styles as u8)?;
} }
for (start, end) in data.start for (start, end) in data
.start
.line_styles .line_styles
.iter() .iter()
.zip(data.end.line_styles.iter()) .zip(data.end.line_styles.iter())
@ -1309,8 +1326,8 @@ impl<W: Write> Writer<W> {
is_smoothed: end_is_smoothed, is_smoothed: end_is_smoothed,
is_repeating: end_is_repeating, is_repeating: end_is_repeating,
}, },
) if id == end_id && is_smoothed == end_is_smoothed || ) if id == end_id && is_smoothed == end_is_smoothed
is_repeating == end_is_repeating => || is_repeating == end_is_repeating =>
{ {
let fill_style_type = match (is_smoothed, is_repeating) { let fill_style_type = match (is_smoothed, is_repeating) {
(true, true) => 0x40, (true, true) => 0x40,
@ -1365,11 +1382,13 @@ impl<W: Write> Writer<W> {
self.write_rgba(&start.color)?; self.write_rgba(&start.color)?;
self.write_rgba(&end.color)?; self.write_rgba(&end.color)?;
} else { } else {
if start.start_cap != end.start_cap || start.join_style != end.join_style || if start.start_cap != end.start_cap
start.allow_scale_x != end.allow_scale_x || || start.join_style != end.join_style
start.allow_scale_y != end.allow_scale_y || || start.allow_scale_x != end.allow_scale_x
start.is_pixel_hinted != end.is_pixel_hinted || || start.allow_scale_y != end.allow_scale_y
start.allow_close != end.allow_close || start.end_cap != end.end_cap || start.is_pixel_hinted != end.is_pixel_hinted
|| start.allow_close != end.allow_close
|| start.end_cap != end.end_cap
{ {
return Err(Error::new( return Err(Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
@ -1664,10 +1683,11 @@ impl<W: Write> Writer<W> {
control_twips_y, control_twips_y,
anchor_twips_x, anchor_twips_x,
anchor_twips_y, anchor_twips_y,
].iter() ]
.map(|x| count_sbits(*x)) .iter()
.max() .map(|x| count_sbits(*x))
.unwrap(); .max()
.unwrap();
self.write_ubits(4, u32::from(num_bits) - 2)?; self.write_ubits(4, u32::from(num_bits) - 2)?;
self.write_sbits(num_bits, control_twips_x)?; self.write_sbits(num_bits, control_twips_x)?;
self.write_sbits(num_bits, control_twips_y)?; self.write_sbits(num_bits, control_twips_y)?;
@ -1928,24 +1948,27 @@ impl<W: Write> Writer<W> {
0b10_0000 0b10_0000
} else { } else {
0 0
} | if place_object.is_image { 0b1_0000 } else { 0 } | } | if place_object.is_image { 0b1_0000 } else { 0 }
if place_object.class_name.is_some() { | if place_object.class_name.is_some() {
0b1000 0b1000
} else { } else {
0 0
} | if place_object.is_bitmap_cached { }
0b100 | if place_object.is_bitmap_cached {
} else { 0b100
0 } else {
} | if place_object.blend_mode != BlendMode::Normal { 0
0b10 }
} else { | if place_object.blend_mode != BlendMode::Normal {
0 0b10
} | if !place_object.filters.is_empty() { } else {
0b1 0
} else { }
0 | if !place_object.filters.is_empty() {
}, 0b1
} else {
0
},
)?; )?;
} }
writer.write_i16(place_object.depth)?; writer.write_i16(place_object.depth)?;
@ -1957,8 +1980,8 @@ impl<W: Write> Writer<W> {
} }
match place_object.action { match place_object.action {
PlaceObjectAction::Place(character_id) | PlaceObjectAction::Place(character_id)
PlaceObjectAction::Replace(character_id) => writer.write_u16(character_id)?, | PlaceObjectAction::Replace(character_id) => writer.write_u16(character_id)?,
PlaceObjectAction::Modify => (), PlaceObjectAction::Modify => (),
} }
if let Some(ref matrix) = place_object.matrix { if let Some(ref matrix) = place_object.matrix {
@ -2113,11 +2136,8 @@ impl<W: Write> Writer<W> {
} }
self.write_rgba(&convolve.default_color)?; self.write_rgba(&convolve.default_color)?;
self.write_u8( self.write_u8(
if convolve.is_clamped { 0b10 } else { 0 } | if convolve.is_preserve_alpha { if convolve.is_clamped { 0b10 } else { 0 }
0b1 | if convolve.is_preserve_alpha { 0b1 } else { 0 },
} else {
0
},
)?; )?;
} }
@ -2279,8 +2299,8 @@ impl<W: Write> Writer<W> {
0b10 0b10
} else { } else {
0 0
} | if sound_info.num_loops > 1 { 0b100 } else { 0 } | } | if sound_info.num_loops > 1 { 0b100 } else { 0 }
if sound_info.envelope.is_some() { | if sound_info.envelope.is_some() {
0b1000 0b1000
} else { } else {
0 0
@ -2346,20 +2366,14 @@ impl<W: Write> Writer<W> {
let mut writer = Writer::new(&mut buf, self.version); let mut writer = Writer::new(&mut buf, self.version);
writer.write_character_id(font.id)?; writer.write_character_id(font.id)?;
writer.write_u8( writer.write_u8(
if font.layout.is_some() { 0b10000000 } else { 0 } | if font.is_shift_jis { if font.layout.is_some() { 0b10000000 } else { 0 }
0b1000000 | if font.is_shift_jis { 0b1000000 } else { 0 }
} else { | if font.is_small_text { 0b100000 } else { 0 }
0 | if font.is_ansi { 0b10000 } else { 0 }
} | if font.is_small_text { 0b100000 } else { 0 } | | if has_wide_offsets { 0b1000 } else { 0 }
if font.is_ansi { 0b10000 } else { 0 } | if has_wide_offsets { | if has_wide_codes { 0b100 } else { 0 }
0b1000 | if font.is_italic { 0b10 } else { 0 }
} else { | if font.is_bold { 0b1 } else { 0 },
0
} | if has_wide_codes { 0b100 } else { 0 } | if font.is_italic {
0b10
} else {
0
} | if font.is_bold { 0b1 } else { 0 },
)?; )?;
writer.write_language(font.language)?; writer.write_language(font.language)?;
writer.write_u8(font.name.len() as u8)?; writer.write_u8(font.name.len() as u8)?;
@ -2434,8 +2448,9 @@ impl<W: Write> Writer<W> {
self.write_tag_header(TagCode::DefineFont4, tag_len as u32)?; self.write_tag_header(TagCode::DefineFont4, tag_len as u32)?;
self.write_character_id(font.id)?; self.write_character_id(font.id)?;
self.write_u8( self.write_u8(
if font.data.is_some() { 0b100 } else { 0 } | if font.is_italic { 0b10 } else { 0 } | if font.data.is_some() { 0b100 } else { 0 }
if font.is_bold { 0b1 } else { 0 }, | if font.is_italic { 0b10 } else { 0 }
| if font.is_bold { 0b1 } else { 0 },
)?; )?;
self.write_c_string(&font.name)?; self.write_c_string(&font.name)?;
if let Some(ref data) = font.data { if let Some(ref data) = font.data {
@ -2467,12 +2482,14 @@ impl<W: Write> Writer<W> {
writer.write_character_id(text.id)?; writer.write_character_id(text.id)?;
writer.write_rectangle(&text.bounds)?; writer.write_rectangle(&text.bounds)?;
writer.write_matrix(&text.matrix)?; writer.write_matrix(&text.matrix)?;
let num_glyph_bits = text.records let num_glyph_bits = text
.records
.iter() .iter()
.flat_map(|r| r.glyphs.iter().map(|g| count_ubits(g.index))) .flat_map(|r| r.glyphs.iter().map(|g| count_ubits(g.index)))
.max() .max()
.unwrap_or(0); .unwrap_or(0);
let num_advance_bits = text.records let num_advance_bits = text
.records
.iter() .iter()
.flat_map(|r| r.glyphs.iter().map(|g| count_sbits(g.advance))) .flat_map(|r| r.glyphs.iter().map(|g| count_sbits(g.advance)))
.max() .max()
@ -2481,10 +2498,11 @@ impl<W: Write> Writer<W> {
writer.write_u8(num_advance_bits)?; writer.write_u8(num_advance_bits)?;
for record in &text.records { for record in &text.records {
let flags = 0b10000000 | if record.font_id.is_some() { 0b1000 } else { 0 } | let flags = 0b10000000
if record.color.is_some() { 0b100 } else { 0 } | | if record.font_id.is_some() { 0b1000 } else { 0 }
if record.y_offset.is_some() { 0b10 } else { 0 } | | if record.color.is_some() { 0b100 } else { 0 }
if record.x_offset.is_some() { 0b1 } else { 0 }; | if record.y_offset.is_some() { 0b10 } else { 0 }
| if record.x_offset.is_some() { 0b1 } else { 0 };
writer.write_u8(flags)?; writer.write_u8(flags)?;
if let Some(id) = record.font_id { if let Some(id) = record.font_id {
writer.write_character_id(id)?; writer.write_character_id(id)?;
@ -2524,30 +2542,32 @@ impl<W: Write> Writer<W> {
0b10000000 0b10000000
} else { } else {
0 0
} | if edit_text.is_word_wrap { 0b1000000 } else { 0 } | } | if edit_text.is_word_wrap { 0b1000000 } else { 0 }
if edit_text.is_multiline { 0b100000 } else { 0 } | | if edit_text.is_multiline { 0b100000 } else { 0 }
if edit_text.is_password { 0b10000 } else { 0 } | | if edit_text.is_password { 0b10000 } else { 0 }
if edit_text.is_read_only { 0b1000 } else { 0 } | | if edit_text.is_read_only { 0b1000 } else { 0 }
if edit_text.color.is_some() { 0b100 } else { 0 } | | if edit_text.color.is_some() { 0b100 } else { 0 }
if edit_text.max_length.is_some() { | if edit_text.max_length.is_some() {
0b10 0b10
} else { } else {
0 0
} | if edit_text.font_id.is_some() { 0b1 } else { 0 }; }
| if edit_text.font_id.is_some() { 0b1 } else { 0 };
let flags2 = if edit_text.font_class_name.is_some() { let flags2 = if edit_text.font_class_name.is_some() {
0b10000000 0b10000000
} else { } else {
0 0
} | if edit_text.is_auto_size { 0b1000000 } else { 0 } | } | if edit_text.is_auto_size { 0b1000000 } else { 0 }
if edit_text.layout.is_some() { | if edit_text.layout.is_some() {
0b100000 0b100000
} else { } else {
0 0
} | if !edit_text.is_selectable { 0b10000 } else { 0 } | }
if edit_text.has_border { 0b1000 } else { 0 } | | if !edit_text.is_selectable { 0b10000 } else { 0 }
if edit_text.was_static { 0b100 } else { 0 } | | if edit_text.has_border { 0b1000 } else { 0 }
if edit_text.is_html { 0b10 } else { 0 } | | if edit_text.was_static { 0b100 } else { 0 }
if !edit_text.is_device_font { 0b1 } else { 0 }; | if edit_text.is_html { 0b10 } else { 0 }
| if !edit_text.is_device_font { 0b1 } else { 0 };
writer.write_u8(flags)?; writer.write_u8(flags)?;
writer.write_u8(flags2)?; writer.write_u8(flags2)?;
@ -2677,10 +2697,10 @@ fn count_fbits(n: f32) -> u8 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use super::Writer; use super::Writer;
use std::io::Result; use super::*;
use crate::test_data; use crate::test_data;
use std::io::Result;
fn new_swf() -> Swf { fn new_swf() -> Swf {
Swf { Swf {
@ -2735,13 +2755,7 @@ mod tests {
assert_eq!( assert_eq!(
buf, buf,
[ [
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0b10000000, 0b00000110, 0b01000000,
0b00000000,
0b00000000,
0b00000001,
0b10000000,
0b00000110,
0b01000000,
0b11101011 0b11101011
] ]
); );
@ -2780,22 +2794,8 @@ mod tests {
#[test] #[test]
fn write_bit() { fn write_bit() {
let bits = [ let bits = [
false, false, true, false, true, false, true, false, true, false, false, true, false, false,
true, true, false, true,
false,
true,
false,
true,
false,
true,
false,
false,
true,
false,
false,
true,
false,
true,
]; ];
let mut buf = Vec::new(); let mut buf = Vec::new();
{ {
@ -2900,10 +2900,7 @@ mod tests {
let mut writer = Writer::new(&mut buf, 1); let mut writer = Writer::new(&mut buf, 1);
writer.write_c_string("😀😂!🐼").unwrap(); writer.write_c_string("😀😂!🐼").unwrap();
} }
assert_eq!( assert_eq!(buf, "😀😂!🐼\0".bytes().collect::<Vec<_>>());
buf,
"😀😂!🐼\0".bytes().collect::<Vec<_>>()
);
} }
} }
@ -2999,9 +2996,7 @@ mod tests {
if written_tag_bytes != expected_tag_bytes { if written_tag_bytes != expected_tag_bytes {
panic!( panic!(
"Error reading tag.\nTag:\n{:?}\n\nWrote:\n{:?}\n\nExpected:\n{:?}", "Error reading tag.\nTag:\n{:?}\n\nWrote:\n{:?}\n\nExpected:\n{:?}",
tag, tag, written_tag_bytes, expected_tag_bytes
written_tag_bytes,
expected_tag_bytes
); );
} }
} }