artichoke_backend/
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::module_name_repetitions,
14    reason = "incompatible with how code is organized in private modules"
15)]
16#![allow(
17    clippy::unnecessary_lazy_evaluations,
18    reason = "https://github.com/rust-lang/rust-clippy/issues/8109"
19)]
20#![cfg_attr(
21    test,
22    allow(clippy::non_ascii_literal, reason = "tests sometimes require UTF-8 string content")
23)]
24#![allow(unknown_lints)]
25#![warn(
26    missing_copy_implementations,
27    missing_debug_implementations,
28    missing_docs,
29    rust_2024_compatibility,
30    trivial_casts,
31    trivial_numeric_casts,
32    unused_qualifications,
33    variant_size_differences
34)]
35#![expect(missing_docs, reason = "TODO: fully document crate")]
36#![expect(clippy::undocumented_unsafe_blocks, reason = "working through legacy code")]
37// Enable feature callouts in generated documentation:
38// https://doc.rust-lang.org/beta/unstable-book/language-features/doc-cfg.html
39//
40// This approach is borrowed from tokio.
41#![cfg_attr(docsrs, feature(doc_cfg))]
42#![cfg_attr(docsrs, feature(doc_alias))]
43
44//! # artichoke-backend
45//!
46//! `artichoke-backend` crate provides a Ruby interpreter. It is currently
47//! implemented with [mruby](https://github.com/mruby/mruby) bindings exported
48//! by the [`sys`] module.
49//!
50//! ## Execute Ruby Code
51//!
52//! `artichoke-backend` crate exposes several mechanisms for executing Ruby code
53//! on the interpreter.
54//!
55//! ### Evaling Source Code
56//!
57//! The `artichoke-backend` interpreter implements
58//! [`Eval` from `artichoke-core`](crate::core::Eval).
59//!
60//! ```rust
61//! use artichoke_backend::prelude::*;
62//!
63//! # fn example() -> Result<(), Error> {
64//! let mut interp = artichoke_backend::interpreter()?;
65//! let result = interp.eval(b"10 * 10")?;
66//! let result = result.try_convert_into::<i64>(&interp)?;
67//! assert_eq!(result, 100);
68//! # interp.close();
69//! # Ok(())
70//! # }
71//! # example().unwrap();
72//! ```
73//!
74//! ### Calling Functions on Ruby Objects
75//!
76//! [`Value`](value::Value)s returned by the `artichoke-backend` interpreter
77//! implement [`Value` from `artichoke-core`](crate::core::Value), which enables
78//! calling Ruby functions from Rust.
79//!
80//! ```rust
81//! use artichoke_backend::prelude::*;
82//!
83//! # fn example() -> Result<(), Error> {
84//! let mut interp = artichoke_backend::interpreter()?;
85//! let result = interp.eval(b"'ruby funcall'")?;
86//! let result = result.funcall(&mut interp, "length", &[], None)?;
87//! let result = result.try_convert_into::<i64>(&mut interp)?;
88//! assert_eq!(result, 12);
89//! # interp.close();
90//! # Ok(())
91//! # }
92//! # example().unwrap();
93//! ```
94//!
95//! ## Virtual File System and `Kernel#require`
96//!
97//! The `artichoke-backend` interpreter includes an in-memory virtual
98//! file system.  The file system stores Ruby sources and Rust extension functions
99//! that are similar to MRI C extensions.
100//!
101//! The virtual file system enables applications built with `artichoke-backend`
102//! to `require` sources that are embedded in the binary without host file system
103//! access.
104//!
105//! ## Embed Rust Types in Ruby `Value`s
106//!
107//! `artichoke-backend` exposes a concept similar to `data`-typed values in MRI
108//! and mruby.
109//!
110//! When Rust types implement a special trait, they can be embedded in a Ruby
111//! [`Value`](value::Value) and passed through the Ruby VM as a Ruby object.
112//! Classes defined in this way can define methods in Rust or Ruby.
113//!
114//! Examples of these types include:
115//!
116//! - `Regexp` and `MatchData`, which are backed by regular expressions from the
117//!   `onig` and `regex` crates.
118//! - `ENV`, which glues Ruby to an environ backend.
119//!
120//! ## Converters Between Ruby and Rust Types
121//!
122//! The [`convert` module](convert) provides implementations for conversions
123//! between boxed Ruby values and native Rust types like `i64` and
124//! `HashMap<String, Option<Vec<u8>>>` using an `artichoke-backend` interpreter.
125
126#![doc(html_root_url = "https://artichoke.github.io/artichoke/artichoke_backend")]
127#![doc(html_favicon_url = "https://www.artichokeruby.org/favicon-32x32.png")]
128#![doc(html_logo_url = "https://www.artichokeruby.org/artichoke-logo.svg")]
129
130// Ensure code blocks in `README.md` compile
131#[cfg(doctest)]
132#[doc = include_str!("../README.md")]
133mod readme {}
134
135#[macro_use]
136#[doc(hidden)]
137pub mod macros;
138
139mod artichoke;
140pub mod block;
141pub mod class;
142mod class_registry;
143mod coerce_to_numeric;
144mod constant;
145pub mod convert;
146mod debug;
147pub mod def;
148pub mod error;
149mod eval;
150pub mod exception_handler;
151pub mod extn;
152pub mod ffi;
153pub mod fmt;
154pub mod gc;
155mod globals;
156mod hash;
157mod intern;
158mod interpreter;
159mod io;
160mod load;
161pub mod load_path;
162pub mod method;
163pub mod module;
164mod module_registry;
165mod parser;
166mod platform_string;
167#[cfg(feature = "core-random")]
168mod prng;
169#[cfg(feature = "core-regexp")]
170mod regexp;
171pub mod release_metadata;
172pub mod state;
173pub mod sys;
174mod top_self;
175pub mod types;
176pub mod value;
177mod warn;
178
179#[cfg(test)]
180mod test;
181
182pub use artichoke_core::prelude as core;
183
184pub use crate::artichoke::{Artichoke, Guard};
185pub use crate::error::{Error, RubyException};
186pub use crate::interpreter::{interpreter, interpreter_with_config};
187
188/// A "prelude" for users of the `artichoke-backend` crate.
189///
190/// This prelude is similar to the standard library's prelude in that you'll
191/// almost always want to import its entire contents, but unlike the standard
192/// library's prelude, you'll have to do so manually:
193///
194/// ```
195/// use artichoke_backend::prelude::*;
196/// ```
197///
198/// The prelude may grow over time as additional items see ubiquitous use.
199pub mod prelude {
200    pub use artichoke_core::prelude::*;
201    pub use spinoso_exception::core::*;
202
203    pub use crate::error::{self, Error, RubyException};
204    pub use crate::gc::MrbGarbageCollection;
205    pub use crate::release_metadata::ReleaseMetadata;
206    pub use crate::{Artichoke, Guard};
207}