Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
codecov:
require_ci_to_pass: false

ignore:
- benches/*
- examples/*
- tests/*

coverage:
status:
project: # Overall project status
default:
target: auto
if_not_found: success
only_pulls: false
patch: # Status for the patch in pull requests
default:
target: auto
if_not_found: success
only_pulls: true
changes: false # Whether to comment on the coverage changes in pull requests

comment:
layout: "header, diff, files, footer"
behavior: default
require_changes: false
162 changes: 6 additions & 156 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ on:
- '**.md'
- '**.txt'
workflow_dispatch:
schedule: [cron: "0 1 */7 * *"]
schedule:
- cron: "0 1 1 * *"

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -55,7 +56,7 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Apply clippy lints
run: cargo hack clippy --each-feature --exclude-no-default-features
run: cargo hack clippy --each-feature

# Run tests on some extra platforms
cross:
Expand Down Expand Up @@ -125,7 +126,7 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Run build
run: cargo hack build --feature-powerset --exclude-no-default-features
run: cargo hack build --feature-powerset

test:
name: test
Expand Down Expand Up @@ -154,156 +155,7 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Run test
run: cargo hack test --feature-powerset --exclude-no-default-features --exclude-features loom

sanitizer:
name: sanitizer
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-sanitizer-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-sanitizer-
- name: Install Rust
run: rustup update nightly && rustup default nightly
- name: Install rust-src
run: rustup component add rust-src
- name: ASAN / LSAN / MSAN / TSAN
run: bash ci/sanitizer.sh

