swf-parser 0.11.0

SWF parser
Documentation
pub mod complete;
mod stream_buffer;
pub mod streaming;
pub use swf_types;

pub use complete::tag::parse_tag;
pub use complete::{parse_swf, SwfParseError};

#[cfg(test)]
mod tests {
  use crate::parse_swf;
  use ::swf_types::Movie;
  use ::test_generator::test_resources;
  use nom::IResult as NomResult;
  use std::io::{Read, Write};
  use std::path::Path;

  #[test_resources("../tests/movies/*/")]
  fn test_parse_movie(path: &str) {
    use serde::Serialize;

    let path: &Path = Path::new(path);
    let _name = path
      .components()
      .last()
      .unwrap()
      .as_os_str()
      .to_str()
      .expect("Failed to retrieve sample name");
    let movie_path = path.join("main.swf");
    let mut movie_file = ::std::fs::File::open(movie_path).expect("Failed to open movie");
    let mut movie_bytes: Vec<u8> = Vec::new();
    movie_file.read_to_end(&mut movie_bytes).expect("Failed to read movie");

    let actual_movie = parse_swf(&movie_bytes).expect("Failed to parse movie");

    let actual_ast_path = path.join("local-ast.rs.json");
    let actual_ast_file = ::std::fs::File::create(actual_ast_path).expect("Failed to create actual AST file");
    let actual_ast_writer = ::std::io::BufWriter::new(actual_ast_file);

    let mut ser = serde_json_v8::Serializer::pretty(actual_ast_writer);
    actual_movie.serialize(&mut ser).expect("Failed to write actual AST");
    ser.into_inner().write_all(b"\n").unwrap();

    // assert_eq!(remaining_input, &[] as &[u8]);

    let ast_path = path.join("ast.json");
    let ast_file = ::std::fs::File::open(ast_path).expect("Failed to open AST");
    let ast_reader = ::std::io::BufReader::new(ast_file);
    let expected_movie = serde_json_v8::from_reader::<_, Movie>(ast_reader).expect("Failed to read AST");

    assert_eq!(actual_movie, expected_movie);
  }

  macro_rules! test_various_parser_impl {
    ($name:ident, $glob:expr, $parser:ident, $type:ty) => {
      #[test_resources($glob)]
      fn $name(path: &str) {
        let path: &Path = Path::new(path);
        let _name = path
          .components()
          .last()
          .unwrap()
          .as_os_str()
          .to_str()
          .expect("Failed to retrieve sample name");
        let input_path = path.join("input.bytes");
        let input_bytes: Vec<u8> = ::std::fs::read(input_path).expect("Failed to read input");

        let (remaining_bytes, actual_value): (&[u8], $type) = $parser(&input_bytes).expect("Failed to parse");

        let expected_path = path.join("value.json");
        let expected_file = ::std::fs::File::open(expected_path).expect("Failed to open expected value file");
        let expected_reader = ::std::io::BufReader::new(expected_file);
        let expected_value = serde_json_v8::from_reader::<_, $type>(expected_reader).expect("Failed to read AST");

        assert_eq!(actual_value, expected_value);
        assert_eq!(remaining_bytes, &[] as &[u8]);
      }
    };
  }

  // A variant of the previous macro that uses `.is` instead of `.eq` to check for bit-pattern equality
  macro_rules! test_various_parser_is_impl {
    ($name:ident, $glob:expr, $parser:ident, $type:ty) => {
      use crate::swf_types::float_is::Is;

      #[test_resources($glob)]
      fn $name(path: &str) {
        let path: &Path = Path::new(path);
        let _name = path
          .components()
          .last()
          .unwrap()
          .as_os_str()
          .to_str()
          .expect("Failed to retrieve sample name");
        let input_path = path.join("input.bytes");
        let input_bytes: Vec<u8> = ::std::fs::read(input_path).expect("Failed to read input");

        let (remaining_bytes, actual_value): (&[u8], $type) = $parser(&input_bytes).expect("Failed to parse");

        let expected_path = path.join("value.json");
        let expected_file = ::std::fs::File::open(expected_path).expect("Failed to open expected value file");
        let expected_reader = ::std::io::BufReader::new(expected_file);
        let expected_value = serde_json_v8::from_reader::<_, $type>(expected_reader).expect("Failed to read AST");

        assert!(actual_value.is(&expected_value));
        assert_eq!(remaining_bytes, &[] as &[u8]);
      }
    };
  }

  use crate::streaming::basic_data_types::parse_le_f16;
  test_various_parser_is_impl!(test_parse_le_f16, "../tests/various/float16-le/*/", parse_le_f16, f32);

  use crate::streaming::movie::parse_header;
  use swf_types::Header;

  fn parse_header34(input: &[u8]) -> NomResult<&[u8], Header> {
    parse_header(input, 34)
  }
  test_various_parser_impl!(test_parse_header, "../tests/various/header/*/", parse_header34, Header);

  use crate::streaming::basic_data_types::parse_matrix;
  use swf_types::Matrix;
  test_various_parser_impl!(test_parse_matrix, "../tests/various/matrix/*/", parse_matrix, Matrix);

  use crate::streaming::basic_data_types::parse_rect;
  use swf_types::Rect;
  test_various_parser_impl!(test_parse_rect, "../tests/various/rect/*/", parse_rect, Rect);

  use crate::streaming::movie::parse_swf_signature;
  use swf_types::SwfSignature;
  test_various_parser_impl!(
    test_parse_swf_signature,
    "../tests/various/swf-signature/*/",
    parse_swf_signature,
    SwfSignature
  );

  use crate::streaming::basic_data_types::parse_leb128_u32;
  test_various_parser_impl!(
    test_parse_leb128_u32,
    "../tests/various/uint32-leb128/*/",
    parse_leb128_u32,
    u32
  );
}