use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, }; use crate::{ color::Color, layers::{style, BlendMode, Layer}, LayerId, }; use serde::{Deserialize, Serialize}; #[repr(C)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub enum Operation { AddEllipse { path: Vec, insert_index: isize, transform: [f64; 6], style: style::PathStyle, }, AddOverlayEllipse { path: Vec, transform: [f64; 6], style: style::PathStyle, }, AddRect { path: Vec, insert_index: isize, transform: [f64; 6], style: style::PathStyle, }, AddOverlayRect { path: Vec, transform: [f64; 6], style: style::PathStyle, }, AddLine { path: Vec, insert_index: isize, transform: [f64; 6], style: style::PathStyle, }, AddOverlayLine { path: Vec, transform: [f64; 6], style: style::PathStyle, }, AddPen { path: Vec, transform: [f64; 6], insert_index: isize, points: Vec<(f64, f64)>, style: style::PathStyle, }, AddNgon { path: Vec, insert_index: isize, transform: [f64; 6], sides: u8, style: style::PathStyle, }, AddOverlayShape { path: Vec, bez_path: kurbo::BezPath, style: style::PathStyle, closed: bool, }, DeleteLayer { path: Vec, }, DuplicateLayer { path: Vec, }, RenameLayer { path: Vec, name: String, }, InsertLayer { layer: Layer, destination_path: Vec, insert_index: isize, }, CreateFolder { path: Vec, }, TransformLayer { path: Vec, transform: [f64; 6], }, TransformLayerInViewport { path: Vec, transform: [f64; 6], }, SetLayerTransformInViewport { path: Vec, transform: [f64; 6], }, SetShapePath { path: Vec, bez_path: kurbo::BezPath, }, SetShapePathInViewport { path: Vec, bez_path: kurbo::BezPath, transform: [f64; 6], }, TransformLayerInScope { path: Vec, transform: [f64; 6], scope: [f64; 6], }, SetLayerTransformInScope { path: Vec, transform: [f64; 6], scope: [f64; 6], }, SetLayerTransform { path: Vec, transform: [f64; 6], }, ToggleLayerVisibility { path: Vec, }, SetLayerVisibility { path: Vec, visible: bool, }, SetLayerBlendMode { path: Vec, blend_mode: BlendMode, }, SetLayerOpacity { path: Vec, opacity: f64, }, SetLayerStyle { path: Vec, style: style::PathStyle, }, SetLayerFill { path: Vec, color: Color, }, } impl Operation { /// 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 Operation as *const u8, std::mem::size_of::()) } /// Returns a pseudo hash that should uniquely identify the operation. /// This is needed because `Hash` is not implemented for f64s /// /// # 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() } }