chore(unsafe): the workspace adopts the drivers' unsafe discipline

`packaging/windows/drivers/*` has run `deny(unsafe_op_in_unsafe_fn)` +
`deny(clippy::undocumented_unsafe_blocks)` for a while, with `forbid(unsafe_code)`
on the modules that need no unsafe at all. The main workspace had no lint config
whatsoever, so nothing stopped a clean crate from quietly growing an `unsafe`, and
nothing distinguished the handful of genuinely-unsafe lines inside a 600-line
`unsafe fn` from the safe ones surrounding them.

Three things, all mechanical:

* `#![forbid(unsafe_code)]` on the eight crates that already contain zero unsafe
  (`pf-driver-proto`, `pf-host-config`, `pf-paths`, the three clean clients, both
  tools). These were clean by accident, not by contract; now they are clean by
  contract.

* `unsafe_op_in_unsafe_fn = "warn"` workspace-wide. `unsafe fn` states a contract
  the CALLER must uphold — it was never meant to switch off checking for the whole
  body. Measured fallout is 300 sites on Linux, and they are concentrated: six
  files carry all of them, while `punktfunk-core`, `pf-frame`, `pf-clipboard` and
  `pf-vdisplay` are already at zero. `warn` (not `deny`) so the build stays green
  while those six are worked down; it flips to `deny` once they are. This is also
  the Rust 2024 default, so it pays off the edition migration early.

* `proc::current_uid()` replaces eight `unsafe { libc::getuid() }` blocks. Each
  site had copied out the same SAFETY note verbatim, which is the tell: `getuid()`
  is parameterless, always succeeds and touches no memory, so there is no contract
  for a caller to uphold and no reason for the unsafe to be visible eight times.
  One `unsafe` behind a safe wrapper, none at the call sites.

