Remove unsafe code and clean up the code base in general (#1263)

* Remove unsafe code

* Make node graph test syncronous

* Add miri step to ci

* Remove unsafe from node graph evaluation

* Replace operation pseudo_hash with hash based on discriminant

* Fix test

* Move memo module to core and make it safe

* Fix formatting

* Remove unused stuff from gstd

* Use safe casting for creating key variants

* Fix memo node types

* Fix ref node

* "fix" ub

* Use correct input types for ExtractImageFrame

* Fix types for async nodes

* Fix missing implementation

* Manually override output type for async nodes

* Fix types for EditorApi

* Fix output type for WasmSurfaceHandle

* Remove unused miri.yml

* Fix incorrect type for cache node
This commit is contained in:
Dennis Kobert
2023-06-02 11:05:32 +02:00
committed by Keavon Chambers
parent 259dcdc628
commit 4e1bfddcd8
43 changed files with 520 additions and 1252 deletions

View File

@@ -37,9 +37,9 @@ impl InputMapperMessageHandler {
.filter_map(|(i, m)| {
let ma = m.0.iter().find_map(|m| actions.find_map(|a| (a == m.action.to_discriminant()).then(|| m.action.to_discriminant())));
ma.map(|a| unsafe { (std::mem::transmute_copy::<usize, Key>(&i), a) })
ma.map(|a| ((i as u8).try_into().unwrap(), a))
})
.for_each(|(k, a)| {
.for_each(|(k, a): (Key, _)| {
let _ = write!(output, "{}: {}, ", k.to_discriminant().local_name(), a.local_name().split('.').last().unwrap());
});
output.replace("Key", "")
@@ -72,7 +72,7 @@ impl InputMapperMessageHandler {
"Attempting to convert a Key with enum index {}, which is larger than the number of Key enums",
i
);
unsafe { std::mem::transmute_copy::<usize, Key>(&i) }
(i as u8).try_into().unwrap()
})
.collect::<Vec<_>>();

View File

@@ -50,7 +50,8 @@ bitflags! {
// (although we ignore the shift key, so the user doesn't have to press `Ctrl Shift +` on a US keyboard), even if the keyboard layout
// is for a different locale where the `+` key is somewhere entirely different, shifted or not. This would then also work for numpad `+`.
#[impl_message(Message, InputMapperMessage, KeyDown)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, specta::Type)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, specta::Type, num_enum::TryFromPrimitive)]
#[repr(u8)]
pub enum Key {
// Writing system keys
Digit0,

View File

@@ -41,28 +41,6 @@ pub enum Message {
Workspace(WorkspaceMessage),
}
impl Message {
/// Returns the byte representation of the message.
///
/// # Safety
/// This function reads from uninitialized memory!!!
/// Only use if you know what you are doing.
unsafe fn as_slice(&self) -> &[u8] {
core::slice::from_raw_parts(self as *const Message as *const u8, std::mem::size_of::<Message>())
}
/// Returns a pseudo hash that should uniquely identify the message.
/// This is needed because `Hash` is not implemented for `f64`s
///
/// # Safety
/// This function reads from uninitialized memory but the generated value should be fine.
pub fn pseudo_hash(&self) -> u64 {
let mut s = DefaultHasher::new();
unsafe { self.as_slice() }.hash(&mut s);
s.finish()
}
}
/// Provides an impl of `specta::Type` for `MessageDiscriminant`, the struct created by `impl_message`.
/// Specta isn't integrated with `impl_message`, so a remote impl must be provided using this
/// struct.

View File

@@ -1001,6 +1001,10 @@ impl DocumentMessageHandler {
// Calculate the size of the region to be exported and generate an SVG of the artwork below this layer within that region
let transform = self.document_legacy.multiply_transforms(&layer_path).unwrap();
let size = DVec2::new(transform.transform_vector2(DVec2::new(1., 0.)).length(), transform.transform_vector2(DVec2::new(0., 1.)).length());
// TODO: Fix this hack
// This is a hack to prevent the compiler from optimizing out the size calculation which likely is due
// to undefined behavior. THIS IS NOT A FIX.
log::trace!("size: {:?}", size);
let svg = self.render_document(size, transform.inverse(), persistent_data, DocumentRenderMode::OnlyBelowLayerInFolder(&layer_path));
self.restore_document_transform(old_transforms);

View File

@@ -148,7 +148,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
1,
DocumentNode {
inputs: vec![NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::proto("graphene_std::memo::MonitorNode<_>"),
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>"),
..Default::default()
},
),
@@ -198,7 +198,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNode {
name: "Cache".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default()
},
// We currently just clone by default
@@ -262,7 +262,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNode {
name: "Cache".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default()
},
]
@@ -305,7 +305,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNode {
name: "Cache".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::node(1, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default()
},
DocumentNode {
@@ -355,13 +355,13 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNode {
name: "LetNode".to_string(),
inputs: vec![NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::LetNode<_>")),
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::memo::LetNode<_>")),
..Default::default()
},
DocumentNode {
name: "RefNode".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::lambda(1, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::RefNode<_, _>")),
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::memo::RefNode<_, _>")),
..Default::default()
},
]
@@ -392,7 +392,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNodeType {
name: "End Scope",
category: "Ignore",
identifier: NodeImplementation::proto("graphene_std::memo::EndLetNode<_>"),
identifier: NodeImplementation::proto("graphene_core::memo::EndLetNode<_>"),
inputs: vec![
DocumentInputType {
name: "Scope",
@@ -666,47 +666,6 @@ fn static_nodes() -> Vec<DocumentNodeType> {
],
properties: node_properties::no_properties,
},
DocumentNodeType {
name: "Gaussian Blur",
category: "Ignore",
identifier: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 1, 1],
outputs: vec![NodeOutput::new(1, 0)],
nodes: vec![
(
0,
DocumentNode {
name: "CacheNode".to_string(),
inputs: vec![NodeInput::Network(concrete!(Image<Color>))],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
..Default::default()
},
),
(
1,
DocumentNode {
name: "BlurNode".to_string(),
inputs: vec![NodeInput::node(0, 0), NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(f64)), NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlurNode")),
..Default::default()
},
),
]
.into_iter()
.collect(),
..Default::default()
}),
inputs: vec![
DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true),
DocumentInputType::value("Radius", TaggedValue::U32(3), false),
DocumentInputType::value("Sigma", TaggedValue::F64(1.), false),
],
outputs: vec![DocumentOutputType {
name: "Image",
data_type: FrontendGraphDataType::Raster,
}],
properties: node_properties::blur_image_properties,
},
DocumentNodeType {
name: "Brush",
category: "Brush",
@@ -735,34 +694,9 @@ fn static_nodes() -> Vec<DocumentNodeType> {
properties: node_properties::no_properties,
},
DocumentNodeType {
name: "Cache",
name: "Memoize",
category: "Structural",
identifier: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0],
outputs: vec![NodeOutput::new(1, 0)],
nodes: [
(
0,
DocumentNode {
name: "CacheNode".to_string(),
inputs: vec![NodeInput::ShortCircut(concrete!(())), NodeInput::Network(concrete!(ImageFrame<Color>))],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::memo::CacheNode")),
..Default::default()
},
),
(
1,
DocumentNode {
name: "CloneNode".to_string(),
inputs: vec![NodeInput::node(0, 0)],
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::CloneNode<_>")),
..Default::default()
},
),
]
.into(),
..Default::default()
}),
identifier: NodeImplementation::proto("graphene_core::memo::MemoNode<_, _>"),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: node_properties::no_properties,
@@ -778,7 +712,7 @@ fn static_nodes() -> Vec<DocumentNodeType> {
DocumentNodeType {
name: "Ref",
category: "Structural",
identifier: NodeImplementation::proto("graphene_std::memo::CacheNode"),
identifier: NodeImplementation::proto("graphene_core::memo::MemoNode<_, _>"),
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
properties: node_properties::no_properties,
@@ -1330,7 +1264,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork {
let mut network_inputs = Vec::new();
let mut input_type = None;
for (id, node) in network.nodes.iter() {
for (index, input) in node.inputs.iter().enumerate() {
for input in node.inputs.iter() {
if let NodeInput::Network(_) = input {
if input_type.is_none() {
input_type = Some(input.clone());

View File

@@ -1222,9 +1222,7 @@ fn edit_layer_deepest_manipulation(intersect: &Layer, responses: &mut VecDeque<M
fn recursive_search(document: &DocumentMessageHandler, layer_path: &Vec<u64>, incoming_layer_path_vector: &Vec<u64>) -> bool {
let layer_paths = document.document_legacy.folder_children_paths(layer_path);
for path in layer_paths {
if path == *incoming_layer_path_vector {
return true;
} else if document.document_legacy.is_folder(path.clone()) && recursive_search(document, &path, incoming_layer_path_vector) {
if path == *incoming_layer_path_vector || document.document_legacy.is_folder(path.clone()) && recursive_search(document, &path, incoming_layer_path_vector) {
return true;
}
}