Skip to main content

openmw_config/config/
filesetting.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Dave Corley (S3kshun8)
3
4use crate::{GameSetting, GameSettingMeta};
5use std::fmt;
6
7/// A plain filename entry from an `openmw.cfg` file (`content=`, `fallback-archive=`, `groundcover=`).
8///
9/// Stores only the filename string — no path resolution is applied, since these entries name
10/// files looked up through the VFS rather than direct filesystem paths.
11///
12/// `PartialEq` comparisons are value-only and ignore source metadata, making it straightforward
13/// to check whether a particular file is present regardless of which config file defined it.
14#[derive(Debug, Clone)]
15pub struct FileSetting {
16    meta: GameSettingMeta,
17    value: String,
18}
19
20impl PartialEq for FileSetting {
21    fn eq(&self, other: &Self) -> bool {
22        &self.value == other.value()
23    }
24}
25
26impl PartialEq<&str> for FileSetting {
27    fn eq(&self, other: &&str) -> bool {
28        self.value == *other
29    }
30}
31
32impl PartialEq<str> for FileSetting {
33    fn eq(&self, other: &str) -> bool {
34        self.value == other
35    }
36}
37
38impl PartialEq<&String> for FileSetting {
39    fn eq(&self, other: &&String) -> bool {
40        &self.value == *other
41    }
42}
43
44impl GameSetting for FileSetting {
45    fn meta(&self) -> &GameSettingMeta {
46        &self.meta
47    }
48
49    fn meta_mut(&mut self) -> &mut GameSettingMeta {
50        &mut self.meta
51    }
52}
53
54impl fmt::Display for FileSetting {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        write!(f, "{}", self.value)
57    }
58}
59
60impl FileSetting {
61    /// Creates a new `FileSetting` attributed to `source_config`.
62    ///
63    /// Consumes the accumulated `comment` string (via [`std::mem::take`]).
64    pub fn new(value: &str, source_config: &std::path::Path, comment: &mut String) -> Self {
65        Self {
66            meta: GameSettingMeta {
67                source_config: source_config.to_path_buf(),
68                comment: std::mem::take(comment),
69            },
70            value: value.to_string(),
71        }
72    }
73
74    /// The filename string as it appeared in the `openmw.cfg` file.
75    #[must_use]
76    pub fn value(&self) -> &String {
77        &self.value
78    }
79
80    /// Borrowed string view of [`Self::value`].
81    #[must_use]
82    pub fn value_str(&self) -> &str {
83        &self.value
84    }
85
86    /// The file that defined the entry and the comment above it.
87    #[must_use]
88    pub fn meta(&self) -> &GameSettingMeta {
89        &self.meta
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use std::path::PathBuf;
97
98    #[test]
99    fn test_new_consumes_comment_and_sets_metadata() {
100        let source = PathBuf::from("/tmp/openmw.cfg");
101        let mut comment = String::from("# note\n");
102
103        let setting = FileSetting::new("Morrowind.esm", &source, &mut comment);
104
105        assert_eq!(setting.value(), "Morrowind.esm");
106        assert_eq!(setting.value_str(), "Morrowind.esm");
107        assert_eq!(setting.meta().source_config, source);
108        assert_eq!(setting.meta().comment, "# note\n");
109        assert!(comment.is_empty());
110    }
111
112    #[test]
113    fn test_display_outputs_only_file_value() {
114        let source = PathBuf::from("/tmp/openmw.cfg");
115        let mut comment = String::new();
116        let setting = FileSetting::new("Tribunal.esm", &source, &mut comment);
117
118        assert_eq!(setting.to_string(), "Tribunal.esm");
119    }
120
121    #[test]
122    fn test_partial_eq_variants_compare_by_value_only() {
123        let source = PathBuf::from("/tmp/openmw.cfg");
124        let mut comment = String::from("# ignored\n");
125
126        let lhs = FileSetting::new("Bloodmoon.esm", &source, &mut comment);
127        let rhs = FileSetting::new("Bloodmoon.esm", &source, &mut String::new());
128        let str_owned = String::from("Bloodmoon.esm");
129
130        assert_eq!(lhs, rhs);
131        assert_eq!(lhs, "Bloodmoon.esm");
132        assert_eq!(lhs, str_owned.as_str());
133        assert_eq!(lhs, &str_owned);
134    }
135}