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(dead_code)]
#[derive(Debug,PartialEq,Clone,Copy,FromPrimitive)]
#[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
pub enum OpCode {
End = 0x00,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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