swf: General cleanup

Just mechanical cleanups to ease future refactors.
This commit is contained in:
relrelb 2021-07-09 17:05:13 +03:00 committed by relrelb
parent 8e7ce18cc2
commit ef9c073d26
11 changed files with 82 additions and 118 deletions

View File

@ -18,7 +18,7 @@ use std::fs::File;
let file = File::open("file.swf").unwrap();
let reader = BufReader::new(file);
let swf = swf::read_swf(reader).unwrap();
let swf = swf::parse_swf(reader).unwrap();
println!("The SWF has {} frames", swf.header.num_frames);
```

View File

@ -41,6 +41,18 @@ impl<'a> Reader<'a> {
&mut self.input
}
#[inline]
fn read_f64_me(&mut self) -> Result<f64> {
// Flash weirdly stores (some?) f64 as two LE 32-bit chunks.
// First word is the hi-word, second word is the lo-word.
let mut bytes = self.read_u64()?.to_le_bytes();
bytes.swap(0, 4);
bytes.swap(1, 5);
bytes.swap(2, 6);
bytes.swap(3, 7);
Ok(f64::from_le_bytes(bytes))
}
#[inline]
pub fn read_action(&mut self) -> Result<Option<Action<'a>>> {
let (opcode, mut length) = self.read_opcode_and_length()?;
@ -79,7 +91,6 @@ impl<'a> Reader<'a> {
/// The `length` passed in should be the length excluding any sub-blocks.
/// The final `length` returned will be total length of the action, including sub-blocks.
#[inline]
#[allow(clippy::inconsistent_digit_grouping)]
fn read_op(&mut self, opcode: u8, length: &mut usize) -> Result<Option<Action<'a>>> {
use num_traits::FromPrimitive;
let action = if let Some(op) = OpCode::from_u8(opcode) {

View File

@ -1,90 +1,86 @@
#![allow(clippy::cognitive_complexity, clippy::unreadable_literal)]
use crate::avm1::opcode::OpCode;
use crate::avm1::types::*;
use crate::string::SwfStr;
use crate::write::SwfWriteExt;
use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Result, Write};
use std::io::{Result, Write};
#[allow(dead_code)]
pub struct Writer<W: Write> {
output: W,
#[allow(dead_code)]
version: u8,
}
impl<W: Write> SwfWriteExt for Writer<W> {
#[inline]
fn write_u8(&mut self, n: u8) -> io::Result<()> {
fn write_u8(&mut self, n: u8) -> Result<()> {
self.output.write_u8(n)
}
#[inline]
fn write_u16(&mut self, n: u16) -> io::Result<()> {
fn write_u16(&mut self, n: u16) -> Result<()> {
self.output.write_u16::<LittleEndian>(n)
}
#[inline]
fn write_u32(&mut self, n: u32) -> io::Result<()> {
fn write_u32(&mut self, n: u32) -> Result<()> {
self.output.write_u32::<LittleEndian>(n)
}
#[inline]
fn write_u64(&mut self, n: u64) -> io::Result<()> {
fn write_u64(&mut self, n: u64) -> Result<()> {
self.output.write_u64::<LittleEndian>(n)
}
#[inline]
fn write_i8(&mut self, n: i8) -> io::Result<()> {
fn write_i8(&mut self, n: i8) -> Result<()> {
self.output.write_i8(n)
}
#[inline]
fn write_i16(&mut self, n: i16) -> io::Result<()> {
fn write_i16(&mut self, n: i16) -> Result<()> {
self.output.write_i16::<LittleEndian>(n)
}
#[inline]
fn write_i32(&mut self, n: i32) -> io::Result<()> {
fn write_i32(&mut self, n: i32) -> Result<()> {
self.output.write_i32::<LittleEndian>(n)
}
#[inline]
fn write_f32(&mut self, n: f32) -> io::Result<()> {
fn write_f32(&mut self, n: f32) -> Result<()> {
self.output.write_f32::<LittleEndian>(n)
}
#[inline]
fn write_f64(&mut self, n: f64) -> io::Result<()> {
fn write_f64(&mut self, n: f64) -> Result<()> {
self.output.write_f64::<LittleEndian>(n)
}
#[inline]
fn write_string(&mut self, s: &'_ SwfStr) -> io::Result<()> {
fn write_string(&mut self, s: &'_ SwfStr) -> Result<()> {
self.output.write_all(s.as_bytes())?;
self.write_u8(0)
}
}
impl<W: Write> Writer<W> {
pub fn new(output: W, version: u8) -> Writer<W> {
Writer { output, version }
pub fn new(output: W, version: u8) -> Self {
Self { output, version }
}
#[inline]
fn write_f64_me(&mut self, n: f64) -> io::Result<()> {
fn write_f64_me(&mut self, n: f64) -> Result<()> {
// Flash weirdly stores f64 as two LE 32-bit chunks.
// First word is the hi-word, second word is the lo-word.
let mut num = [0u8; 8];
(&mut num[..]).write_f64::<LittleEndian>(n)?;
num.swap(0, 4);
num.swap(1, 5);
num.swap(2, 6);
num.swap(3, 7);
self.output.write_all(&num)
let mut bytes = n.to_le_bytes();
bytes.swap(0, 4);
bytes.swap(1, 5);
bytes.swap(2, 6);
bytes.swap(3, 7);
self.output.write_all(&bytes)
}
#[allow(clippy::inconsistent_digit_grouping)]
pub fn write_action(&mut self, action: &Action) -> Result<()> {
match *action {
Action::Add => self.write_action_header(OpCode::Add, 0)?,

View File

@ -1,3 +1,5 @@
#![allow(clippy::unusual_byte_groupings)]
use crate::avm2::types::*;
use crate::error::{Error, Result};
use crate::extensions::ReadSwfExt;

View File

@ -1,3 +1,5 @@
#![allow(clippy::unusual_byte_groupings)]
use crate::avm2::opcode::OpCode;
use crate::avm2::types::*;
use crate::string::SwfStr;
@ -63,8 +65,8 @@ impl<W: Write> SwfWriteExt for Writer<W> {
}
impl<W: Write> Writer<W> {
pub fn new(output: W) -> Writer<W> {
Writer { output }
pub fn new(output: W) -> Self {
Self { output }
}
pub fn write(&mut self, abc_file: AbcFile) -> Result<()> {

View File

@ -1,8 +1,7 @@
use crate::byteorder::{LittleEndian, ReadBytesExt};
use crate::error::Result;
use crate::string::SwfStr;
use crate::{Fixed16, Fixed8};
use std::io::{self, Read};
use byteorder::{LittleEndian, ReadBytesExt};
use std::io;
pub trait ReadSwfExt<'a> {
fn as_mut_slice(&mut self) -> &mut &'a [u8];
@ -15,9 +14,9 @@ pub trait ReadSwfExt<'a> {
// TODO: Make this fallible?
fn seek(&mut self, data: &'a [u8], relative_offset: isize) {
let mut pos = self.pos(data);
pos = (pos as isize + relative_offset) as usize;
pos = pos.min(data.len());
let pos = self.pos(data);
let pos = (pos as isize + relative_offset) as usize;
let pos = pos.min(data.len());
*self.as_mut_slice() = &data[pos..];
}
@ -66,16 +65,6 @@ pub trait ReadSwfExt<'a> {
Ok(ReadBytesExt::read_f64::<LittleEndian>(self.as_mut_slice())?)
}
#[inline]
fn read_fixed8(&mut self) -> Result<Fixed8> {
Ok(Fixed8::from_bits(self.read_i16()?))
}
#[inline]
fn read_fixed16(&mut self) -> Result<Fixed16> {
Ok(Fixed16::from_bits(self.read_i32()?))
}
#[inline]
fn read_encoded_u32(&mut self) -> Result<u32> {
let mut val: u32 = 0;
@ -89,19 +78,6 @@ pub trait ReadSwfExt<'a> {
Ok(val)
}
#[inline]
fn read_f64_me(&mut self) -> Result<f64> {
// Flash weirdly stores (some?) f64 as two LE 32-bit chunks.
// First word is the hi-word, second word is the lo-word.
let mut num = [0u8; 8];
self.as_mut_slice().read_exact(&mut num)?;
num.swap(0, 4);
num.swap(1, 5);
num.swap(2, 6);
num.swap(3, 7);
Ok(ReadBytesExt::read_f64::<LittleEndian>(&mut &num[..])?)
}
fn read_slice(&mut self, len: usize) -> Result<&'a [u8]> {
let slice = self.as_mut_slice();
if slice.len() >= len {

View File

@ -6,14 +6,7 @@
//!
//! This library consists of a `read` module for decoding SWF data, and a `write` library for
//! writing SWF data.
#![allow(
renamed_and_removed_lints,
clippy::unknown_clippy_lints,
clippy::unusual_byte_groupings,
clippy::upper_case_acronyms
)]
extern crate byteorder;
#[cfg(feature = "flate2")]
extern crate flate2;
#[cfg(feature = "libflate")]
@ -36,7 +29,7 @@ pub mod write;
#[cfg(test)]
mod test_data;
/// Reexports
/// Re-exports
pub use read::{decompress_swf, parse_swf};
pub use string::*;
pub use tag_code::TagCode;

View File

@ -1,9 +1,4 @@
#![allow(
renamed_and_removed_lints,
clippy::unknown_clippy_lints,
clippy::inconsistent_digit_grouping,
clippy::unreadable_literal
)]
#![allow(clippy::unusual_byte_groupings)]
use crate::extensions::ReadSwfExt;
use crate::{
@ -16,7 +11,7 @@ use bitstream_io::BitRead;
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::{self, Read};
/// Parse a decompressed SWF and return a `Vec` of tags.
/// Parse a decompressed SWF.
///
/// # Example
/// ```
@ -220,16 +215,11 @@ fn make_lzma_reader<'a, R: Read + 'a>(
))
}
pub struct BitReader<'a, 'b> {
struct BitReader<'a, 'b> {
bits: bitstream_io::BitReader<&'b mut &'a [u8], bitstream_io::BigEndian>,
}
impl<'a, 'b> BitReader<'a, 'b> {
#[inline]
fn byte_align(&mut self) {
self.bits.byte_align();
}
#[inline]
fn read_bit(&mut self) -> io::Result<bool> {
self.bits.read_bit()
@ -271,7 +261,7 @@ impl<'a, 'b> BitReader<'a, 'b> {
#[inline]
fn reader(&mut self) -> &mut &'a [u8] {
self.byte_align();
self.bits.byte_align();
self.bits.reader().unwrap()
}
}
@ -295,8 +285,8 @@ impl<'a> ReadSwfExt<'a> for Reader<'a> {
impl<'a> Reader<'a> {
#[inline]
pub const fn new(input: &'a [u8], version: u8) -> Reader<'a> {
Reader { input, version }
pub const fn new(input: &'a [u8], version: u8) -> Self {
Self { input, version }
}
/// Returns the suggested string encoding for this SWF.
@ -333,6 +323,16 @@ impl<'a> Reader<'a> {
}
}
#[inline]
fn read_fixed8(&mut self) -> Result<Fixed8> {
Ok(Fixed8::from_bits(self.read_i16()?))
}
#[inline]
fn read_fixed16(&mut self) -> Result<Fixed16> {
Ok(Fixed16::from_bits(self.read_i32()?))
}
/// Reads the next SWF tag from the stream.
/// # Example
/// ```
@ -795,8 +795,7 @@ impl<'a> Reader<'a> {
// to the characters in a button in sequence.
// We don't know how many color transforms this tag will contain, so read it into a buffer.
let version = self.version;
let mut reader = Reader::new(self.read_slice(tag_length)?, version);
let mut reader = Reader::new(self.read_slice(tag_length)?, self.version);
let id = reader.read_character_id()?;
let mut color_transforms = Vec::new();
@ -1819,7 +1818,6 @@ impl<'a> Reader<'a> {
// but SWFs in the wild exist with them in DefineShape1 (generated by third party tools),
// and these run correctly in the Flash Player.
if (flags & 0b10000) != 0 {
bits.byte_align();
let mut reader = Reader::new(bits.reader(), context.swf_version);
let (new_styles, num_fill_bits, num_line_bits) =
reader.read_shape_styles(context.shape_version)?;

View File

@ -1,4 +1,4 @@
#![allow(clippy::inconsistent_digit_grouping, clippy::unreadable_literal)]
#![allow(clippy::unusual_byte_groupings)]
use crate::avm1::types::*;
use crate::avm2::read::tests::read_abc_from_file;

View File

@ -13,7 +13,7 @@ pub use fixed::*;
pub use matrix::Matrix;
/// A complete header and tags in the SWF file.
/// This is returned by the `swf::read_swf` convenience method.
/// This is returned by the `swf::parse_swf` convenience method.
#[derive(Debug)]
pub struct Swf<'a> {
pub header: HeaderExt,

View File

@ -1,9 +1,4 @@
#![allow(
clippy::cognitive_complexity,
clippy::float_cmp,
clippy::inconsistent_digit_grouping,
clippy::unreadable_literal
)]
#![allow(clippy::unusual_byte_groupings)]
use crate::{
error::{Error, Result},
@ -22,16 +17,16 @@ use std::io::{self, Write};
/// use swf::*;
///
/// let header = Header {
/// compression: Compression::Zlib,
/// version: 6,
/// stage_size: Rectangle { x_min: Twips::from_pixels(0.0), x_max: Twips::from_pixels(400.0), y_min: Twips::from_pixels(0.0), y_max: Twips::from_pixels(400.0) },
/// frame_rate: Fixed8::from_f32(60.0),
/// num_frames: 1,
/// };
/// compression: Compression::Zlib,
/// version: 6,
/// stage_size: Rectangle { x_min: Twips::from_pixels(0.0), x_max: Twips::from_pixels(400.0), y_min: Twips::from_pixels(0.0), y_max: Twips::from_pixels(400.0) },
/// frame_rate: Fixed8::from_f32(60.0),
/// num_frames: 1,
/// };
/// let tags = [
/// Tag::SetBackgroundColor(Color { r: 255, g: 0, b: 0, a: 255 }),
/// Tag::ShowFrame
/// ];
/// Tag::SetBackgroundColor(Color { r: 255, g: 0, b: 0, a: 255 }),
/// Tag::ShowFrame,
/// ];
/// let output = Vec::new();
/// swf::write_swf(&header, &tags, output).unwrap();
/// ```
@ -63,22 +58,16 @@ pub fn write_swf<W: Write>(header: &Header, tags: &[Tag<'_>], mut output: W) ->
// Compress SWF body.
match header.compression {
Compression::None => {
output.write_all(&swf_body)?;
}
Compression::None => output.write_all(&swf_body)?,
Compression::Zlib => write_zlib_swf(&mut output, &swf_body)?,
// LZMA header.
// SWF format has a mangled LZMA header, so we have to do some magic to convert the
// standard LZMA header to SWF format.
// https://adobe.ly/2s8oYzn
Compression::Lzma => {
write_lzma_swf(&mut output, &swf_body)?;
// 5 bytes of garbage data?
//output.write_all(&[0xFF, 0xB5, 0xE6, 0xF8, 0xCB])?;
}
};
}
Ok(())
}
@ -265,13 +254,8 @@ impl<W: Write> SwfWriteExt for Writer<W> {
}
impl<W: Write> Writer<W> {
fn new(output: W, version: u8) -> Writer<W> {
Writer { output, version }
}
#[allow(dead_code)]
fn into_inner(self) -> W {
self.output
fn new(output: W, version: u8) -> Self {
Self { output, version }
}
#[inline]
@ -281,10 +265,12 @@ impl<W: Write> Writer<W> {
}
}
#[inline]
fn write_fixed8(&mut self, n: Fixed8) -> io::Result<()> {
self.write_i16(n.get())
}
#[inline]
fn write_fixed16(&mut self, n: Fixed16) -> io::Result<()> {
self.write_i32(n.get())
}