implement editwriter for the binary edit channel
This commit is contained in:
1 parent
d90c71c508
commit
21b71e992f
4 files changed
+207
-4
No files matched your search
@@ -18,10 +18,13 @@ sledgehammer_bindgen = { git = "https://github.com/ealmloff/sledgehammer_bindgen
|
|||||||
sledgehammer_utils = { version = "0.2", optional = true }
|
sledgehammer_utils = { version = "0.2", optional = true }
|
||||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||||
|
|
||||||
|
dioxus-core = { workspace = true , optional = true }
|
||||||
|
dioxus-html = { workspace = true , optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
serialize = ["serde"]
|
serialize = ["serde"]
|
||||||
sledgehammer = ["sledgehammer_bindgen", "sledgehammer_utils"]
|
sledgehammer = ["sledgehammer_bindgen", "sledgehammer_utils"]
|
||||||
web = ["sledgehammer", "wasm-bindgen", "js-sys", "web-sys", "sledgehammer_bindgen/web"]
|
web = ["sledgehammer", "wasm-bindgen", "js-sys", "web-sys", "sledgehammer_bindgen/web"]
|
||||||
binary-protocol = ["sledgehammer", "wasm-bindgen"]
|
binary-protocol = ["sledgehammer", "wasm-bindgen", "dioxus-core", "dioxus-html"]
|
||||||
minimal_bindings = []
|
minimal_bindings = []
|
||||||
@@ -10,6 +10,11 @@ mod sledgehammer_bindings;
|
|||||||
#[cfg(feature = "sledgehammer")]
|
#[cfg(feature = "sledgehammer")]
|
||||||
pub use sledgehammer_bindings::*;
|
pub use sledgehammer_bindings::*;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "binary-protocol", feature = "sledgehammer"))]
|
||||||
|
mod write_native_mutations;
|
||||||
|
#[cfg(all(feature = "binary-protocol", feature = "sledgehammer"))]
|
||||||
|
pub use write_native_mutations::*;
|
||||||
|
|
||||||
// Common bindings for minimal usage.
|
// Common bindings for minimal usage.
|
||||||
#[cfg(all(feature = "minimal_bindings", feature = "web"))]
|
#[cfg(all(feature = "minimal_bindings", feature = "web"))]
|
||||||
pub mod minimal_bindings {
|
pub mod minimal_bindings {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub const SLEDGEHAMMER_JS: &str = GENERATED_JS;
|
|||||||
#[cfg(feature = "web")]
|
#[cfg(feature = "web")]
|
||||||
#[bindgen(module)]
|
#[bindgen(module)]
|
||||||
mod js {
|
mod js {
|
||||||
const JS_FILE: &str = "./packages/interpreter/src/common.js";
|
const JS_FILE: &str = "./src/common.js";
|
||||||
const JS: &str = r#"
|
const JS: &str = r#"
|
||||||
class ListenerMap {
|
class ListenerMap {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
@@ -260,8 +260,8 @@ pub mod binary_protocol {
|
|||||||
|
|
||||||
#[bindgen]
|
#[bindgen]
|
||||||
mod protocol_js {
|
mod protocol_js {
|
||||||
const JS_FILE: &str = "./packages/interpreter/src/interpreter.js";
|
const JS_FILE: &str = "./src/interpreter.js";
|
||||||
const JS_FILE: &str = "./packages/interpreter/src/common.js";
|
const JS_FILE: &str = "./src/common.js";
|
||||||
|
|
||||||
fn mount_to_root() {
|
fn mount_to_root() {
|
||||||
"{AppendChildren(root, stack.length-1);}"
|
"{AppendChildren(root, stack.length-1);}"
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
use dioxus_html::event_bubbles;
|
||||||
|
|
||||||
|
use dioxus_core::{TemplateAttribute, TemplateNode, WriteMutations};
|
||||||
|
use sledgehammer_utils::rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use crate::binary_protocol::Channel;
|
||||||
|
|
||||||
|
/// The state needed to apply mutations to a channel. This state should be kept across all mutations for the app
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MutationState {
|
||||||
|
/// The maximum number of templates that we have registered
|
||||||
|
max_template_count: u16,
|
||||||
|
/// The currently registered templates with the template ids
|
||||||
|
templates: FxHashMap<String, u16>,
|
||||||
|
/// The channel that we are applying mutations to
|
||||||
|
channel: Channel,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutationState {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn export_memory(&mut self) -> Vec<u8> {
|
||||||
|
let bytes: Vec<_> = self.channel.export_memory().collect();
|
||||||
|
self.channel.reset();
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel(&mut self) -> &mut Channel {
|
||||||
|
&mut self.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn channel_mut(&mut self) -> &mut Channel {
|
||||||
|
&mut self.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_template_node(&mut self, node: &'static TemplateNode) {
|
||||||
|
use TemplateNode::*;
|
||||||
|
match node {
|
||||||
|
Element {
|
||||||
|
tag,
|
||||||
|
namespace,
|
||||||
|
attrs,
|
||||||
|
children,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// Push the current node onto the stack
|
||||||
|
match namespace {
|
||||||
|
Some(ns) => self.channel.create_element_ns(tag, ns),
|
||||||
|
None => self.channel.create_element(tag),
|
||||||
|
}
|
||||||
|
// Set attributes on the current node
|
||||||
|
for attr in *attrs {
|
||||||
|
if let TemplateAttribute::Static {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
namespace,
|
||||||
|
} = attr
|
||||||
|
{
|
||||||
|
self.channel
|
||||||
|
.set_top_attribute(name, value, namespace.unwrap_or_default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add each child to the stack
|
||||||
|
for child in *children {
|
||||||
|
self.create_template_node(child);
|
||||||
|
}
|
||||||
|
// Add all children to the parent
|
||||||
|
self.channel.append_children_to_top(children.len() as u16);
|
||||||
|
}
|
||||||
|
Text { text } => self.channel.create_raw_text(text),
|
||||||
|
DynamicText { .. } => self.channel.create_raw_text("p"),
|
||||||
|
Dynamic { .. } => self.channel.add_placeholder(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WriteMutations for MutationState {
|
||||||
|
fn register_template(&mut self, template: dioxus_core::prelude::Template) {
|
||||||
|
let current_max_template_count = self.max_template_count;
|
||||||
|
for root in template.roots.iter() {
|
||||||
|
self.create_template_node(root);
|
||||||
|
self.templates
|
||||||
|
.insert(template.name.to_owned(), current_max_template_count);
|
||||||
|
}
|
||||||
|
self.channel
|
||||||
|
.add_templates(current_max_template_count, template.roots.len() as u16);
|
||||||
|
|
||||||
|
self.max_template_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_children(&mut self, id: dioxus_core::ElementId, m: usize) {
|
||||||
|
self.channel.append_children(id.0 as u32, m as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_node_id(&mut self, path: &'static [u8], id: dioxus_core::ElementId) {
|
||||||
|
self.channel.assign_id(path, id.0 as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_placeholder(&mut self, id: dioxus_core::ElementId) {
|
||||||
|
self.channel.create_placeholder(id.0 as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_text_node(&mut self, value: &str, id: dioxus_core::ElementId) {
|
||||||
|
self.channel.create_text_node(value, id.0 as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: dioxus_core::ElementId) {
|
||||||
|
self.channel.hydrate_text(path, value, id.0 as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_template(&mut self, name: &'static str, index: usize, id: dioxus_core::ElementId) {
|
||||||
|
if let Some(tmpl_id) = self.templates.get(name) {
|
||||||
|
self.channel
|
||||||
|
.load_template(*tmpl_id, index as u16, id.0 as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_node_with(&mut self, id: dioxus_core::ElementId, m: usize) {
|
||||||
|
self.channel.replace_with(id.0 as u32, m as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
|
||||||
|
self.channel.replace_placeholder(path, m as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_nodes_after(&mut self, id: dioxus_core::ElementId, m: usize) {
|
||||||
|
self.channel.insert_after(id.0 as u32, m as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_nodes_before(&mut self, id: dioxus_core::ElementId, m: usize) {
|
||||||
|
self.channel.insert_before(id.0 as u32, m as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_attribute(
|
||||||
|
&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
ns: Option<&'static str>,
|
||||||
|
value: &dioxus_core::AttributeValue,
|
||||||
|
id: dioxus_core::ElementId,
|
||||||
|
) {
|
||||||
|
match value {
|
||||||
|
dioxus_core::AttributeValue::Text(txt) => {
|
||||||
|
self.channel
|
||||||
|
.set_attribute(id.0 as u32, name, txt, ns.unwrap_or_default())
|
||||||
|
}
|
||||||
|
dioxus_core::AttributeValue::Float(f) => self.channel.set_attribute(
|
||||||
|
id.0 as u32,
|
||||||
|
name,
|
||||||
|
&f.to_string(),
|
||||||
|
ns.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
dioxus_core::AttributeValue::Int(n) => self.channel.set_attribute(
|
||||||
|
id.0 as u32,
|
||||||
|
name,
|
||||||
|
&n.to_string(),
|
||||||
|
ns.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
dioxus_core::AttributeValue::Bool(b) => self.channel.set_attribute(
|
||||||
|
id.0 as u32,
|
||||||
|
name,
|
||||||
|
if *b { "true" } else { "false" },
|
||||||
|
ns.unwrap_or_default(),
|
||||||
|
),
|
||||||
|
dioxus_core::AttributeValue::None => {
|
||||||
|
self.channel
|
||||||
|
.remove_attribute(id.0 as u32, name, ns.unwrap_or_default())
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_node_text(&mut self, value: &str, id: dioxus_core::ElementId) {
|
||||||
|
self.channel.set_text(id.0 as u32, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_event_listener(&mut self, name: &'static str, id: dioxus_core::ElementId) {
|
||||||
|
self.channel
|
||||||
|
.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_event_listener(&mut self, name: &'static str, id: dioxus_core::ElementId) {
|
||||||
|
self.channel
|
||||||
|
.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_node(&mut self, id: dioxus_core::ElementId) {
|
||||||
|
self.channel.remove(id.0 as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_root(&mut self, _id: dioxus_core::ElementId) {
|
||||||
|
self.channel.push_root(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user