Skip to main content

mago_prelude/
lib.rs

1//! A crate for building and loading Mago's "prelude".
2//!
3//! The prelude contains the pre-compiled `Database` and `CodebaseMetadata` for all
4//! of PHP's built-in symbols (functions, classes, constants, etc.). This is
5//! essential for providing accurate analysis, especially in environments like WASM
6//! where stubs cannot be loaded from the filesystem.
7//!
8//! ## Workflow
9//!
10//! This crate is split into two parts using a feature flag:
11//!
12//! 1.  **At Compile Time (with the `build` feature):**
13//!     - A `build.rs` script enables the `build` feature for this crate.
14//!     - It calls `Prelude::build()` to perform the expensive, one-time analysis of all stub files.
15//!     - It then calls `prelude.encode()` to serialize the result into a byte slice.
16//!     - The bytes are written to a file (e.g., `prelude.bin`) in the `OUT_DIR`.
17//!
18//! 2.  **At Runtime (without the `build` feature):**
19//!     - The main application uses `include_bytes!` to embed the `prelude.bin` file.
20//!     - It calls `Prelude::decode()` on the bytes to instantly reconstruct the prelude in memory.
21
22use bincode::config::standard;
23use serde::Deserialize;
24use serde::Serialize;
25
26use mago_codex::metadata::CodebaseMetadata;
27use mago_codex::reference::SymbolReferences;
28use mago_database::Database;
29
30use crate::error::PreludeError;
31
32pub mod error;
33
34#[cfg(feature = "build")]
35pub mod build;
36
37/// A container for the pre-compiled database and metadata of PHP's built-in symbols.
38///
39/// This struct holds all the necessary, fully-analyzed data for PHP's core library,
40/// allowing for instant startup without needing to parse and analyze stubs at runtime.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct Prelude {
43    /// The database of all built-in PHP files.
44    pub database: Database<'static>,
45    /// The fully populated and analyzed metadata for all symbols in the database.
46    pub metadata: CodebaseMetadata,
47    /// The collected symbol references from the analysis.
48    pub symbol_references: SymbolReferences,
49}
50
51impl Prelude {
52    /// Decodes a prelude from a byte slice.
53    ///
54    /// This is the primary runtime function, used to load a pre-compiled prelude
55    /// that was embedded in the binary. It is a very fast operation.
56    ///
57    /// # Errors
58    ///
59    /// Returns a [`PreludeError`] if deserialization fails due to corrupted or
60    /// incompatible binary data.
61    pub fn decode(bytes: &[u8]) -> Result<Self, PreludeError> {
62        let (prelude, _) = bincode::serde::decode_from_slice(bytes, standard())?;
63
64        Ok(prelude)
65    }
66
67    /// (Builder-only) Builds the prelude by parsing and analyzing all embedded PHP stub files.
68    ///
69    /// This is an expensive, one-time operation that should only be run at compile
70    /// time within a `build.rs` script. It is only available when the `build`
71    /// feature is enabled.
72    #[cfg(feature = "build")]
73    #[must_use]
74    pub fn build() -> Self {
75        build::build_prelude_internal()
76    }
77
78    /// (Builder-only) Encodes the prelude into a compact byte slice.
79    ///
80    /// The resulting `Vec<u8>` can be saved to a file for later loading.
81    /// This is only available when the `build` feature is enabled.
82    ///
83    /// # Errors
84    ///
85    /// Returns a [`PreludeError`] if serialization fails.
86    #[cfg(feature = "build")]
87    pub fn encode(&self) -> Result<Vec<u8>, PreludeError> {
88        Ok(bincode::serde::encode_to_vec(self, standard())?)
89    }
90}
91
92impl Default for Prelude {
93    fn default() -> Self {
94        let configuration =
95            mago_database::DatabaseConfiguration::new(std::path::Path::new("/"), vec![], vec![], vec![], vec![])
96                .into_static();
97
98        Self {
99            database: mago_database::Database::new(configuration),
100            metadata: CodebaseMetadata::default(),
101            symbol_references: SymbolReferences::default(),
102        }
103    }
104}