wdl-modules 0.3.2

Implementation of the WDL module specification
Documentation
//! Implementation of the WDL module specification.
//!
//! `wdl-modules` provides the local, deterministic pieces of WDL module
//! handling: `module.json` manifest parsing, `module-lock.json` lockfile
//! parsing, symbolic import paths, deterministic content hashing, Ed25519
//! `module.sig` signing and verification, SPDX license validation, and
//! module file-tree checks.
//!
//! # Quickstart
//!
//! Parse `module.json` with [`Manifest::parse`], parse `module-lock.json` with
//! [`Lockfile::parse`], and compute a content hash with
//! [`hash::hash_directory`]. These entry points reject duplicate JSON object
//! keys, invalid relative paths, invalid dependency declarations, and module
//! trees that violate the reserved-filename or Unicode-normalization rules.
//!
//! Use [`project::ModuleProject`] to load an exact `module.json` path or
//! discover the nearest ancestor project. Use [`project::ManifestDocument`] to
//! edit `module.json` losslessly while preserving extension fields and
//! validating each change before it lands. Use
//! [`project::ModuleProject::write_manifest`] to replace `module.json` through
//! an atomic rename and [`project::LockedLockfile`] to read or rewrite the
//! sibling `module-lock.json` under its own advisory lock, and use
//! `resolver::TrustStore` to accept lockfile signers in a user-level
//! trust store outside the project tree.
//!
//! ```rust
//! use wdl_modules::Manifest;
//!
//! let manifest = Manifest::parse(
//!     br#"{
//!         "name": "spellbook",
//!         "license": "MIT"
//!     }"#,
//! )?;
//!
//! assert_eq!(manifest.name, "spellbook");
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```

pub mod dependency;
pub mod hash;
pub mod license;
pub mod lockfile;
pub mod manifest;
pub mod module;
pub mod module_walk;
pub mod project;
pub mod relative_path;
pub mod remote;
pub mod resolver;
pub mod signing;
mod strict_json;
pub mod symbolic_path;
pub mod tree;
pub use crate::remote::normalize_git_remote;
pub mod version_requirement;

pub use crate::lockfile::Lockfile;
pub use crate::manifest::Manifest;
pub use crate::resolver::Resolver;

/// The filename of a module manifest.
pub const MANIFEST_FILENAME: &str = "module.json";

/// The filename of a module lockfile.
pub const LOCKFILE_FILENAME: &str = "module-lock.json";

/// The filename of a module signature.
pub const SIGNATURE_FILENAME: &str = "module.sig";

/// The default filename of a module entrypoint, used when
/// `Manifest::entrypoint` is not set.
pub const DEFAULT_ENTRYPOINT_FILENAME: &str = "index.wdl";

/// The default filename of a module readme, used when `Manifest::readme` is
/// `Readme::Default`.
pub const DEFAULT_README_FILENAME: &str = "README.md";

/// Returns `true` if `s` begins with a Windows-style drive letter (e.g.
/// `C:`, `c:\\`, `Z:/`). The spec rejects these as cross-platform unsafe
/// even on non-Windows hosts where `Path::is_absolute` does not flag
/// them.
pub(crate) fn starts_with_windows_drive(s: &str) -> bool {
    let mut bytes = s.bytes();
    matches!(
        (bytes.next(), bytes.next()),
        (Some(b'A'..=b'Z' | b'a'..=b'z'), Some(b':'))
    )
}