Skip to main content

wdl_modules/
lib.rs

1//! Implementation of the WDL module specification.
2//!
3//! `wdl-modules` provides the local, deterministic pieces of WDL module
4//! handling: `module.json` manifest parsing, `module-lock.json` lockfile
5//! parsing, symbolic import paths, deterministic content hashing, Ed25519
6//! `module.sig` signing and verification, SPDX license validation, and
7//! module file-tree checks.
8//!
9//! # Quickstart
10//!
11//! Parse `module.json` with [`Manifest::parse`], parse `module-lock.json` with
12//! [`Lockfile::parse`], and compute a content hash with
13//! [`hash::hash_directory`]. These entry points reject duplicate JSON object
14//! keys, invalid relative paths, invalid dependency declarations, and module
15//! trees that violate the reserved-filename or Unicode-normalization rules.
16//!
17//! ```rust
18//! use wdl_modules::Manifest;
19//!
20//! let manifest = Manifest::parse(
21//!     br#"{
22//!         "name": "spellbook",
23//!         "version": "1.0.0",
24//!         "license": "MIT"
25//!     }"#,
26//! )?;
27//!
28//! assert_eq!(manifest.name, "spellbook");
29//! # Ok::<(), Box<dyn std::error::Error>>(())
30//! ```
31
32pub mod dependency;
33pub mod hash;
34pub mod license;
35pub mod lockfile;
36pub mod manifest;
37pub mod module;
38pub mod module_walk;
39pub mod relative_path;
40pub mod resolver;
41pub mod signing;
42mod strict_json;
43pub mod symbolic_path;
44pub mod tree;
45pub mod version_requirement;
46
47pub use crate::lockfile::Lockfile;
48pub use crate::manifest::Manifest;
49pub use crate::resolver::Resolver;
50
51/// The filename of a module manifest.
52pub const MANIFEST_FILENAME: &str = "module.json";
53
54/// The filename of a module lockfile.
55pub const LOCKFILE_FILENAME: &str = "module-lock.json";
56
57/// The filename of a module signature.
58pub const SIGNATURE_FILENAME: &str = "module.sig";
59
60/// The default filename of a module entrypoint, used when
61/// `Manifest::entrypoint` is not set.
62pub const DEFAULT_ENTRYPOINT_FILENAME: &str = "index.wdl";
63
64/// The default filename of a module readme, used when `Manifest::readme` is
65/// `Readme::Default`.
66pub const DEFAULT_README_FILENAME: &str = "README.md";
67
68/// Returns `true` if `s` begins with a Windows-style drive letter (e.g.
69/// `C:`, `c:\\`, `Z:/`). The spec rejects these as cross-platform unsafe
70/// even on non-Windows hosts where `Path::is_absolute` does not flag
71/// them.
72pub(crate) fn starts_with_windows_drive(s: &str) -> bool {
73    let mut bytes = s.bytes();
74    matches!(
75        (bytes.next(), bytes.next()),
76        (Some(b'A'..=b'Z' | b'a'..=b'z'), Some(b':'))
77    )
78}