1use crate::AssetOptions;
2use const_serialize::{ConstStr, SerializeConst};
3use std::path::PathBuf;
4
5#[derive(
11 Debug,
12 PartialEq,
13 PartialOrd,
14 Clone,
15 Copy,
16 Hash,
17 SerializeConst,
18 serde::Serialize,
19 serde::Deserialize,
20)]
21pub struct BundledAsset {
22 absolute_source_path: ConstStr,
24 bundled_path: ConstStr,
26 options: AssetOptions,
28}
29
30impl BundledAsset {
31 #[doc(hidden)]
32 pub const fn new(
35 absolute_source_path: &'static str,
36 bundled_path: &'static str,
37 options: AssetOptions,
38 ) -> Self {
39 Self {
40 absolute_source_path: ConstStr::new(absolute_source_path),
41 bundled_path: ConstStr::new(bundled_path),
42 options,
43 }
44 }
45
46 #[doc(hidden)]
47 #[deprecated(
52 note = "Relative asset!() paths are not supported. Use a path like `/assets/myfile.png` instead of `./assets/myfile.png`"
53 )]
54 pub const fn new_relative(
55 absolute_source_path: &'static str,
56 bundled_path: &'static str,
57 options: AssetOptions,
58 ) -> Self {
59 Self::new(absolute_source_path, bundled_path, options)
60 }
61
62 #[doc(hidden)]
63 pub const fn new_from_const(
66 absolute_source_path: ConstStr,
67 bundled_path: ConstStr,
68 options: AssetOptions,
69 ) -> Self {
70 Self {
71 absolute_source_path,
72 bundled_path,
73 options,
74 }
75 }
76
77 pub fn bundled_path(&self) -> &str {
79 self.bundled_path.as_str()
80 }
81
82 pub fn absolute_source_path(&self) -> &str {
84 self.absolute_source_path.as_str()
85 }
86 pub const fn options(&self) -> &AssetOptions {
88 &self.options
89 }
90}
91
92#[derive(Debug, PartialEq, Clone, Copy)]
105pub struct Asset {
106 bundled: BundledAsset,
108 keep_link_section: fn() -> u8,
110}
111
112impl Asset {
113 #[doc(hidden)]
114 pub const fn new(bundled: BundledAsset, keep_link_section: fn() -> u8) -> Self {
117 Self {
118 bundled,
119 keep_link_section,
120 }
121 }
122
123 pub const fn bundled(&self) -> &BundledAsset {
125 &self.bundled
126 }
127
128 pub fn resolve(&self) -> PathBuf {
133 (self.keep_link_section)();
135
136 #[cfg(feature = "dioxus")]
137 if !dioxus_core_types::is_bundled_app() {
139 return PathBuf::from(self.bundled.absolute_source_path.as_str());
140 }
141
142 #[cfg(feature = "dioxus")]
143 let bundle_root = {
144 let base_path = dioxus_cli_config::base_path();
145 let base_path = base_path
146 .as_deref()
147 .map(|base_path| {
148 let trimmed = base_path.trim_matches('/');
149 format!("/{trimmed}")
150 })
151 .unwrap_or_default();
152 PathBuf::from(format!("{base_path}/assets/"))
153 };
154 #[cfg(not(feature = "dioxus"))]
155 let bundle_root = PathBuf::from("/assets/");
156
157 bundle_root.join(PathBuf::from(
159 self.bundled.bundled_path.as_str().trim_start_matches('/'),
160 ))
161 }
162}
163
164impl From<Asset> for String {
165 fn from(value: Asset) -> Self {
166 value.to_string()
167 }
168}
169impl From<Asset> for Option<String> {
170 fn from(value: Asset) -> Self {
171 Some(value.to_string())
172 }
173}
174
175impl std::fmt::Display for Asset {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 write!(f, "{}", self.resolve().display())
178 }
179}
180
181#[cfg(feature = "dioxus")]
182impl dioxus_core_types::DioxusFormattable for Asset {
183 fn format(&self) -> std::borrow::Cow<'static, str> {
184 std::borrow::Cow::Owned(self.to_string())
185 }
186}