diff --git a/.github/workflows/lambda-repo-security.yml b/.github/workflows/lambda-repo-security.yml index e60250d1..1f9df3bc 100644 --- a/.github/workflows/lambda-repo-security.yml +++ b/.github/workflows/lambda-repo-security.yml @@ -4,19 +4,19 @@ # documentation. # rust-clippy is a tool that runs a bunch of lints to catch common # mistakes in your Rust code and help improve your Rust code. -# More details at https://github.com/rust-lang/rust-clippy +# More details at https://github.com/rust-lang/rust-clippy # and https://rust-lang.github.io/rust-clippy/ name: rust fmt + clippy analyze on: push: - branches: [ "main" ] + branches: ["main"] pull_request: # The branches below must be a subset of the branches above - branches: [ "main" ] + branches: ["main"] schedule: - - cron: '41 10 * * 5' + - cron: "41 10 * * 5" jobs: rust-clippy-analyze: @@ -25,7 +25,7 @@ jobs: permissions: contents: read security-events: write - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status steps: - name: Checkout code uses: actions/checkout@v4 @@ -42,7 +42,9 @@ jobs: run: cargo install clippy-sarif sarif-fmt - name: Check formatting - run: cargo fmt --all --check + run: | + rustup component add rustfmt --toolchain nightly-2025-09-26 + cargo +nightly-2025-09-26 fmt --all --check - name: Run rust-clippy run: | diff --git a/crates/lambda-rs-args/src/lib.rs b/crates/lambda-rs-args/src/lib.rs index fcd6de44..31cf4e13 100644 --- a/crates/lambda-rs-args/src/lib.rs +++ b/crates/lambda-rs-args/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] //! # Lambda Args //! Lambda Args is a simple argument parser for Rust. It is designed to be //! simple to use and primarily for use in lambda command line applications. @@ -7,6 +8,18 @@ use std::{ fmt, }; +/// Configurable command‑line argument parser for Lambda tools and examples. +/// +/// Features: +/// - Long/short flags with aliases (e.g., "-o", "--output") +/// - Positional arguments in declaration order +/// - Type‑aware parsing (`string`, `integer`, `float`, `boolean`, `count`, lists) +/// - Optional environment variable and config‑file integration +/// - Mutually exclusive groups and simple requires relationships +/// - Subcommands with their own parsers +/// +/// Use the builder to register arguments and then call `parse` with a slice of +/// tokens (usually `std::env::args().collect()`). pub struct ArgumentParser { name: String, description: String, @@ -24,20 +37,32 @@ pub struct ArgumentParser { } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] +/// Supported value types for an argument definition. pub enum ArgumentType { + /// `true`/`false` (or implied by presence when compiled as a flag). Boolean, + /// 64‑bit signed integer. Integer, + /// 32‑bit floating point number. Float, + /// 64‑bit floating point number. Double, + /// UTF‑8 string. String, + /// Count of flag occurrences (e.g., `-vvv` => 3). Count, + /// One or more strings (space‑separated tokens). StringList, + /// One or more integers. IntegerList, + /// One or more 32‑bit floats. FloatList, + /// One or more 64‑bit floats. DoubleList, } #[derive(Debug, Clone, PartialEq, PartialOrd)] +/// Parsed value container used in results and defaults. pub enum ArgumentValue { None, Boolean(bool), @@ -88,6 +113,7 @@ impl Into for ArgumentValue { } #[derive(Debug)] +/// Declarative definition for a single CLI argument or positional parameter. pub struct Argument { name: String, description: String, @@ -99,7 +125,11 @@ pub struct Argument { } impl Argument { - /// Creates a new argument where the name represents + /// Create a new argument definition. + /// + /// The `name` should be the canonical identifier used in help/usage output + /// (for example, `--output` or `--count`). For positional parameters call + /// `as_positional()` when building. pub fn new(name: &str) -> Self { return Argument { name: name.to_string(), @@ -118,13 +148,13 @@ impl Argument { return self; } - /// Sets the type for the ArgumentParser to parse the arguments value into. + /// Sets the type the parser should use when converting the raw value. pub fn with_type(mut self, arg_type: ArgumentType) -> Self { self.arg_type = arg_type; return self; } - /// Sets the description (Help string) of the argument for + /// Set a human‑readable description used in help/usage output. pub fn with_description(mut self, description: &str) -> Self { self.description = description.to_string(); return self; @@ -167,27 +197,33 @@ impl Argument { return self.arg_type.clone(); } + /// Canonical name used for matching and display (e.g., `--output`). pub fn name(&self) -> &str { return self.name.as_ref(); } + /// Default value used when the argument is not present. pub fn default_value(&self) -> ArgumentValue { return self.default_value.clone(); } + /// Description shown in `usage()` output. pub fn description(&self) -> &str { return self.description.as_ref(); } + /// Declared aliases that resolve to this argument (e.g., `-o`). pub fn aliases(&self) -> &Vec { &self.aliases } + /// Whether the argument is positional (no leading `-`/`--`). pub fn is_positional(&self) -> bool { self.positional } } #[derive(Debug, Clone)] +/// A single parsed argument result as `(name, value)`. pub struct ParsedArgument { name: String, value: ArgumentValue, @@ -205,6 +241,7 @@ impl ParsedArgument { return self.name.clone(); } + /// Return a clone of the parsed value. pub fn value(&self) -> ArgumentValue { return self.value.clone(); } @@ -240,17 +277,20 @@ impl ArgumentParser { return self.args.len(); } + /// Add an author string displayed in `usage()`. pub fn with_author(mut self, author: &str) -> Self { self.authors.push(author.to_string()); self } // TODO(vmarcella): Add description to the name + /// Add a human‑readable description shown in `usage()`. pub fn with_description(mut self, description: &str) -> Self { self.description = description.to_string(); self } + /// Register an argument definition with the parser. pub fn with_argument(mut self, argument: Argument) -> Self { let idx = self.args.len(); let name = argument.name().to_string(); @@ -264,7 +304,7 @@ impl ArgumentParser { return self; } - /// Set an environment variable prefix (e.g., "OBJ_LOADER"). + /// Set an environment variable prefix to read defaults (e.g., "OBJ_LOADER"). pub fn with_env_prefix(mut self, prefix: &str) -> Self { self.env_prefix = Some(prefix.to_string()); self @@ -290,13 +330,13 @@ impl ArgumentParser { self } - /// Merge values from a simple key=value config file (optional). + /// Merge values from a simple `key=value` config file (optional). pub fn with_config_file(mut self, path: &str) -> Self { self.config_path = Some(path.to_string()); self } - /// Add a subcommand parser. + /// Add a subcommand parser which activates on a matching first token. pub fn with_subcommand(mut self, mut sub: ArgumentParser) -> Self { sub.is_subcommand = true; let key = sub.name.clone(); @@ -717,7 +757,7 @@ impl ArgumentParser { }) } - /// Backwards-compatible panicking API. Prefer `parse` for non-panicking behavior. + /// Backwards‑compatible panicking API. Prefer `parse` for non‑panicking use. pub fn compile(self, args: &[String]) -> Vec { match self.parse(args) { Ok(parsed) => parsed.into_vec(), @@ -791,16 +831,23 @@ fn parse_value(arg: &Argument, raw: &str) -> Result { } #[derive(Debug)] +/// Errors that may occur during argument parsing. pub enum ArgsError { + /// An unknown flag or option was encountered. UnknownArgument(String), + /// The same flag/option was specified more than once when not allowed. DuplicateArgument(String), + /// A flag/option expecting a value did not receive one. MissingValue(String), + /// A provided value could not be parsed into the expected type. InvalidValue { name: String, expected: String, value: String, }, + /// A required option or positional argument was not provided. MissingRequired(String), + /// Help was requested; contains a preformatted usage string. HelpRequested(String), } @@ -831,7 +878,7 @@ impl fmt::Display for ArgsError { impl std::error::Error for ArgsError {} -/// A parsed arguments wrapper with typed getters. +/// Parsed arguments with typed getters and subcommand support. #[derive(Debug, Clone)] pub struct ParsedArgs { values: Vec, @@ -839,10 +886,12 @@ pub struct ParsedArgs { } impl ParsedArgs { + /// Convert into the raw underlying `(name, value)` vector. pub fn into_vec(self) -> Vec { self.values } + /// True if the named argument is present (and not `None`). pub fn has(&self, name: &str) -> bool { self .values @@ -850,6 +899,7 @@ impl ParsedArgs { .any(|p| p.name == name && !matches!(p.value, ArgumentValue::None)) } + /// Get a `String` value by name, if present and typed as string. pub fn get_string(&self, name: &str) -> Option { self .values @@ -861,6 +911,7 @@ impl ParsedArgs { }) } + /// Get an `i64` value by name, if present and typed as integer. pub fn get_i64(&self, name: &str) -> Option { self .values @@ -872,6 +923,7 @@ impl ParsedArgs { }) } + /// Get an `f32` value by name, if present and typed as float. pub fn get_f32(&self, name: &str) -> Option { self .values @@ -883,6 +935,7 @@ impl ParsedArgs { }) } + /// Get an `f64` value by name, if present and typed as double. pub fn get_f64(&self, name: &str) -> Option { self .values @@ -894,6 +947,7 @@ impl ParsedArgs { }) } + /// Get a `bool` value by name, if present and typed as boolean. pub fn get_bool(&self, name: &str) -> Option { self .values diff --git a/crates/lambda-rs-logging/src/handler.rs b/crates/lambda-rs-logging/src/handler.rs index 4e418b2e..f2a5d5c7 100644 --- a/crates/lambda-rs-logging/src/handler.rs +++ b/crates/lambda-rs-logging/src/handler.rs @@ -9,6 +9,10 @@ use std::{ use crate::LogLevel; +/// Pluggable sink for log records emitted by the `Logger`. +/// +/// Implementors decide how to format and where to deliver messages for each +/// severity level. pub trait Handler { fn trace(&mut self, message: String); fn debug(&mut self, message: String); @@ -102,6 +106,7 @@ impl Handler for FileHandler { } #[derive(Debug, Clone, PartialEq, PartialOrd)] +/// A handler that prints colored log lines to stdout. pub struct ConsoleHandler { name: String, } diff --git a/crates/lambda-rs-logging/src/lib.rs b/crates/lambda-rs-logging/src/lib.rs index 1fbd7cf6..a2e97582 100644 --- a/crates/lambda-rs-logging/src/lib.rs +++ b/crates/lambda-rs-logging/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] //! A simple logging library for lambda-rs crates. use std::fmt::Debug; diff --git a/crates/lambda-rs-platform/src/lib.rs b/crates/lambda-rs-platform/src/lib.rs index 3e7248a5..2e4ca19c 100644 --- a/crates/lambda-rs-platform/src/lib.rs +++ b/crates/lambda-rs-platform/src/lib.rs @@ -1,3 +1,10 @@ +#![allow(clippy::needless_return)] +//! Cross‑platform abstractions and utilities used by Lambda. +//! +//! This crate hosts thin wrappers around `winit` (windowing) and `wgpu` +//! (graphics) that provide consistent defaults and ergonomic builders, along +//! with shader compilation backends and small helper modules (e.g., OBJ +//! loading and random number generation). pub mod obj; pub mod rand; pub mod shader; diff --git a/crates/lambda-rs-platform/src/obj/mod.rs b/crates/lambda-rs-platform/src/obj/mod.rs index 07aec04c..2114463d 100644 --- a/crates/lambda-rs-platform/src/obj/mod.rs +++ b/crates/lambda-rs-platform/src/obj/mod.rs @@ -1,3 +1,7 @@ +//! Minimal helpers for loading Wavefront OBJ assets. +//! +//! These functions are thin wrappers around the `obj` crate used by examples +//! and tooling to import meshes. use std::{ fs::File, io::BufReader, diff --git a/crates/lambda-rs-platform/src/rand/mod.rs b/crates/lambda-rs-platform/src/rand/mod.rs index 5e727226..b87c2473 100644 --- a/crates/lambda-rs-platform/src/rand/mod.rs +++ b/crates/lambda-rs-platform/src/rand/mod.rs @@ -1,3 +1,7 @@ +//! Random number utilities used by examples and tests. +//! +//! Functions here delegate to the `rand` crate to generate simple random +//! values and uniformly distributed sequences. use rand::Rng; /// Generate a random float within any given range. diff --git a/crates/lambda-rs-platform/src/winit/mod.rs b/crates/lambda-rs-platform/src/winit/mod.rs index 4f39e881..853eeb57 100644 --- a/crates/lambda-rs-platform/src/winit/mod.rs +++ b/crates/lambda-rs-platform/src/winit/mod.rs @@ -81,6 +81,7 @@ pub struct WindowSize { pub physical: PhysicalSize, } +/// Aggregated window handle with cached sizing and monitor metadata. pub struct WindowHandle { pub window_handle: Window, pub size: WindowSize, @@ -88,6 +89,7 @@ pub struct WindowHandle { } // Should we take the loop as a field right here? Probably a ref or something? IDK +/// Builder for constructing a `WindowHandle` from window properties. pub struct WindowHandleBuilder { window_handle: Option, size: WindowSize, diff --git a/crates/lambda-rs/examples/minimal.rs b/crates/lambda-rs/examples/minimal.rs index 9158c3e3..43413baa 100644 --- a/crates/lambda-rs/examples/minimal.rs +++ b/crates/lambda-rs/examples/minimal.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] //! Minimal application which configures a window & render context before //! starting the runtime. You can use this as a starting point for your own //! applications or to verify that your system is configured to run lambda diff --git a/crates/lambda-rs/examples/push_constants.rs b/crates/lambda-rs/examples/push_constants.rs index 90d06370..4d5014be 100644 --- a/crates/lambda-rs/examples/push_constants.rs +++ b/crates/lambda-rs/examples/push_constants.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_return)] + use lambda::{ component::Component, events::WindowEvent, diff --git a/crates/lambda-rs/examples/triangle.rs b/crates/lambda-rs/examples/triangle.rs index 43d8a1ce..2ee9aa59 100644 --- a/crates/lambda-rs/examples/triangle.rs +++ b/crates/lambda-rs/examples/triangle.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] use lambda::{ component::Component, events::{ diff --git a/crates/lambda-rs/examples/triangles.rs b/crates/lambda-rs/examples/triangles.rs index b8a4548d..9815e012 100644 --- a/crates/lambda-rs/examples/triangles.rs +++ b/crates/lambda-rs/examples/triangles.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] use lambda::{ component::Component, events::{ diff --git a/crates/lambda-rs/src/lib.rs b/crates/lambda-rs/src/lib.rs index 43d12c06..b3a9b2b2 100644 --- a/crates/lambda-rs/src/lib.rs +++ b/crates/lambda-rs/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::needless_return)] //! Lambda is a simple, fast, and safe compute engine written in Rust. pub mod component; diff --git a/crates/lambda-rs/src/math/mod.rs b/crates/lambda-rs/src/math/mod.rs index cfbc1380..17804a1a 100644 --- a/crates/lambda-rs/src/math/mod.rs +++ b/crates/lambda-rs/src/math/mod.rs @@ -3,9 +3,16 @@ pub mod matrix; pub mod vector; +/// Angle units used by conversion helpers and matrix transforms. +/// +/// Prefer `Angle::Turns` for ergonomic quarter/half rotations when building +/// camera and model transforms. One full turn equals `2π` radians. pub enum Angle { + /// Angle expressed in radians. Radians(f32), + /// Angle expressed in degrees. Degrees(f32), + /// Angle expressed in turns, where `1.0` is a full revolution. Turns(f32), } diff --git a/crates/lambda-rs/src/render/mod.rs b/crates/lambda-rs/src/render/mod.rs index d67ca12c..735db8e7 100644 --- a/crates/lambda-rs/src/render/mod.rs +++ b/crates/lambda-rs/src/render/mod.rs @@ -120,6 +120,7 @@ pub struct RenderContext { render_pipelines: Vec, } +/// Opaque handle used to refer to resources attached to a `RenderContext`. pub type ResourceId = usize; impl RenderContext { diff --git a/crates/lambda-rs/src/render/window.rs b/crates/lambda-rs/src/render/window.rs index 9d20ad1e..ee5567a8 100644 --- a/crates/lambda-rs/src/render/window.rs +++ b/crates/lambda-rs/src/render/window.rs @@ -42,6 +42,11 @@ impl WindowBuilder { return self; } + /// Request vertical sync behavior for the swapchain. + /// + /// Note: present mode is ultimately selected when configuring the rendering + /// surface in `RenderContextBuilder`. This flag is reserved to influence + /// that choice and is currently a no‑op. pub fn with_vsync(mut self, vsync: bool) -> Self { return self; } diff --git a/crates/lambda-rs/src/runtimes/application.rs b/crates/lambda-rs/src/runtimes/application.rs index d316afa8..4cf2b51d 100644 --- a/crates/lambda-rs/src/runtimes/application.rs +++ b/crates/lambda-rs/src/runtimes/application.rs @@ -42,11 +42,19 @@ use crate::{ }; #[derive(Clone, Debug)] +/// Result value used by component callbacks executed under +/// `ApplicationRuntime`. +/// +/// Components can return `Success` when work completed as expected or +/// `Failure` to signal a non‑fatal error to the runtime. pub enum ComponentResult { Success, Failure, } +/// Builder for constructing an `ApplicationRuntime` with a window, a +/// configured `RenderContext`, and a stack of components that receive events +/// and render access. pub struct ApplicationRuntimeBuilder { app_name: String, render_context_builder: RenderContextBuilder, @@ -55,6 +63,7 @@ pub struct ApplicationRuntimeBuilder { } impl ApplicationRuntimeBuilder { + /// Create a new builder seeded with sensible defaults. pub fn new(app_name: &str) -> Self { return Self { app_name: app_name.to_string(), diff --git a/crates/lambda-rs/src/runtimes/mod.rs b/crates/lambda-rs/src/runtimes/mod.rs index eb459f59..4968d88b 100644 --- a/crates/lambda-rs/src/runtimes/mod.rs +++ b/crates/lambda-rs/src/runtimes/mod.rs @@ -1,3 +1,6 @@ +//! Runtime implementations and builders for Lambda applications. +//!\n//! This module currently exposes the windowed `ApplicationRuntime` which pairs +//! a `RenderContext` with an event loop and a component stack. pub mod application; pub use application::{ ApplicationRuntime, diff --git a/crates/lambda-rs/tests/runnables.rs b/crates/lambda-rs/tests/runnables.rs index 4b3b1ed8..fc4bb623 100644 --- a/crates/lambda-rs/tests/runnables.rs +++ b/crates/lambda-rs/tests/runnables.rs @@ -1,2 +1,3 @@ +#![allow(clippy::needless_return)] #[test] fn lambda_runnable() {} diff --git a/rustfmt.toml b/rustfmt.toml index e330908f..24e4d6e9 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,5 +1,6 @@ edition="2021" -fn_args_layout="Tall" +fn_params_layout="Tall" +fn_args_layout = "Tall" force_explicit_abi=true max_width=80 tab_spaces=2