wgui: use ouroboros self-ref struct

This commit is contained in:
Aleksander
2025-06-17 22:54:21 +02:00
parent 8c4eb4bd49
commit 231b8bc3e1
3 changed files with 76 additions and 24 deletions

50
Cargo.lock generated
View File

@@ -55,6 +55,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "aliasable"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
[[package]] [[package]]
name = "aligned-vec" name = "aligned-vec"
version = "0.6.4" version = "0.6.4"
@@ -3419,6 +3425,30 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "ouroboros"
version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
dependencies = [
"aliasable",
"ouroboros_macro",
"static_assertions",
]
[[package]]
name = "ouroboros_macro"
version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
dependencies = [
"heck 0.4.1",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.103",
]
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@@ -3784,6 +3814,19 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "proc-macro2-diagnostics"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.103",
"version_check",
"yansi",
]
[[package]] [[package]]
name = "profiling" name = "profiling"
version = "1.0.16" version = "1.0.16"
@@ -5600,6 +5643,7 @@ dependencies = [
"image", "image",
"log", "log",
"lru", "lru",
"ouroboros",
"resvg", "resvg",
"roxmltree 0.20.0", "roxmltree 0.20.0",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
@@ -6372,6 +6416,12 @@ dependencies = [
"hashlink", "hashlink",
] ]
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]] [[package]]
name = "yansi-term" name = "yansi-term"
version = "0.1.2" version = "0.1.2"

View File

@@ -17,6 +17,7 @@ image = { version = "0.25.6", default-features = false, features = [
] } ] }
log = { workspace = true } log = { workspace = true }
lru = "0.14.0" lru = "0.14.0"
ouroboros = "0.18.5"
resvg = { version = "0.45.1", default-features = false } resvg = { version = "0.45.1", default-features = false }
roxmltree = "0.20.0" roxmltree = "0.20.0"
rustc-hash = "2.1.1" rustc-hash = "2.1.1"

View File

@@ -5,6 +5,7 @@ use std::{
rc::Rc, rc::Rc,
}; };
use ouroboros::self_referencing;
use taffy::{ use taffy::{
AlignContent, AlignItems, AlignSelf, BoxSizing, Display, FlexDirection, FlexWrap, JustifyContent, AlignContent, AlignItems, AlignSelf, BoxSizing, Display, FlexDirection, FlexWrap, JustifyContent,
JustifySelf, Overflow, JustifySelf, Overflow,
@@ -29,8 +30,17 @@ use crate::{
type VarMap = HashMap<Rc<str>, Rc<str>>; type VarMap = HashMap<Rc<str>, Rc<str>>;
#[self_referencing]
struct XmlDocument {
xml: String,
#[borrows(xml)]
#[covariant]
doc: roxmltree::Document<'this>,
}
struct Template { struct Template {
doc: Rc<roxmltree::Document<'static>>, doc: Rc<XmlDocument>,
node: roxmltree::NodeId, node: roxmltree::NodeId,
parameters: HashMap<Rc<str>, Rc<str>>, parameters: HashMap<Rc<str>, Rc<str>>,
} }
@@ -58,8 +68,7 @@ struct ParserContext<'a> {
struct ParserFile<'a> { struct ParserFile<'a> {
path: PathBuf, path: PathBuf,
_xml: Rc<Box<str>>, document: Rc<XmlDocument>,
document: Rc<roxmltree::Document<'static>>,
ctx: Rc<RefCell<ParserContext<'a>>>, ctx: Rc<RefCell<ParserContext<'a>>>,
} }
@@ -806,7 +815,6 @@ fn parse_children<'a>(
}; };
let file = ParserFile { let file = ParserFile {
_xml: file._xml.clone(),
ctx: file.ctx.clone(), ctx: file.ctx.clone(),
document: template.doc.clone(), document: template.doc.clone(),
path: file.path.clone(), path: file.path.clone(),
@@ -815,6 +823,7 @@ fn parse_children<'a>(
let doc = template.doc.clone(); let doc = template.doc.clone();
let template_node = doc let template_node = doc
.borrow_doc()
.get_node(template.node) .get_node(template.node)
.ok_or(anyhow::anyhow!("template node invalid"))?; .ok_or(anyhow::anyhow!("template node invalid"))?;
@@ -849,12 +858,9 @@ pub fn parse_from_assets(
Ok(result) Ok(result)
} }
fn assets_path_to_xml( fn assets_path_to_xml(assets: &mut Box<dyn AssetProvider>, path: &Path) -> anyhow::Result<String> {
assets: &mut Box<dyn AssetProvider>,
path: &Path,
) -> anyhow::Result<Rc<String>> {
let data = assets.load_from_path(&path.to_string_lossy())?; let data = assets.load_from_path(&path.to_string_lossy())?;
Ok(Rc::from(String::from_utf8(data)?)) Ok(String::from_utf8(data)?)
} }
fn get_doc_from_path<'a>( fn get_doc_from_path<'a>(
@@ -862,24 +868,19 @@ fn get_doc_from_path<'a>(
ctx: &mut ParserContext, ctx: &mut ParserContext,
path: &Path, path: &Path,
) -> anyhow::Result<ParserFile<'a>> { ) -> anyhow::Result<ParserFile<'a>> {
let opt = roxmltree::ParsingOptions { let xml = assets_path_to_xml(&mut ctx.layout.assets, path)?;
allow_dtd: true, let document = XmlDocument::new(xml, |xml| {
..Default::default() let opt = roxmltree::ParsingOptions {
}; allow_dtd: true,
..Default::default()
let xml_string = assets_path_to_xml(&mut ctx.layout.assets, path)?; };
roxmltree::Document::parse_with_options(xml, opt).unwrap()
let xml = Rc::new(<std::string::String as Clone>::clone(&xml_string).into_boxed_str()); });
let xml_ref: &'static str = Box::leak(Box::new(Rc::clone(&xml)));
let document = Rc::new(roxmltree::Document::parse_with_options(xml_ref, opt)?);
let file = ParserFile { let file = ParserFile {
ctx: ctx_rc.clone(), ctx: ctx_rc.clone(),
path: PathBuf::from(path), path: PathBuf::from(path),
document, document: Rc::new(document),
_xml: xml,
}; };
Ok(file) Ok(file)
@@ -890,7 +891,7 @@ fn parse_document_root(
ctx: &mut ParserContext, ctx: &mut ParserContext,
parent_id: WidgetID, parent_id: WidgetID,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let root = file.document.root(); let root = file.document.borrow_doc().root();
let tag_layout = require_tag_by_name(&root, "layout")?; let tag_layout = require_tag_by_name(&root, "layout")?;
for child_node in tag_layout.children() { for child_node in tag_layout.children() {