Verified: `pf-vdisplay` builds clean on Linux (Nobara) at zero E0133; the
macOS-buildable crates build clean locally. No behaviour change.
This commit is contained in:
2026-07-28 21:31:41 +02:00
parent 37edb1cc1a
commit 5219107177
42 changed files with 128 additions and 19 deletions
+10
View File
@@ -56,6 +56,16 @@ license = "MIT OR Apache-2.0"
authors = ["unom"] authors = ["unom"]
repository = "https://git.unom.io/unom/punktfunk" repository = "https://git.unom.io/unom/punktfunk"
# The `unsafe` discipline the `packaging/windows/drivers/*` crates already run, extended to the
# workspace. `unsafe fn` marks a CONTRACT the caller must uphold; it is not a licence for the whole
# body to skip checking. Without this lint an `unsafe fn` body is unchecked end to end, so a 600-line
# function hides which handful of lines are actually the unsafe ones — exactly the reviewer-hostile
# shape we are working down. `warn` while the remaining sites are cleared crate by crate; flip to
# `deny` once they are, so it can never regress. (This is the Rust 2024 default; adopting it early
# also pays off the edition migration.)
[workspace.lints.rust]
unsafe_op_in_unsafe_fn = "warn"
[profile.release] [profile.release]
opt-level = 3 opt-level = 3
lto = "thin" lto = "thin"
+3
View File
@@ -64,3 +64,6 @@ libc = "0.2"
# host + Linux client use. audiopus_sys vendors libopus (pure C) and builds it static via cmake — # host + Linux client use. audiopus_sys vendors libopus (pure C) and builds it static via cmake —
# the cargo-ndk build sets LIBOPUS_STATIC=1/LIBOPUS_NO_PKG=1 so it links the bundled lib, not the host's. # the cargo-ndk build sets LIBOPUS_STATIC=1/LIBOPUS_NO_PKG=1 so it links the bundled lib, not the host's.
opus = "0.3" opus = "0.3"
[lints]
workspace = true
+3
View File
@@ -32,3 +32,6 @@ anyhow = "1"
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] }
relm4 = { version = "0.11", features = ["libadwaita"] } relm4 = { version = "0.11", features = ["libadwaita"] }
[lints]
workspace = true
+1
View File
@@ -3,6 +3,7 @@
//! Hosts, pairing/trust, settings, and the desktop library page; every stream (and the //! Hosts, pairing/trust, settings, and the desktop library page; every stream (and the
//! console game library) runs in the spawned `punktfunk-session` Vulkan binary — the //! console game library) runs in the spawned `punktfunk-session` Vulkan binary — the
//! shell never touches video (punktfunk-planning `linux-client-rearchitecture.md`). //! shell never touches video (punktfunk-planning `linux-client-rearchitecture.md`).
#![forbid(unsafe_code)]
// The UI-agnostic plumbing lives in `pf-client-core`, shared with the session binary. // The UI-agnostic plumbing lives in `pf-client-core`, shared with the session binary.
// Root re-exports keep every `crate::trust`-style path resolving unchanged. // Root re-exports keep every `crate::trust`-style path resolving unchanged.
+3
View File
@@ -22,3 +22,6 @@ mdns-sd = "0.20"
# encoder. libopus is already in the graph via `punktfunk-core`'s quic feature; this exposes the # encoder. libopus is already in the graph via `punktfunk-core`'s quic feature; this exposes the
# name directly. Cross-platform (cmake-vendored), so the probe builds + validates everywhere. # name directly. Cross-platform (cmake-vendored), so the probe builds + validates everywhere.
opus = "0.3" opus = "0.3"
[lints]
workspace = true
+1
View File
@@ -45,6 +45,7 @@
//! [--input-test | --mic-test [--mic-burst] | --touch-test | --rich-input-test] //! [--input-test | --mic-test [--mic-burst] | --touch-test | --rich-input-test]
//! [--pin HEX | --pair PIN] [--compositor NAME] [--gamepad NAME] | --discover [SECS]` //! [--pin HEX | --pair PIN] [--compositor NAME] [--gamepad NAME] | --discover [SECS]`
//! Env: `PUNKTFUNK_CLIENT_10BIT=1` / `PUNKTFUNK_CLIENT_444=1` advertise the 10-bit / 4:4:4 caps. //! Env: `PUNKTFUNK_CLIENT_10BIT=1` / `PUNKTFUNK_CLIENT_444=1` advertise the 10-bit / 4:4:4 caps.
#![forbid(unsafe_code)]
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use punktfunk_core::config::GamepadPref; use punktfunk_core::config::GamepadPref;
+3
View File
@@ -45,3 +45,6 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# the SDK); same pattern as clients/windows. # the SDK); same pattern as clients/windows.
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winresource = "0.1" winresource = "0.1"
[lints]
workspace = true
+1
View File
@@ -13,6 +13,7 @@
//! the first presented frame, `stats:` lines per 1 s window, one `{"error": …}` / //! the first presented frame, `stats:` lines per 1 s window, one `{"error": …}` /
//! `{"ended": …}` JSON line on the way out. Logs go to stderr. Exit codes: 0 clean end, //! `{"ended": …}` JSON line on the way out. Logs go to stderr. Exit codes: 0 clean end,
//! 2 connect failed, 3 trust rejected / pairing required, 4 presenter init failed. //! 2 connect failed, 3 trust rejected / pairing required, 4 presenter init failed.
#![forbid(unsafe_code)]
#[cfg(all(any(target_os = "linux", windows), feature = "ui"))] #[cfg(all(any(target_os = "linux", windows), feature = "ui"))]
mod console; mod console;
+3
View File
@@ -95,3 +95,6 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winresource = "0.1" winresource = "0.1"
windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" } windows-reactor-setup = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63c6bb7fc77a2affe57145be1d8c4f" }
[lints]
workspace = true
+3
View File
@@ -15,3 +15,6 @@ links = "vpl"
cmake = "0.1" cmake = "0.1"
# Same bindgen configuration as pyrowave-sys (runtime = dlopen libclang). # Same bindgen configuration as pyrowave-sys (runtime = dlopen libclang).
bindgen = { version = "0.72", features = ["runtime"], default-features = false } bindgen = { version = "0.72", features = ["runtime"], default-features = false }
[lints]
workspace = true
+3
View File
@@ -58,3 +58,6 @@ windows = { version = "0.62", features = [
"Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Input_KeyboardAndMouse",
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
] } ] }
[lints]
workspace = true
+3
View File
@@ -79,3 +79,6 @@ windows = { git = "https://github.com/microsoft/windows-rs", rev = "a4f7b2cb7c63
# still strictly per-session opt-in (Settings codec pick / PUNKTFUNK_PREFER_PYROWAVE=1). # still strictly per-session opt-in (Settings codec pick / PUNKTFUNK_PREFER_PYROWAVE=1).
default = ["pyrowave"] default = ["pyrowave"]
pyrowave = ["dep:pyrowave-sys", "dep:ash"] pyrowave = ["dep:pyrowave-sys", "dep:ash"]
[lints]
workspace = true
+3
View File
@@ -52,3 +52,6 @@ windows = { version = "0.62", features = [
"Win32_System_Ole", "Win32_System_Ole",
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
] } ] }
[lints]
workspace = true
+3
View File
@@ -33,3 +33,6 @@ sdl3 = { version = "0.18", features = ["hidapi", "ash"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
sdl3 = { version = "0.18", features = ["hidapi", "ash", "build-from-source"] } sdl3 = { version = "0.18", features = ["hidapi", "ash", "build-from-source"] }
[lints]
workspace = true
+3
View File
@@ -18,3 +18,6 @@ publish = false
[dependencies] [dependencies]
# `min_const_generics`: Pod/Zeroable for `[u8; N]` of any N (the gamepad SHM reserved tails are >32). # `min_const_generics`: Pod/Zeroable for `[u8; N]` of any N (the gamepad SHM reserved tails are >32).
bytemuck = { version = "1.19", features = ["derive", "min_const_generics"] } bytemuck = { version = "1.19", features = ["derive", "min_const_generics"] }
[lints]
workspace = true
+1 -1
View File
@@ -20,7 +20,7 @@
//! //!
//! The GUID and LUID are carried as plain integers; the host converts to `windows::core::GUID` / //! The GUID and LUID are carried as plain integers; the host converts to `windows::core::GUID` /
//! `windows::Win32::Foundation::LUID` and the driver to its own bindgen types via the same constants. //! `windows::Win32::Foundation::LUID` and the driver to its own bindgen types via the same constants.
#![forbid(unsafe_code)]
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
extern crate alloc; extern crate alloc;
+3
View File
@@ -92,3 +92,6 @@ pyrowave = ["dep:pyrowave-sys"]
# (design/native-qsv-encoder.md). ⚠ Like `nvenc`: hand builds need this feature or # (design/native-qsv-encoder.md). ⚠ Like `nvenc`: hand builds need this feature or
# Intel boxes fall through to the ffmpeg path / software. # Intel boxes fall through to the ffmpeg path / software.
qsv = ["dep:libvpl-sys"] qsv = ["dep:libvpl-sys"]
[lints]
workspace = true
+3
View File
@@ -20,3 +20,6 @@ ash = { version = "0.38", features = ["loaded"] }
# Same bindgen configuration as ffmpeg-sys-next (runtime = dlopen libclang). # Same bindgen configuration as ffmpeg-sys-next (runtime = dlopen libclang).
bindgen = { version = "0.72", features = ["runtime"], default-features = false } bindgen = { version = "0.72", features = ["runtime"], default-features = false }
pkg-config = "0.3" pkg-config = "0.3"
[lints]
workspace = true
+3
View File
@@ -35,3 +35,6 @@ windows = { version = "0.62", features = [
"Win32_System_LibraryLoader", "Win32_System_LibraryLoader",
"Win32_System_Threading", "Win32_System_Threading",
] } ] }
[lints]
workspace = true
+3
View File
@@ -26,3 +26,6 @@ windows = { version = "0.62", features = [
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"
[lints]
workspace = true
+3
View File
@@ -10,3 +10,6 @@ description = "Process-wide punktfunk host configuration (env-parsed HostConfig
publish = false publish = false
[dependencies] [dependencies]
[lints]
workspace = true
+1
View File
@@ -31,6 +31,7 @@
//! = off, anything else = on, so the old presence-style `=1` keeps working). The Linux `zerocopy` //! = off, anything else = on, so the old presence-style `=1` keeps working). The Linux `zerocopy`
//! module keeps its own *truthy* parser (`1|true|yes|on`) — the two are independent features that //! module keeps its own *truthy* parser (`1|true|yes|on`) — the two are independent features that
//! share a name; do NOT conflate them. //! share a name; do NOT conflate them.
#![forbid(unsafe_code)]
use std::sync::OnceLock; use std::sync::OnceLock;
+3
View File
@@ -75,3 +75,6 @@ windows = { version = "0.62", features = [
"Win32_UI_Input_Pointer", "Win32_UI_Input_Pointer",
"Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging",
] } ] }
[lints]
workspace = true
+3
View File
@@ -11,3 +11,6 @@ publish = false
[dependencies] [dependencies]
tracing = "0.1" tracing = "0.1"
[lints]
workspace = true
+1
View File
@@ -6,6 +6,7 @@
//! - [`config_dir`] resolves the per-host config directory (XDG / `%ProgramData%`, `PUNKTFUNK_CONFIG_DIR` override). //! - [`config_dir`] resolves the per-host config directory (XDG / `%ProgramData%`, `PUNKTFUNK_CONFIG_DIR` override).
//! - [`create_private_dir`] makes it owner-private (0700 / restrictive DACL). //! - [`create_private_dir`] makes it owner-private (0700 / restrictive DACL).
//! - [`write_secret_file`] writes an owner-only secret (0600 / SYSTEM+Admins DACL). //! - [`write_secret_file`] writes an owner-only secret (0600 / SYSTEM+Admins DACL).
#![forbid(unsafe_code)]
use std::path::PathBuf; use std::path::PathBuf;
+3
View File
@@ -53,3 +53,6 @@ windows-sys = { version = "0.61", features = [
# backend in pf-client-core; ON by default, matching pf-client-core's default. # backend in pf-client-core; ON by default, matching pf-client-core's default.
default = ["pyrowave"] default = ["pyrowave"]
pyrowave = ["pf-client-core/pyrowave"] pyrowave = ["pf-client-core/pyrowave"]
[lints]
workspace = true
+3
View File
@@ -65,3 +65,6 @@ windows = { version = "0.62", features = [
"Win32_System_IO", "Win32_System_IO",
"Win32_System_Threading", "Win32_System_Threading",
] } ] }
[lints]
workspace = true
@@ -604,8 +604,7 @@ pub fn managed_session_available() -> bool {
/// walking each candidate's ppid chain — so one client's nested gamescope never makes the next /// walking each candidate's ppid chain — so one client's nested gamescope never makes the next
/// client attach to it. /// client attach to it.
pub fn foreign_gamescope_running() -> bool { pub fn foreign_gamescope_running() -> bool {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory. let uid = crate::proc::current_uid();
let uid = unsafe { libc::getuid() };
let our_pid = std::process::id(); let our_pid = std::process::id();
let Ok(entries) = std::fs::read_dir("/proc") else { let Ok(entries) = std::fs::read_dir("/proc") else {
return false; return false;
@@ -708,8 +707,7 @@ pub fn launch_into_session(cmd: &str) -> Result<std::process::Child> {
/// when a process exposes it. Empty when no gamescope session is running / none exposes a `DISPLAY`. /// when a process exposes it. Empty when no gamescope session is running / none exposes a `DISPLAY`.
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub(crate) fn xwayland_cursor_targets() -> Vec<(String, Option<String>)> { pub(crate) fn xwayland_cursor_targets() -> Vec<(String, Option<String>)> {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory. let uid = crate::proc::current_uid();
let uid = unsafe { libc::getuid() };
let mut out: Vec<(String, Option<String>)> = Vec::new(); let mut out: Vec<(String, Option<String>)> = Vec::new();
let Ok(entries) = std::fs::read_dir("/proc") else { let Ok(entries) = std::fs::read_dir("/proc") else {
return out; return out;
@@ -765,8 +763,7 @@ pub(crate) fn xwayland_cursor_targets() -> Vec<(String, Option<String>)> {
/// gamescope socket; `DISPLAY` is the nested Xwayland; `XAUTHORITY` is its auth file (for X /// gamescope socket; `DISPLAY` is the nested Xwayland; `XAUTHORITY` is its auth file (for X
/// clients that aren't gamescope children). Any one can be individually absent. /// clients that aren't gamescope children). Any one can be individually absent.
fn discover_session_display_env() -> Option<(Option<String>, Option<String>, Option<String>)> { fn discover_session_display_env() -> Option<(Option<String>, Option<String>, Option<String>)> {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory. let uid = crate::proc::current_uid();
let uid = unsafe { libc::getuid() };
for e in std::fs::read_dir("/proc").ok()?.flatten() { for e in std::fs::read_dir("/proc").ok()?.flatten() {
let name = e.file_name(); let name = e.file_name();
let Some(pid_str) = name.to_str() else { let Some(pid_str) = name.to_str() else {
@@ -1441,8 +1438,7 @@ fn cgroup_under_user_manager(cgroup: &str) -> bool {
/// Our uid as a string — what `loginctl` wants for a user argument. /// Our uid as a string — what `loginctl` wants for a user argument.
fn uid_string() -> String { fn uid_string() -> String {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory. crate::proc::current_uid().to_string()
unsafe { libc::getuid() }.to_string()
} }
/// Is lingering on for this user (logind keeps the `--user` manager alive with no session)? /// Is lingering on for this user (logind keeps the `--user` manager alive with no session)?
@@ -106,8 +106,7 @@ pub(crate) fn wait_for_steam_game_exit(
/// `AppId=57` never matches appid 570) — specific to the game reaper, so Steam's own shader-precompile /// `AppId=57` never matches appid 570) — specific to the game reaper, so Steam's own shader-precompile
/// step (not reaper-wrapped) can't be mistaken for the game. /// step (not reaper-wrapped) can't be mistaken for the game.
fn steam_game_running(appid: u32) -> bool { fn steam_game_running(appid: u32) -> bool {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory. let uid = crate::proc::current_uid();
let uid = unsafe { libc::getuid() };
let appid_tok = format!("AppId={appid}"); let appid_tok = format!("AppId={appid}");
let Ok(entries) = std::fs::read_dir("/proc") else { let Ok(entries) = std::fs::read_dir("/proc") else {
return false; return false;
+15
View File
@@ -78,6 +78,21 @@ fn timed_out(cmd: &Command, budget: Duration) -> Error {
) )
} }
/// The calling process's real uid.
///
/// Every session/gamescope lookup that derives `/run/user/<uid>` (or filters `/proc` to "our"
/// processes) needs this, and each one used to open its own `unsafe` block carrying a verbatim
/// copy of the same SAFETY note. `getuid()` is parameterless, always succeeds, and touches no
/// memory, so there is no contract for a caller to uphold — which makes it exactly the shape that
/// belongs behind a safe wrapper instead of being restated at every call site. One `unsafe` here,
/// none at the callers.
#[cfg(target_os = "linux")]
pub(crate) fn current_uid() -> u32 {
// SAFETY: parameterless POSIX call that always succeeds and touches no memory — it just
// returns the calling process's real uid. Nothing is aliased, read, or freed.
unsafe { libc::getuid() }
}
// `unix` gate, not `test` alone: this module is compiled on every platform (lib.rs declares it // `unix` gate, not `test` alone: this module is compiled on every platform (lib.rs declares it
// unconditionally), but the cases below spawn `sleep`/`true`/`echo` as EXECUTABLES. On Windows // unconditionally), but the cases below spawn `sleep`/`true`/`echo` as EXECUTABLES. On Windows
// `echo` is a shell builtin and there is no `sleep.exe`, so an ungated module turns a green suite // `echo` is a shell builtin and there is no `sleep.exe`, so an ungated module turns a green suite
+3 -8
View File
@@ -280,9 +280,7 @@ pub(crate) fn runtime_dir() -> String {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn default_runtime_dir(env: &EnvProbe) -> String { fn default_runtime_dir(env: &EnvProbe) -> String {
env.xdg_runtime_dir.clone().unwrap_or_else(|| { env.xdg_runtime_dir.clone().unwrap_or_else(|| {
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no let uid = crate::proc::current_uid();
// memory — it just returns the calling process's real uid. Nothing is aliased or freed.
let uid = unsafe { libc::getuid() };
format!("/run/user/{uid}") format!("/run/user/{uid}")
}) })
} }
@@ -305,9 +303,7 @@ fn default_bus(env: &EnvProbe, runtime: &str) -> String {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn detect_active_session() -> ActiveSession { pub fn detect_active_session() -> ActiveSession {
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
// SAFETY: `getuid()` is a parameterless POSIX call that always succeeds and touches no memory — let uid = crate::proc::current_uid();
// it just returns the calling process's real uid. Nothing is aliased or freed.
let uid = unsafe { libc::getuid() };
// ONE sample of the session-scoped env, before any scanning — see [`EnvProbe`]. Everything // ONE sample of the session-scoped env, before any scanning — see [`EnvProbe`]. Everything
// below reads this snapshot, never the process env. // below reads this snapshot, never the process env.
let env = EnvProbe::sample(); let env = EnvProbe::sample();
@@ -712,8 +708,7 @@ mod tests {
impl FakeRuntime { impl FakeRuntime {
fn new(tag: &str, pids: &[u32]) -> FakeRuntime { fn new(tag: &str, pids: &[u32]) -> FakeRuntime {
// SAFETY: parameterless POSIX call, returns the calling process's uid; touches no memory. let uid = crate::proc::current_uid();
let uid = unsafe { libc::getuid() };
let dir = let dir =
std::env::temp_dir().join(format!("pf-swaysock-{tag}-{}", std::process::id())); std::env::temp_dir().join(format!("pf-swaysock-{tag}-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir); let _ = std::fs::remove_dir_all(&dir);
+3
View File
@@ -36,3 +36,6 @@ windows = { version = "0.62", features = [
"Win32_System_StationsAndDesktops", "Win32_System_StationsAndDesktops",
"Win32_System_Threading", "Win32_System_Threading",
] } ] }
[lints]
workspace = true
+3
View File
@@ -34,3 +34,6 @@ serde_json = "1"
# Linux-only like the code under test: the render-node scan is exercised against a fixture tree. # Linux-only like the code under test: the render-node scan is exercised against a fixture tree.
[target.'cfg(target_os = "linux")'.dev-dependencies] [target.'cfg(target_os = "linux")'.dev-dependencies]
tempfile = "3" tempfile = "3"
[lints]
workspace = true
+3
View File
@@ -107,3 +107,6 @@ harness = false
[build-dependencies] [build-dependencies]
cbindgen = "0.29" cbindgen = "0.29"
[lints]
workspace = true
+3
View File
@@ -310,3 +310,6 @@ pyrowave = ["pf-encode/pyrowave"]
# builds of this crate never execute the winresource block). # builds of this crate never execute the winresource block).
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winresource = "0.1" winresource = "0.1"
[lints]
workspace = true
+3
View File
@@ -58,3 +58,6 @@ libc = "0.2"
# Windows client's build.rs — cross-builds from Linux CI runners skip it. # Windows client's build.rs — cross-builds from Linux CI runners skip it.
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winresource = "0.1" winresource = "0.1"
[lints]
workspace = true
+3
View File
@@ -15,3 +15,6 @@ links = "pyrowave"
cmake = "0.1" cmake = "0.1"
# Same bindgen configuration as pf-ffvk (runtime = dlopen libclang). # Same bindgen configuration as pf-ffvk (runtime = dlopen libclang).
bindgen = { version = "0.72", features = ["runtime"], default-features = false } bindgen = { version = "0.72", features = ["runtime"], default-features = false }
[lints]
workspace = true
+3
View File
@@ -14,3 +14,6 @@ windows = { version = "0.62", features = [
"Win32_Graphics_Gdi", "Win32_Graphics_Gdi",
"Win32_Foundation", "Win32_Foundation",
] } ] }
[lints]
workspace = true
+3
View File
@@ -9,3 +9,6 @@ authors.workspace = true
repository.workspace = true repository.workspace = true
[dependencies] [dependencies]
[lints]
workspace = true
+1
View File
@@ -5,6 +5,7 @@
//! anything, so regressions are quantifiable. //! anything, so regressions are quantifiable.
//! //!
//! Status: scaffold. //! Status: scaffold.
#![forbid(unsafe_code)]
fn main() { fn main() {
println!( println!(
+3
View File
@@ -10,3 +10,6 @@ repository.workspace = true
[dependencies] [dependencies]
punktfunk-core = { path = "../../crates/punktfunk-core" } punktfunk-core = { path = "../../crates/punktfunk-core" }
[lints]
workspace = true
+1
View File
@@ -4,6 +4,7 @@
//! both FEC schemes, and prints how many frames survive. A pure-software stand-in for //! both FEC schemes, and prints how many frames survive. A pure-software stand-in for
//! `tc netem` that needs no network and runs anywhere `punktfunk_core` builds. The real punktfunk/1 //! `tc netem` that needs no network and runs anywhere `punktfunk_core` builds. The real punktfunk/1
//! harness adds `tc netem` jitter/reorder on the UDP path. //! harness adds `tc netem` jitter/reorder on the UDP path.
#![forbid(unsafe_code)]
use punktfunk_core::config::{Config, FecConfig, FecScheme, ProtocolPhase, Role}; use punktfunk_core::config::{Config, FecConfig, FecScheme, ProtocolPhase, Role};
use punktfunk_core::crypto::SessionKey; use punktfunk_core::crypto::SessionKey;