Skip to main content

libretro_core/
content.rs

1//! Content-loading contract helpers shared by `SystemInfo` and `Environment`.
2//!
3//! `ContentContract` lets a core describe valid extensions, no-game support,
4//! fullpath requirements, and persistent data handling once, then apply that
5//! same contract to both startup metadata and environment registration.
6
7use crate::{ContentInfoOverride, Environment, SystemInfo};
8
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct ContentContract {
11    pub extensions: String,
12    pub need_fullpath: bool,
13    pub block_extract: bool,
14    pub supports_no_game: bool,
15    pub persistent_data: bool,
16}
17
18impl ContentContract {
19    pub fn new(extensions: impl Into<String>) -> Self {
20        Self {
21            extensions: extensions.into(),
22            need_fullpath: false,
23            block_extract: false,
24            supports_no_game: false,
25            persistent_data: false,
26        }
27    }
28
29    pub fn with_need_fullpath(mut self, need_fullpath: bool) -> Self {
30        self.need_fullpath = need_fullpath;
31        self
32    }
33
34    pub fn with_block_extract(mut self, block_extract: bool) -> Self {
35        self.block_extract = block_extract;
36        self
37    }
38
39    pub fn with_support_no_game(mut self, supports_no_game: bool) -> Self {
40        self.supports_no_game = supports_no_game;
41        self
42    }
43
44    pub fn with_persistent_data(mut self, persistent_data: bool) -> Self {
45        self.persistent_data = persistent_data;
46        self
47    }
48
49    pub fn apply_to_system_info(&self, info: &mut SystemInfo) {
50        info.valid_extensions = Some(self.extensions.clone());
51        info.need_fullpath = self.need_fullpath;
52        info.block_extract = self.block_extract;
53    }
54
55    pub fn register_environment(&self, env: &mut Environment<'_>) -> bool {
56        let support_ok = if self.supports_no_game {
57            env.set_support_no_game(true)
58        } else {
59            true
60        };
61        let override_ok = env.set_content_info_overrides(&[self.content_info_override()]);
62        support_ok && override_ok
63    }
64
65    pub fn content_info_override(&self) -> ContentInfoOverride {
66        ContentInfoOverride {
67            extensions: self.extensions.clone(),
68            need_fullpath: self.need_fullpath,
69            persistent_data: self.persistent_data,
70        }
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn content_contract_applies_system_info_and_override_fields() {
80        let contract = ContentContract::new("bin|dat")
81            .with_need_fullpath(true)
82            .with_block_extract(true)
83            .with_support_no_game(false)
84            .with_persistent_data(true);
85        let mut info = SystemInfo::new("test", "0.1");
86
87        contract.apply_to_system_info(&mut info);
88        let override_info = contract.content_info_override();
89
90        assert_eq!(info.valid_extensions.as_deref(), Some("bin|dat"));
91        assert!(info.need_fullpath);
92        assert!(info.block_extract);
93        assert_eq!(override_info.extensions, "bin|dat");
94        assert!(override_info.need_fullpath);
95        assert!(override_info.persistent_data);
96    }
97}