miri-tb:
name: miri-tb-${{ matrix.target }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
- os: ubuntu-latest
target: i686-unknown-linux-gnu
- os: ubuntu-latest
target: powerpc64-unknown-linux-gnu
- os: ubuntu-latest
target: s390x-unknown-linux-gnu
- os: ubuntu-latest
target: riscv64gc-unknown-linux-gnu
- os: macos-latest
target: aarch64-apple-darwin
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-miri-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-miri-
- name: Miri
run: |
bash ci/miri_tb.sh "${{ matrix.target }}"

miri-sb:
name: miri-sb-${{ matrix.target }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
- os: ubuntu-latest
target: i686-unknown-linux-gnu
- os: ubuntu-latest
target: powerpc64-unknown-linux-gnu
- os: ubuntu-latest
target: s390x-unknown-linux-gnu
- os: ubuntu-latest
target: riscv64gc-unknown-linux-gnu
- os: macos-latest
target: aarch64-apple-darwin
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-miri-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-miri-
- name: Miri
run: |
bash ci/miri_sb.sh "${{ matrix.target }}"

loom:
name: loom
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Cache cargo build and registry
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-loom-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-loom-
- name: Install Rust
run: rustup update nightly --no-self-update && rustup default nightly
- name: Loom tests
run: cargo test --tests --features loom

# valgrind:
# name: valgrind
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v6
# - name: Cache cargo build and registry
# uses: actions/cache@v5
# with:
# path: |
# ~/.cargo/registry
# ~/.cargo/git
# target
# key: ubuntu-latest-valgrind-${{ hashFiles('**/Cargo.lock') }}
# restore-keys: |
# ubuntu-latest-valgrind-
# - name: Install Rust
# run: rustup update stable && rustup default stable
# - name: Install Valgrind
# run: |
# sudo apt-get update -y
# sudo apt-get install -y valgrind
# # Uncomment and customize when you have binaries to test:
# # - name: cargo build foo
# # run: cargo build --bin foo
# # working-directory: integration
# # - name: Run valgrind foo
# # run: valgrind --error-exitcode=1 --leak-check=full --show-leak-kinds=all ./target/debug/foo
# # working-directory: integration
run: cargo hack test --feature-powerset

coverage:
name: coverage
Expand All @@ -314,8 +166,6 @@ jobs:
- build
- cross
- test
- sanitizer
- loom
steps:
- uses: actions/checkout@v6
- name: Install Rust
Expand All @@ -337,7 +187,7 @@ jobs:
RUSTFLAGS: "--cfg tarpaulin"
run: cargo tarpaulin --all-features --run-types tests --run-types doctests --workspace --out xml
- name: Upload to codecov.io
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: ${{ github.repository }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/loc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
run: |
tokeit --lang rust
- name: Upload total loc to GitHub Gist
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GIST_PAT }}
script: |
Expand All @@ -51,7 +51,7 @@ jobs:
await github.rest.gists.update({
gist_id: gistId,
files: {
"template-rs": {
"mediatime": {
content: output
}
}
Expand Down
55 changes: 52 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,56 @@
# UNRELEASED
# Changelog

# 0.1.2 (January 6th, 2022)
All notable changes to this crate are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

FEATURES
## [Unreleased]

## [0.1.0] — April 17, 2026

Initial public release. First-cut API — expect minor refinements before 1.0.

### Added

- `Timebase` — rational `num/den` (`u32` numerator, `NonZeroU32` denominator).
Mirrors FFmpeg's `AVRational`. Supports value-based equality, ordering, and
hashing (reduced-form rational), so `1/2 == 2/4 == 3/6` and all three hash
identically.
- `Timestamp` — integer PTS (`i64`) tagged with a `Timebase`. Semantic
comparison across different timebases via 128-bit cross-multiplication —
no rounding, no division.
- `TimeRange` — half-open `[start, end)` interval sharing a `Timebase`, with
`start()` / `end()` as `Timestamp`, `duration()`, and clamped linear
`interpolate(t)` for midpoint / bias placement.
- Timebase utilities: `rescale_pts` (FFmpeg's `av_rescale_q`), `rescale`,
`frames_to_duration`, `duration_to_pts`, `num`/`den` accessors, `with_*`
consuming builders and `set_*` in-place setters.
- Timestamp utilities: `pts`/`timebase` accessors, `with_pts`/`set_pts`,
`rescale_to`, `saturating_sub_duration`, `duration_since`, `cmp_semantic`
(const-fn form of `Ord::cmp`).
- TimeRange utilities: `new`, `instant`, `start_pts`/`end_pts`/`timebase`
accessors, `with_*`/`set_*` setters for both endpoints, `is_instant`.
- `const fn` across the whole public surface — every constructor, accessor,
and setter can be evaluated in a `const` context.
- `#![no_std]` always, zero dependencies. No allocation anywhere — every
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changelog claims "#![no_std] always", but the crate uses #![cfg_attr(not(test), no_std)] (tests/doctests build with std). Consider rewording to something like "no_std by default" or "no_std in non-test builds" to match the actual crate configuration.

Suggested change
- `#![no_std]` always, zero dependencies. No allocation anywhere — every
- `#![no_std]` in non-test builds, zero dependencies. No allocation anywhere — every

Copilot uses AI. Check for mistakes.
public type is `Copy`.

### Behavior

- All comparisons between types are **semantic**, not structural: two
`Timestamp`s representing the same instant in different timebases are
`Eq`, `Ord::Equal`, and hash the same. Use this directly as a `HashMap` or
`BTreeMap` key without worrying about canonicalization.
- Cross-timebase arithmetic (rescaling, `duration_since`) uses 128-bit
intermediates throughout — exact for any `u32`×`u32` timebase combined
with any `i64` PTS in the real-video range.
- `rescale_pts` rounds toward zero, matching `av_rescale_q` with default
rounding. Saturating variants are not provided yet — overflow in
`duration_to_pts` is clamped to `i64::MAX`.

### Testing

- 100% line coverage on `src/lib.rs` under
`cargo tarpaulin --all-features --run-types tests --run-types doctests`.
- Criterion bench (`cargo bench --bench gcd`) for the internal GCD helpers
used by `Hash`; ships both Euclidean and binary variants for comparison.
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
[package]
name = "template-rs"
version = "0.0.0"
edition = "2021"
repository = "https://github.com/al8n/template-rs"
homepage = "https://github.com/al8n/template-rs"
documentation = "https://docs.rs/template-rs"
description = "A template for creating Rust open-source repo on GitHub"
name = "mediatime"
version = "0.1.0"
edition = "2024"
repository = "https://github.com/findit-ai/mediatime"
homepage = "https://github.com/findit-ai/mediatime"
documentation = "https://docs.rs/mediatime"
description = "Exact-integer rational time types for media pipelines — FFmpeg-style Timebase, Timestamp, and TimeRange. no_std, zero dependencies, const fn."
license = "MIT OR Apache-2.0"
rust-version = "1.73"
rust-version = "1.85"
keywords = ["media", "timebase", "timestamp", "pts", "ffmpeg"]
categories = ["multimedia", "multimedia::video", "date-and-time", "no-std", "no-std::no-alloc"]

[[bench]]
path = "benches/foo.rs"
name = "foo"
path = "benches/gcd.rs"
name = "gcd"
harness = false

[features]
default = ["std"]
alloc = []
std = []
default = []

[dependencies]

Expand Down
51 changes: 0 additions & 51 deletions README-zh_CN.md

This file was deleted.

Loading