diff --git a/.github/codecov.yml b/.github/codecov.yml deleted file mode 100644 index 7d56722..0000000 --- a/.github/codecov.yml +++ /dev/null @@ -1,4 +0,0 @@ -coverage: - status: - patch: off - project: off diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1116676..b444304 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,9 +3,9 @@ updates: - package-ecosystem: "cargo" directory: "/" schedule: - interval: "daily" + interval: "monthly" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" + interval: "monthly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 3df7cc8..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: build - -on: - push: - branches: [master] - pull_request: - -jobs: - build: - name: Build & Test - strategy: - fail-fast: false - matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] - toolchain: [stable] - runs-on: ${{ matrix.platform }} - - steps: - - name: Checkout Sources - uses: actions/checkout@v4 - - - name: Install Rust Toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.toolchain }} - override: true - components: rustfmt, clippy - - - name: Check Code Format - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check - - - name: Code Lint - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all-features --all-targets -- -D warnings - - - name: Test - uses: actions-rs/cargo@v1 - with: - command: test - - build-no-std: - name: Build no_std - runs-on: ubuntu-latest - - steps: - - name: Checkout Sources - uses: actions/checkout@v4 - - - name: Install Rust Toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - target: thumbv6m-none-eabi - - - name: Build - uses: actions-rs/cargo@v1 - with: - command: build - args: --no-default-features --features alloc --target thumbv6m-none-eabi - -# coverage: -# name: Code Coverage -# runs-on: ubuntu-latest -# steps: -# - name: Checkout Sources -# uses: actions/checkout@v4 -# -# - name: Install Rust Toolchain -# uses: actions-rs/toolchain@v1 -# with: -# profile: minimal -# toolchain: stable -# override: true -# -# - name: Generate Code Coverage -# uses: actions-rs/tarpaulin@v0.1 -# -# - name: Upload Code Coverage -# uses: codecov/codecov-action@v1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d2ffbde --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,111 @@ +name: CI + +on: + push: + branches: + - main + - "v0.*.x" # v0.1.x or v0.20.x + - "v[1-9]*.x" # v1.x or v20.x + pull_request: + branches: + - main + - "v0.*.x" # v0.1.x or v0.20.x + - "v[1-9]*.x" # v1.x or v20.x + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + RUSTFLAGS: -D warnings + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + TAPLO_CLI_VERSION: 0.10.0 + +jobs: + check-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Cache taplo-cli + id: cache-taplo + uses: actions/cache@v5 + with: + path: ~/.cargo/bin/taplo + key: ${{ runner.os }}-taplo-${{ env.TAPLO_CLI_VERSION }} + + - name: Install taplo-cli if not cached + if: steps.cache-taplo.outputs.cache-hit != 'true' + shell: bash + run: cargo install taplo-cli@${TAPLO_CLI_VERSION} --locked + + - name: Run taplo fmt + run: taplo fmt --check + + - name: Run cargo fmt + run: cargo fmt --all -- --check + + check-clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: swatinem/rust-cache@v2 + + - name: Run cargo clippy + run: cargo clippy --workspace --all-targets --all-features -- -D warnings + + build-default-features: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: swatinem/rust-cache@v2 + - run: cargo build + + build-no-default-features: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: swatinem/rust-cache@v2 + - run: cargo build --no-default-features + + check-msrv: + runs-on: ubuntu-latest + env: + MSRV: 1.85.0 + steps: + - uses: actions/checkout@v6 + + - name: Setup MSRV + run: rustup toolchain install ${MSRV} --no-self-update + + - name: Check code + run: cargo +${MSRV} check --all-features + + check-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: swatinem/rust-cache@v2 + + - name: Generate docs + run: cargo doc --no-deps --lib --all-features + + run-tests: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v6 + + - name: Rust Cache + uses: swatinem/rust-cache@v2 + with: + shared-key: ${{ matrix.os }} + + - name: Run tests + run: cargo test --workspace --all-features + env: + RUST_BACKTRACE: 1 diff --git a/Cargo.toml b/Cargo.toml index 222146e..6e3de9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,29 @@ +[workspace] +members = [".", "cmd"] +resolver = "3" + +[workspace.package] +edition = "2024" +rust-version = "1.85.0" +license = "Apache-2.0" +homepage = "https://github.com/koushiro/flvparse" +repository = "https://github.com/koushiro/flvparse" + [package] name = "flvparse" version = "0.1.0" authors = ["koushiro "] -edition = "2018" +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +description = "A FLV format parsing library written in Rust" readme = "README.md" -license = "MIT/Apache-2.0" documentation = "https://docs.rs/flvparse" -repository = "https://github.com/koushiro/flvparse" -description = "A FLV format parsing library written in Rust" keywords = ["flv", "parse", "nom"] -exclude = [ - ".github", - "assets", - "cmd", - "tests" -] +exclude = ["assets", "cmd", "tests"] [lib] name = "flvparse" @@ -22,8 +31,7 @@ path = "src/lib.rs" [features] default = ["std"] -alloc = ["nom/alloc"] std = ["nom/std"] [dependencies] -nom = { version = "6.1", default-features = false } +nom = { version = "6.1", default-features = false, features = ["alloc"] } diff --git a/LICENSE-APACHE b/LICENSE similarity index 100% rename from LICENSE-APACHE rename to LICENSE diff --git a/LICENSE-MIT b/LICENSE-MIT deleted file mode 100644 index d2ceaa1..0000000 --- a/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Qinxuan Chen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index da1af36..064f65b 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,18 @@ # flvparse -[![ga-svg]][ga-url] -[![crates-svg]][crates-url] -[![docs-svg]][docs-url] -[![codecov-svg]][codecov-url] -[![deps-svg]][deps-url] - -[ga-svg]: https://github.com/koushiro/flvparse/workflows/build/badge.svg -[ga-url]: https://github.com/koushiro/flvparse/actions -[crates-svg]: https://img.shields.io/crates/v/flvparse -[crates-url]: https://crates.io/crates/flvparse -[docs-svg]: https://docs.rs/flvparse/badge.svg -[docs-url]: https://docs.rs/flvparse -[codecov-svg]: https://img.shields.io/codecov/c/github/koushiro/flvparse -[codecov-url]: https://codecov.io/gh/koushiro/flvparse -[deps-svg]: https://deps.rs/repo/github/koushiro/flvparse/status.svg -[deps-url]: https://deps.rs/repo/github/koushiro/flvparse - -A FLV format parsing library written in Rust with [nom](https://github.com/Geal/nom). +[![](https://github.com/koushiro/flvparse/actions/workflows/ci.yml/badge.svg)][actions] +[![](https://img.shields.io/docsrs/flvparse)][docs.rs] +[![](https://img.shields.io/crates/v/flvparse)][crates.io] +[![](https://img.shields.io/crates/l/flvparse)][crates.io] +[![](https://img.shields.io/crates/d/flvparse.svg)][crates.io] +[![](https://img.shields.io/badge/MSRV-1.85.0-green?logo=rust)][whatrustisit] + +[actions]: https://github.com/koushiro/flvparse/actions +[docs.rs]: https://docs.rs/flvparse +[crates.io]: https://crates.io/crates/flvparse +[whatrustisit]: https://www.whatrustisit.com + +A toy FLV format parsing library written in Rust with [nom](https://github.com/Geal/nom), mainly for learning `nom` (not production-ready). ## Usage @@ -40,54 +35,65 @@ fn main() { See [example](cmd/src/main.rs) for details. -``` +```bash cd cmd cargo run -- --input ../assets/test.flv - -+-----------------+-----------+ -| FLV File Header | | -+-----------------+-----------+ -| Signature (3B) | 46 4c 56 | -| Version (1B) | 1 | -| Flags (1B) | 0000 0101 | -| DataOffset (4B) | 9 | -+-----------------+-----------+ -+------------------+-------------------+------------------+------------------+ -| Total tag number | Script tag number | Video tag number | Audio tag number | -+------------------+-------------------+------------------+------------------+ -| 13041 | 1 | 4668 | 8372 | -+------------------+-------------------+------------------+------------------+ ``` +```text +FLV File Header +┌─────────────────────────────┐ +│ Field Value │ +╞═════════════════════════════╡ +│ Signature (3B) 46 4c 56 │ +│ Version (1B) 1 │ +│ Flags (1B) 0000 0101 │ +│ DataOffset (4B) 9 │ +└─────────────────────────────┘ +Tag Summary +┌────────────────────────────────────────────────────────────────────────────┐ +│ Total tag number Script tag number Video tag number Audio tag number │ +╞════════════════════════════════════════════════════════════════════════════╡ +│ 13041 1 4668 8372 │ +└────────────────────────────────────────────────────────────────────────────┘ ``` + +```bash cd cmd cargo run -- --input ../assets/test.flv -p -+-----------------+-----------+ -| FLV File Header | | -+-----------------+-----------+ -| Signature (3B) | 46 4c 56 | -| Version (1B) | 1 | -| Flags (1B) | 0000 0101 | -| DataOffset (4B) | 9 | -+-----------------+-----------+ -+---------------+--------------+---------------+----------------+---------------+ -| FLV File Body | | | | | -+---------------+--------------+---------------+----------------+---------------+ -| Index | TagType (1B) | DataSize (3B) | Timestamp (4B) | StreamID (3B) | -| 1 | Script | 1030 | 0 | 0 | -| 2 | Video | 48 | 0 | 0 | -| 3 | Audio | 7 | 0 | 0 | -| 4 | Video | 2831 | 0 | 0 | -| ... | -| 13039 | Audio | 15 | 194494 | 0 | -| 13040 | Audio | 15 | 194517 | 0 | -| 13041 | Video | 5 | 194375 | 0 | -+---------------+--------------+---------------+----------------+---------------+ -+------------------+-------------------+------------------+------------------+ -| Total tag number | Script tag number | Video tag number | Audio tag number | -+------------------+-------------------+------------------+------------------+ -| 13041 | 1 | 4668 | 8372 | -+------------------+-------------------+------------------+------------------+ +``` + +```text +FLV File Header +┌─────────────────────────────┐ +│ Field Value │ +╞═════════════════════════════╡ +│ Signature (3B) 46 4c 56 │ +│ Version (1B) 1 │ +│ Flags (1B) 0000 0101 │ +│ DataOffset (4B) 9 │ +└─────────────────────────────┘ +FLV File Body +┌───────────────────────────────────────────────────────────────────────┐ +│ Index TagType (1B) DataSize (3B) Timestamp (4B) StreamID (3B) │ +╞═══════════════════════════════════════════════════════════════════════╡ +│ 1 Script 1030 0 0 │ +│ 2 Video 48 0 0 │ +│ 3 Audio 7 0 0 │ +│ 4 Video 2831 0 0 │ +│ 5 Video 104 41 0 │ +| ... | +│ 13038 Audio 15 194471 0 │ +│ 13039 Audio 15 194494 0 │ +│ 13040 Audio 15 194517 0 │ +│ 13041 Video 5 194375 0 │ +└───────────────────────────────────────────────────────────────────────┘ +Tag Summary +┌────────────────────────────────────────────────────────────────────────────┐ +│ Total tag number Script tag number Video tag number Audio tag number │ +╞════════════════════════════════════════════════════════════════════════════╡ +│ 13041 1 4668 8372 │ +└────────────────────────────────────────────────────────────────────────────┘ ``` ### Related structure @@ -98,7 +104,7 @@ FlvFile └──FlvFileBody ├──u32 -- first previous tag size └──Vec<(FlvTag, u32)> - + FlvTag ├──FlvTagHeader └──FlvTagData @@ -109,15 +115,4 @@ FlvTagData ## License -Licensed under either of - -- [Apache License, Version 2.0](LICENSE-APACHE) -- [MIT License](LICENSE-MIT) - -at your option. - -## Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be -dual licensed as above, without any additional terms or conditions. +This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file for details. diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml index c87f7a4..faaff8e 100644 --- a/cmd/Cargo.toml +++ b/cmd/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "flvparser" -version = "0.1.0" +version = "0.0.0" authors = ["koushiro "] -edition = "2018" - -readme = "../README.md" -license = "MIT" description = "A FLV file parsing command line tool" +edition.workspace = true +rust-version.workspace = true +license.workspace = true +publish = false [dependencies] +anyhow = "1.0" flvparse = { path = "../" } -structopt = "0.3" -prettytable-rs = "0.8" +clap = { version = "4.5", features = ["derive"] } +comfy-table = "7.2" diff --git a/cmd/src/main.rs b/cmd/src/main.rs index a282045..440ffac 100644 --- a/cmd/src/main.rs +++ b/cmd/src/main.rs @@ -1,34 +1,35 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. +use std::{ + fs::File, + io::{BufReader, Read}, + path::PathBuf, +}; -use std::fs::File; -use std::io::{BufReader, Read}; -use std::path::PathBuf; +use anyhow::{Result, anyhow}; +use clap::Parser; +use comfy_table::{Attribute, Cell, ContentArrangement, Table, presets}; +use flvparse::{FlvFile, FlvTagType}; -use flvparse::{parse, FlvFile, FlvTagType}; -use prettytable::{cell, format, row, Attr, Cell, Row, Table}; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(author, about)] -struct Opt { +#[derive(Debug, Parser)] +#[command(author, about)] +struct Cli { /// The input FLV file to parse. - #[structopt(short, long, parse(from_os_str))] + #[arg(short, long)] input: PathBuf, /// Prints all tables about FLV File info. - #[structopt(short = "p", long)] + #[arg(short, long)] print: bool, } -fn main() -> Result<(), Box> { - let opt: Opt = Opt::from_args(); +fn main() -> Result<()> { + let cli: Cli = Cli::parse(); - let file = File::open(opt.input)?; + let file = File::open(cli.input)?; let mut reader = BufReader::new(file); - let mut contents = vec![]; - reader.read_to_end(&mut contents)?; + let mut input = vec![]; + reader.read_to_end(&mut input)?; - let flv = parse(&contents)?; - if opt.print { + let (_, flv) = FlvFile::parse(&input).map_err(|e| anyhow!("failed to parse: {e:?}"))?; + if cli.print { print_table(&flv, true); } else { print_table(&flv, false); @@ -37,50 +38,51 @@ fn main() -> Result<(), Box> { } fn print_table(flv_file: &FlvFile, print_body: bool) { + println!("FLV File Header"); let mut header = Table::new(); - header.set_titles(Row::new(vec![ - Cell::new("FLV File Header").with_style(Attr::Bold) - ])); - header.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE); - header.add_row(row!( - "Signature (3B)", - &format!( + header.load_preset(presets::UTF8_BORDERS_ONLY); + header.set_content_arrangement(ContentArrangement::Dynamic); + header.set_header(vec![ + Cell::new("Field").add_attribute(Attribute::Bold), + Cell::new("Value").add_attribute(Attribute::Bold), + ]); + header.add_row(vec![ + Cell::new("Signature (3B)"), + Cell::new(format!( "{:x} {:x} {:x}", flv_file.header.signature[0], flv_file.header.signature[1], flv_file.header.signature[2] - ) - )); - header.add_row(row!( - "Version (1B)", - &format!("{}", flv_file.header.version) - )); - header.add_row(row!( - "Flags (1B)", - &format!( + )), + ]); + header.add_row(vec![ + Cell::new("Version (1B)"), + Cell::new(format!("{}", flv_file.header.version)), + ]); + header.add_row(vec![ + Cell::new("Flags (1B)"), + Cell::new(format!( "{:04b} {:04b}", flv_file.header.flags & 0xf0, flv_file.header.flags & 0x0f - ) - )); - header.add_row(row!( - "DataOffset (4B)", - &format!("{}", flv_file.header.data_offset) - )); - header.printstd(); + )), + ]); + header.add_row(vec![ + Cell::new("DataOffset (4B)"), + Cell::new(format!("{}", flv_file.header.data_offset)), + ]); + println!("{header}"); let mut body = Table::new(); - body.set_titles(Row::new(vec![ - Cell::new("FLV File Body").with_style(Attr::Bold) - ])); - body.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE); - body.add_row(row!( - "Index", - "TagType (1B)", - "DataSize (3B)", - "Timestamp (4B)", - "StreamID (3B)" - )); + body.load_preset(presets::UTF8_BORDERS_ONLY); + body.set_content_arrangement(ContentArrangement::Dynamic); + body.set_header(vec![ + Cell::new("Index").add_attribute(Attribute::Bold), + Cell::new("TagType (1B)").add_attribute(Attribute::Bold), + Cell::new("DataSize (3B)").add_attribute(Attribute::Bold), + Cell::new("Timestamp (4B)").add_attribute(Attribute::Bold), + Cell::new("StreamID (3B)").add_attribute(Attribute::Bold), + ]); let mut index = 0usize; let mut script_tag_num = 0usize; let mut video_tag_num = 0usize; @@ -92,31 +94,34 @@ fn print_table(flv_file: &FlvFile, print_body: bool) { FlvTagType::Video => video_tag_num += 1, FlvTagType::Audio => audio_tag_num += 1, } - body.add_row(Row::new(vec![ - Cell::new(&format!("{}", index)), - Cell::new(&format!("{:?}", tag.header.tag_type)), - Cell::new(&format!("{}", tag.header.data_size)), - Cell::new(&format!("{}", tag.header.timestamp)), - Cell::new(&format!("{}", tag.header.stream_id)), - ])); + body.add_row(vec![ + Cell::new(format!("{}", index)), + Cell::new(format!("{:?}", tag.header.tag_type)), + Cell::new(format!("{}", tag.header.data_size)), + Cell::new(format!("{}", tag.header.timestamp)), + Cell::new(format!("{}", tag.header.stream_id)), + ]); } if print_body { - body.printstd(); + println!("FLV File Body"); + println!("{body}"); } + println!("Tag Summary"); let mut result = Table::new(); - result.set_titles(Row::new(vec![ - Cell::new("Total tag number").with_style(Attr::Bold), - Cell::new("Script tag number").with_style(Attr::Bold), - Cell::new("Video tag number").with_style(Attr::Bold), - Cell::new("Audio tag number").with_style(Attr::Bold), - ])); - result.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE); - result.add_row(row!( - &format!("{}", index), - &format!("{}", script_tag_num), - &format!("{}", video_tag_num), - &format!("{}", audio_tag_num), - )); - result.printstd(); + result.load_preset(presets::UTF8_BORDERS_ONLY); + result.set_content_arrangement(ContentArrangement::Dynamic); + result.set_header(vec![ + Cell::new("Total tag number").add_attribute(Attribute::Bold), + Cell::new("Script tag number").add_attribute(Attribute::Bold), + Cell::new("Video tag number").add_attribute(Attribute::Bold), + Cell::new("Audio tag number").add_attribute(Attribute::Bold), + ]); + result.add_row(vec![ + Cell::new(format!("{}", index)), + Cell::new(format!("{}", script_tag_num)), + Cell::new(format!("{}", video_tag_num)), + Cell::new(format!("{}", audio_tag_num)), + ]); + println!("{result}"); } diff --git a/justfile b/justfile new file mode 100644 index 0000000..7093d88 --- /dev/null +++ b/justfile @@ -0,0 +1,38 @@ +# Show all commands +[default] +help: + @just --list --list-heading $'Available commands:\n' + +# Cleanup compilation outputs +clean: + @cargo clean + +# Check the code format +fmt-check: + @taplo fmt --check + @cargo fmt --all -- --check + +# Format the code +fmt: + @taplo fmt + @cargo +nightly fmt --all + +# Run rust clippy +clippy *args='': + @cargo clippy --workspace --all-targets --all-features {{ args }} -- -D warnings + +# Check code +check *args='': + @cargo check --workspace --all-targets --all-features {{ args }} + +# Build workspace +build *args='': + @cargo build --workspace --all-targets --all-features {{ args }} + +# Run all tests +test *args='': + @cargo test --workspace --all-features {{ args }} + +# Generate docs +gen-docs *args='': + @cargo doc --no-deps --workspace --lib --all-features {{ args }} diff --git a/release.toml b/release.toml new file mode 100644 index 0000000..555003f --- /dev/null +++ b/release.toml @@ -0,0 +1,8 @@ +# NOTE: Before releasing, confirm config like below: +# `cargo release config --manifest-path Cargo.toml -c release.toml` +push-remote = "upstream" +allow-branch = ["main"] +consolidate-commits = false +pre-release-commit-message = "chore: release {{crate_name}}-v{{version}}" +tag-message = "chore: release {{crate_name}}-v{{version}}" +tag-name = "{{prefix}}v{{version}}" diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..92a57c5 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "stable" +components = ["clippy", "rustfmt"] +profile = "minimal" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..cb401cc --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,18 @@ +# Basic +edition = "2024" +max_width = 100 +use_small_heuristics = "Max" +# Imports +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Format comments +comment_width = 100 +wrap_comments = true +# Misc +chain_width = 80 +match_block_trailing_comma = true +merge_derives = false +use_field_init_shorthand = true diff --git a/src/lib.rs b/src/lib.rs index 46e6f66..ffb6a44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - //! # flvparse //! //! A FLV format parsing library written in Rust with nom. @@ -7,7 +5,7 @@ #![deny(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(all(not(feature = "std"), feature = "alloc"))] +#[cfg(not(feature = "std"))] extern crate alloc; #[macro_use] @@ -15,9 +13,9 @@ extern crate nom; mod parse; -pub use self::parse::*; - pub use nom::{ - error::{Error, ErrorKind}, Err as NomErr, IResult, Needed, + error::{Error, ErrorKind}, }; + +pub use self::parse::*; diff --git a/src/parse/audio.rs b/src/parse/audio.rs index 250268b..968473b 100644 --- a/src/parse/audio.rs +++ b/src/parse/audio.rs @@ -1,6 +1,4 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - -use nom::{number::streaming::be_u8, Err as NomErr, IResult, Needed}; +use nom::{Err as NomErr, IResult, Needed, number::streaming::be_u8}; /// The tag data part of `audio` FLV tag, including `tag data header` and `tag data body`. #[derive(Clone, Debug, PartialEq)] @@ -151,15 +149,7 @@ impl AudioTagHeader { )) ); - Ok(( - remain, - AudioTagHeader { - sound_format, - sound_rate, - sound_size, - sound_type, - }, - )) + Ok((remain, AudioTagHeader { sound_format, sound_rate, sound_size, sound_type })) } } @@ -177,12 +167,7 @@ impl<'a> AudioTagBody<'a> { return Err(NomErr::Incomplete(Needed::new(size))); } - Ok(( - &input[size..], - AudioTagBody { - data: &input[0..size], - }, - )) + Ok((&input[size..], AudioTagBody { data: &input[0..size] })) } } @@ -205,7 +190,7 @@ pub enum AACPacketType { } /// Parse AAC audio packet. -pub fn aac_audio_packet(input: &[u8], size: usize) -> IResult<&[u8], AACAudioPacket> { +pub fn aac_audio_packet(input: &[u8], size: usize) -> IResult<&[u8], AACAudioPacket<'_>> { if input.len() < size { return Err(NomErr::Incomplete(Needed::new(size))); } @@ -222,11 +207,5 @@ pub fn aac_audio_packet(input: &[u8], size: usize) -> IResult<&[u8], AACAudioPac ) ); - Ok(( - &input[size..], - AACAudioPacket { - packet_type, - aac_data: &input[1..size], - }, - )) + Ok((&input[size..], AACAudioPacket { packet_type, aac_data: &input[1..size] })) } diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 3a65237..66e3638 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,5 +1,3 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - // Parse the structure of the contents of FLV files. // [The FLV File Format Spec](https://www.adobe.com/content/dam/acom/en/devnet/flv/video_file_format_spec_v10_1.pdf) @@ -7,12 +5,12 @@ mod audio; mod script; mod video; -#[cfg(all(not(feature = "std"), feature = "alloc"))] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; use nom::{ - number::streaming::{be_u24, be_u32, be_u8}, IResult, + number::streaming::{be_u8, be_u24, be_u32}, }; pub use self::{audio::*, script::*, video::*}; @@ -156,7 +154,8 @@ pub struct FlvTagHeader { pub tag_type: FlvTagType, /// The size of the tag's data part, 3 bytes. pub data_size: u32, - /// The timestamp (in milliseconds) of the tag, Timestamp (3 bytes) + TimestampExtended (1 byte). + /// The timestamp (in milliseconds) of the tag, + /// Timestamp (3 bytes) + TimestampExtended (1byte). pub timestamp: u32, /// The id of stream is always 0, 3 bytes. pub stream_id: u32, diff --git a/src/parse/script.rs b/src/parse/script.rs index 664319b..e5cac0a 100644 --- a/src/parse/script.rs +++ b/src/parse/script.rs @@ -1,12 +1,10 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - -#[cfg(all(not(feature = "std"), feature = "alloc"))] +#[cfg(not(feature = "std"))] use alloc::vec::Vec; use core::str; use nom::{ - number::streaming::{be_f64, be_i16, be_u16, be_u32, be_u8}, IResult, + number::streaming::{be_f64, be_i16, be_u8, be_u16, be_u32}, }; const SCRIPT_DATA_VALUE_STRING_TYPE: [u8; 1] = [0x02]; diff --git a/src/parse/video.rs b/src/parse/video.rs index d09c7a4..86362a6 100644 --- a/src/parse/video.rs +++ b/src/parse/video.rs @@ -1,8 +1,6 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - use nom::{ - number::streaming::{be_i24, be_u8}, Err as NomErr, IResult, Needed, + number::streaming::{be_i24, be_u8}, }; /// The tag data part of `video` FLV tag, including `tag data header` and `tag data body`. @@ -107,13 +105,7 @@ impl VideoTagHeader { )) ); - Ok(( - remain, - VideoTagHeader { - frame_type, - codec_id, - }, - )) + Ok((remain, VideoTagHeader { frame_type, codec_id })) } } @@ -131,12 +123,7 @@ impl<'a> VideoTagBody<'a> { return Err(NomErr::Incomplete(Needed::new(size))); } - Ok(( - &input[size..], - VideoTagBody { - data: &input[0..size], - }, - )) + Ok((&input[size..], VideoTagBody { data: &input[0..size] })) } } @@ -170,7 +157,7 @@ pub enum AvcPacketType { } /// Parse AVC video packet. -pub fn avc_video_packet(input: &[u8], size: usize) -> IResult<&[u8], AvcVideoPacket> { +pub fn avc_video_packet(input: &[u8], size: usize) -> IResult<&[u8], AvcVideoPacket<'_>> { if input.len() < size { return Err(NomErr::Incomplete(Needed::new(size))); } @@ -194,10 +181,6 @@ pub fn avc_video_packet(input: &[u8], size: usize) -> IResult<&[u8], AvcVideoPac Ok(( &input[size..], - AvcVideoPacket { - packet_type, - composition_time, - avc_data: &input[4..size], - }, + AvcVideoPacket { packet_type, composition_time, avc_data: &input[4..size] }, )) } diff --git a/tests/parse.rs b/tests/parse.rs index 716d2e1..9d012fc 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -1,5 +1,3 @@ -// Copyright 2019-2021 koushiro. Licensed under MIT. - #![allow(clippy::unreadable_literal)] use flvparse::*; @@ -38,10 +36,7 @@ fn test_parse_flv_file() { #[test] fn test_flv_file_header() { let end = FLV_FILE_HEADER_LENGTH; - println!( - "flv file header = {:?}", - FlvFileHeader::parse(&TEST_FLV_FILE[..end]).unwrap().1 - ); + println!("flv file header = {:?}", FlvFileHeader::parse(&TEST_FLV_FILE[..end]).unwrap().1); assert_eq!( FlvFileHeader::parse(&TEST_FLV_FILE[..FLV_FILE_HEADER_LENGTH]), Ok(( @@ -80,10 +75,7 @@ fn test_flv_tag() { + 48 + PREVIOUS_TAG_SIZE_LENGTH; let end: usize = start + FLV_TAG_HEADER_LENGTH + 7; - println!( - "flv tag = {:?}", - FlvTag::parse(&TEST_FLV_FILE[start..end]).unwrap().1 - ); + println!("flv tag = {:?}", FlvTag::parse(&TEST_FLV_FILE[start..end]).unwrap().1); assert_eq!( FlvTag::parse(&TEST_FLV_FILE[start..end]), Ok(( @@ -104,9 +96,7 @@ fn test_flv_tag() { sound_type: SoundType::Stereo, // 0b01 = 1 }, // 0x0012 1056 e500, 6 bytes - body: AudioTagBody { - data: &b"\x00\x12\x10\x56\xe5\x00"[..], - }, + body: AudioTagBody { data: &b"\x00\x12\x10\x56\xe5\x00"[..] }, }) } )) @@ -121,10 +111,7 @@ fn test_flv_tag_header() { // script tag (the first tag in TEST_FLV_FILE) let mut start = FLV_FILE_HEADER_LENGTH + PREVIOUS_TAG_SIZE_LENGTH; let mut end = start + FLV_TAG_HEADER_LENGTH; - println!( - "flv tag header = {:?}", - FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1 - ); + println!("flv tag header = {:?}", FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1); assert_eq!( FlvTagHeader::parse(&TEST_FLV_FILE[start..end]), Ok(( @@ -141,10 +128,7 @@ fn test_flv_tag_header() { // video tag (the second tag in TEST_FLV_FILE) start = end + 1030 + PREVIOUS_TAG_SIZE_LENGTH; end = start + FLV_TAG_HEADER_LENGTH; - println!( - "flv tag header = {:?}", - FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1 - ); + println!("flv tag header = {:?}", FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1); assert_eq!( FlvTagHeader::parse(&TEST_FLV_FILE[start..end]), Ok(( @@ -161,10 +145,7 @@ fn test_flv_tag_header() { // audio tag (the third tag in TEST_FLV_FILE) start = end + 48 + PREVIOUS_TAG_SIZE_LENGTH; end = start + FLV_TAG_HEADER_LENGTH; - println!( - "flv tag header = {:?}", - FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1 - ); + println!("flv tag header = {:?}", FlvTagHeader::parse(&TEST_FLV_FILE[start..end]).unwrap().1); assert_eq!( FlvTagHeader::parse(&TEST_FLV_FILE[start..end]), Ok(( @@ -194,9 +175,7 @@ fn test_flv_tag_data() { let end = start + 7; println!( "flv tag data = {:?}", - FlvTagData::parse(&TEST_FLV_FILE[start..end], FlvTagType::Audio, 7) - .unwrap() - .1 + FlvTagData::parse(&TEST_FLV_FILE[start..end], FlvTagType::Audio, 7).unwrap().1 ); assert_eq!( FlvTagData::parse(&TEST_FLV_FILE[start..end], FlvTagType::Audio, 7), @@ -211,9 +190,7 @@ fn test_flv_tag_data() { sound_type: SoundType::Stereo, // 0b01 = 1 }, // 0x0012 1056 e500, 6 bytes - body: AudioTagBody { - data: &b"\x00\x12\x10\x56\xe5\x00"[..], - }, + body: AudioTagBody { data: &b"\x00\x12\x10\x56\xe5\x00"[..] }, }) )) ); @@ -232,10 +209,7 @@ fn test_audio_tag() { + PREVIOUS_TAG_SIZE_LENGTH + FLV_TAG_HEADER_LENGTH; let end = start + 7; - println!( - "audio tag = {:?}", - AudioTag::parse(&TEST_FLV_FILE[start..end], 7).unwrap().1 - ); + println!("audio tag = {:?}", AudioTag::parse(&TEST_FLV_FILE[start..end], 7).unwrap().1); assert_eq!( AudioTag::parse(&TEST_FLV_FILE[start..end], 7), Ok(( @@ -249,9 +223,7 @@ fn test_audio_tag() { sound_type: SoundType::Stereo, // 0b01 = 1 }, // 0x0012 1056 e500, 6 bytes - body: AudioTagBody { - data: &b"\x00\x12\x10\x56\xe5\x00"[..], - }, + body: AudioTagBody { data: &b"\x00\x12\x10\x56\xe5\x00"[..] }, } )) ); @@ -316,9 +288,7 @@ fn test_audio_tag_body() { Ok(( &b""[..], // 0x0012 1056 e500, 6 bytes - AudioTagBody { - data: &b"\x00\x12\x10\x56\xe5\x00"[..], - } + AudioTagBody { data: &b"\x00\x12\x10\x56\xe5\x00"[..] } )) ); } @@ -333,10 +303,7 @@ fn test_video_tag() { + PREVIOUS_TAG_SIZE_LENGTH + FLV_TAG_HEADER_LENGTH; let end = start + 48; - println!( - "video tag = {:?}", - VideoTag::parse(&TEST_FLV_FILE[start..end], 48).unwrap().1 - ); + println!("video tag = {:?}", VideoTag::parse(&TEST_FLV_FILE[start..end], 48).unwrap().1); assert_eq!( VideoTag::parse(&TEST_FLV_FILE[start..end], 48), Ok(( @@ -428,10 +395,7 @@ fn test_video_tag_body() { macro_rules! obj_prop { ($name:expr, $value:expr) => { - ScriptDataObjectProperty { - name: $name, - value: $value, - } + ScriptDataObjectProperty { name: $name, value: $value } }; } @@ -440,10 +404,7 @@ fn test_script_tag() { // script tag (the first tag in TEST_FLV_FILE) let start = FLV_FILE_HEADER_LENGTH + PREVIOUS_TAG_SIZE_LENGTH + FLV_TAG_HEADER_LENGTH; let end = start + 1030; - println!( - "script tag = {:?}", - ScriptTag::parse(&TEST_FLV_FILE[start..end], 1030) - ); + println!("script tag = {:?}", ScriptTag::parse(&TEST_FLV_FILE[start..end], 1030)); assert_eq!( ScriptTag::parse(&TEST_FLV_FILE[start..end], 1030), Ok(( @@ -549,19 +510,10 @@ fn test_script_tag() { #[test] fn test_script_data_date() { let input = &b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08Remain"[..]; - println!( - "script data date = {:?}", - ScriptDataValue::parse_date(input).unwrap().1 - ); + println!("script data date = {:?}", ScriptDataValue::parse_date(input).unwrap().1); assert_eq!( ScriptDataValue::parse_date(input), - Ok(( - &b"Remain"[..], - ScriptDataDate { - date_time: 0.0, - local_date_time_offset: 8, - } - )) + Ok((&b"Remain"[..], ScriptDataDate { date_time: 0.0, local_date_time_offset: 8 })) ); } @@ -572,8 +524,5 @@ fn test_script_data_long_string() { "script data long string = {:?}", ScriptDataValue::parse_long_string(input).unwrap().1 ); - assert_eq!( - ScriptDataValue::parse_long_string(input), - Ok((&b"Remain"[..], "Long String")) - ); + assert_eq!(ScriptDataValue::parse_long_string(input), Ok((&b"Remain"[..], "Long String"))); }