mezzaluna_load_path/
lib.rs

1#![warn(clippy::all, clippy::pedantic, clippy::undocumented_unsafe_blocks)]
2#![allow(
3    clippy::let_underscore_untyped,
4    reason = "https://github.com/rust-lang/rust-clippy/pull/10442#issuecomment-1516570154"
5)]
6#![allow(
7    clippy::question_mark,
8    reason = "https://github.com/rust-lang/rust-clippy/issues/8281"
9)]
10#![allow(clippy::manual_let_else, reason = "manual_let_else was very buggy on release")]
11#![allow(clippy::missing_errors_doc, reason = "A lot of existing code fails this lint")]
12#![allow(
13    clippy::unnecessary_lazy_evaluations,
14    reason = "https://github.com/rust-lang/rust-clippy/issues/8109"
15)]
16#![cfg_attr(
17    test,
18    allow(clippy::non_ascii_literal, reason = "tests sometimes require UTF-8 string content")
19)]
20#![allow(unknown_lints)]
21#![warn(
22    missing_copy_implementations,
23    missing_debug_implementations,
24    missing_docs,
25    rust_2024_compatibility,
26    trivial_casts,
27    trivial_numeric_casts,
28    unused_qualifications,
29    variant_size_differences
30)]
31#![cfg_attr(not(test), forbid(unsafe_code))]
32// Enable feature callouts in generated documentation:
33// https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html
34//
35// This approach is borrowed from tokio.
36#![cfg_attr(docsrs, feature(doc_cfg))]
37#![cfg_attr(docsrs, feature(doc_alias))]
38
39//! Ruby load path builders.
40//!
41//! An Artichoke Ruby VM may load code (called "features") from several file
42//! system locations. These locations form the `$LOAD_PATH` global.
43//!
44//! Code and native extensions from the Ruby Core library and Ruby Standard
45//! Library can be loaded from an [in-memory virtual file system].
46//!
47//! [in-memory virtual file system]: RubyCore
48//!
49#![cfg_attr(feature = "rubylib", doc = "Users can prepend items to the load path at interpreter")]
50#![cfg_attr(
51    feature = "rubylib",
52    doc = "boot by setting the [`RUBYLIB` environment variable](Rubylib)."
53)]
54//!
55//! This crate exports builders which can be used to construct the initial load
56//! path at interpreter boot. See their documentation for more details.
57//!
58//! # Examples
59//!
60//! ```
61//! # #[cfg(feature = "rubylib")]
62//! # fn example() -> Option<()> {
63//! use std::ffi::OsStr;
64//! use std::path::PathBuf;
65//! use mezzaluna_load_path::{RubyCore, Rubylib};
66//!
67//! let core_loader = RubyCore::new();
68//! let rubylib_loader = Rubylib::with_rubylib(OsStr::new("lib"))?;
69//!
70//! // Assemble the load path in priority order.
71//! let load_path = rubylib_loader
72//!     .into_load_path()
73//!     .into_iter()
74//!     .chain(core_loader.load_path().into_iter().map(PathBuf::from))
75//!     .collect::<Box<[PathBuf]>>();
76//!
77//! assert_eq!(load_path.len(), 3);
78//! # Some(())
79//! # }
80//! # #[cfg(feature = "rubylib")]
81//! # example().unwrap();
82//! ```
83
84// Ensure code blocks in `README.md` compile
85#[cfg(all(doctest, feature = "rubylib"))]
86#[doc = include_str!("../README.md")]
87mod readme {}
88
89mod ruby_core;
90#[cfg(feature = "rubylib")]
91mod rubylib;
92
93pub use ruby_core::RubyCore;
94#[cfg(feature = "rubylib")]
95pub use rubylib::Rubylib;
96
97#[cfg(all(test, feature = "rubylib"))]
98mod tests {
99    use std::ffi::OsStr;
100    use std::path::{Path, PathBuf};
101
102    use super::*;
103
104    #[test]
105    fn test_assemble_load_path() {
106        let core_loader = RubyCore::new();
107        let rubylib_loader = Rubylib::with_rubylib(OsStr::new("lib")).unwrap();
108
109        // Assemble the load path in priority order.
110        let load_path = rubylib_loader
111            .into_load_path()
112            .into_iter()
113            .chain(core_loader.load_path().into_iter().map(PathBuf::from))
114            .collect::<Box<[PathBuf]>>();
115
116        assert_eq!(load_path.len(), 3);
117        assert_eq!(load_path.first().unwrap(), Path::new("lib"));
118    }
119}