♻️ Make SerializableResult to depend on From traits

This commit is contained in:
Belén Albeza
2025-12-11 15:17:33 +01:00
parent ea4d0e1238
commit 0a7a65af5d
10 changed files with 89 additions and 64 deletions

View File

@@ -303,7 +303,7 @@ pub extern "C" fn set_focus_mode() {
let entries: Vec<Uuid> = bytes
.chunks(size_of::<<Uuid as SerializableResult>::BytesType>())
.map(|data| Uuid::from_bytes(data.try_into().unwrap()))
.map(|data| Uuid::try_from(data).unwrap())
.collect();
with_state_mut!(state, {
@@ -523,7 +523,7 @@ pub extern "C" fn set_children() {
let entries: Vec<Uuid> = bytes
.chunks(size_of::<<Uuid as SerializableResult>::BytesType>())
.map(|data| Uuid::from_bytes(data.try_into().unwrap()))
.map(|data| Uuid::try_from(data).unwrap())
.collect();
set_children_set(entries);
@@ -679,7 +679,7 @@ pub extern "C" fn propagate_modifiers(pixel_precision: bool) -> *mut u8 {
let entries: Vec<_> = bytes
.chunks(size_of::<<TransformEntry as SerializableResult>::BytesType>())
.map(|data| TransformEntry::from_bytes(data.try_into().unwrap()))
.map(|data| TransformEntry::try_from(data).unwrap())
.collect();
with_state!(state, {
@@ -694,7 +694,7 @@ pub extern "C" fn set_modifiers() {
let entries: Vec<_> = bytes
.chunks(size_of::<<TransformEntry as SerializableResult>::BytesType>())
.map(|data| TransformEntry::from_bytes(data.try_into().unwrap()))
.map(|data| TransformEntry::try_from(data).unwrap())
.collect();
let mut modifiers = HashMap::new();

View File

@@ -57,10 +57,8 @@ pub fn bytes_or_empty() -> Vec<u8> {
guard.take().unwrap_or_default()
}
pub trait SerializableResult {
pub trait SerializableResult: From<Self::BytesType> + Into<Self::BytesType> {
type BytesType;
fn from_bytes(bytes: Self::BytesType) -> Self;
fn as_bytes(&self) -> Self::BytesType;
fn clone_to_slice(&self, slice: &mut [u8]);
}

View File

@@ -384,7 +384,7 @@ pub fn propagate_modifiers(
if math::identitish(&entry.transform) {
Modifier::Reflow(entry.id)
} else {
Modifier::Transform(entry.clone())
Modifier::Transform(*entry)
}
})
.collect();

View File

@@ -1053,7 +1053,7 @@ impl TextSpan {
}
#[allow(dead_code)]
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct PositionData {
pub paragraph: u32,
pub span: u32,

View File

@@ -23,13 +23,13 @@ impl Modifier {
}
}
#[derive(PartialEq, Debug, Clone)]
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum TransformEntrySource {
Input,
Propagate,
}
#[derive(PartialEq, Debug, Clone)]
#[derive(PartialEq, Debug, Clone, Copy)]
#[repr(C)]
pub struct TransformEntry {
pub id: Uuid,
@@ -65,10 +65,8 @@ impl TransformEntry {
}
}
impl SerializableResult for TransformEntry {
type BytesType = [u8; 40];
fn from_bytes(bytes: Self::BytesType) -> Self {
impl From<[u8; 40]> for TransformEntry {
fn from(bytes: [u8; 40]) -> Self {
let id = uuid_from_u32_quartet(
u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
@@ -89,29 +87,46 @@ impl SerializableResult for TransformEntry {
);
TransformEntry::from_input(id, transform)
}
}
fn as_bytes(&self) -> Self::BytesType {
let mut result: Self::BytesType = [0; 40];
let (a, b, c, d) = uuid_to_u32_quartet(&self.id);
impl TryFrom<&[u8]> for TransformEntry {
type Error = String;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let bytes: [u8; 40] = bytes
.try_into()
.map_err(|_| "Invalid transform entry bytes".to_string())?;
Ok(TransformEntry::from(bytes))
}
}
impl From<TransformEntry> for [u8; 40] {
fn from(value: TransformEntry) -> Self {
let mut result = [0; 40];
let (a, b, c, d) = uuid_to_u32_quartet(&value.id);
result[0..4].clone_from_slice(&a.to_le_bytes());
result[4..8].clone_from_slice(&b.to_le_bytes());
result[8..12].clone_from_slice(&c.to_le_bytes());
result[12..16].clone_from_slice(&d.to_le_bytes());
result[16..20].clone_from_slice(&self.transform[0].to_le_bytes());
result[20..24].clone_from_slice(&self.transform[3].to_le_bytes());
result[24..28].clone_from_slice(&self.transform[1].to_le_bytes());
result[28..32].clone_from_slice(&self.transform[4].to_le_bytes());
result[32..36].clone_from_slice(&self.transform[2].to_le_bytes());
result[36..40].clone_from_slice(&self.transform[5].to_le_bytes());
result[16..20].clone_from_slice(&value.transform[0].to_le_bytes());
result[20..24].clone_from_slice(&value.transform[3].to_le_bytes());
result[24..28].clone_from_slice(&value.transform[1].to_le_bytes());
result[28..32].clone_from_slice(&value.transform[4].to_le_bytes());
result[32..36].clone_from_slice(&value.transform[2].to_le_bytes());
result[36..40].clone_from_slice(&value.transform[5].to_le_bytes());
result
}
}
impl SerializableResult for TransformEntry {
type BytesType = [u8; 40];
// The generic trait doesn't know the size of the array. This is why the
// clone needs to be here even if it could be generic.
fn clone_to_slice(&self, slice: &mut [u8]) {
slice.clone_from_slice(&self.as_bytes());
let bytes = Self::BytesType::from(*self);
slice.clone_from_slice(&bytes);
}
}
@@ -198,8 +213,8 @@ mod tests {
Matrix::new_all(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 0.0, 0.0, 1.0),
);
let bytes = entry.as_bytes();
let bytes: [u8; 40] = entry.into();
assert_eq!(entry, TransformEntry::from_bytes(bytes));
assert_eq!(entry, TransformEntry::from(bytes));
}
}

View File

@@ -49,10 +49,8 @@ impl fmt::Display for Uuid {
}
}
impl SerializableResult for Uuid {
type BytesType = [u8; 16];
fn from_bytes(bytes: Self::BytesType) -> Self {
impl From<[u8; 16]> for Uuid {
fn from(bytes: [u8; 16]) -> Self {
Self(*uuid_from_u32_quartet(
u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
@@ -60,10 +58,22 @@ impl SerializableResult for Uuid {
u32::from_le_bytes([bytes[12], bytes[13], bytes[14], bytes[15]]),
))
}
}
fn as_bytes(&self) -> Self::BytesType {
let mut result: Self::BytesType = [0; 16];
let (a, b, c, d) = uuid_to_u32_quartet(self);
impl TryFrom<&[u8]> for Uuid {
type Error = String;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let bytes: [u8; 16] = bytes
.try_into()
.map_err(|_| "Invalid UUID bytes".to_string())?;
Ok(Self::from(bytes))
}
}
impl From<Uuid> for [u8; 16] {
fn from(value: Uuid) -> Self {
let mut result = [0; 16];
let (a, b, c, d) = uuid_to_u32_quartet(&value);
result[0..4].clone_from_slice(&a.to_le_bytes());
result[4..8].clone_from_slice(&b.to_le_bytes());
result[8..12].clone_from_slice(&c.to_le_bytes());
@@ -71,10 +81,15 @@ impl SerializableResult for Uuid {
result
}
}
impl SerializableResult for Uuid {
type BytesType = [u8; 16];
// The generic trait doesn't know the size of the array. This is why the
// clone needs to be here even if it could be generic.
fn clone_to_slice(&self, slice: &mut [u8]) {
slice.clone_from_slice(&self.as_bytes());
let bytes = Self::BytesType::from(*self);
slice.clone_from_slice(&bytes);
}
}

View File

@@ -1,5 +1,5 @@
use crate::mem;
use crate::mem::SerializableResult;
// use crate::mem::SerializableResult;
use crate::uuid::Uuid;
use crate::with_state_mut;
use crate::STATE;
@@ -48,8 +48,8 @@ pub struct ShapeImageIds {
impl From<[u8; IMAGE_IDS_SIZE]> for ShapeImageIds {
fn from(bytes: [u8; IMAGE_IDS_SIZE]) -> Self {
let shape_id = Uuid::from_bytes(bytes[0..16].try_into().unwrap());
let image_id = Uuid::from_bytes(bytes[16..32].try_into().unwrap());
let shape_id = Uuid::try_from(&bytes[0..16]).unwrap();
let image_id = Uuid::try_from(&bytes[16..32]).unwrap();
ShapeImageIds { shape_id, image_id }
}
}
@@ -93,7 +93,7 @@ pub extern "C" fn store_image() {
/// Stores an image from an existing WebGL texture, avoiding re-decoding
/// Expected memory layout:
/// - bytes 0-15: shape UUID
/// - bytes 16-31: image UUID
/// - bytes 16-31: image UUID
/// - bytes 32-35: is_thumbnail flag (u32)
/// - bytes 36-39: GL texture ID (u32)
/// - bytes 40-43: width (i32)

View File

@@ -51,25 +51,20 @@ impl TryFrom<&[u8]> for RawSegmentData {
}
}
impl From<RawSegmentData> for [u8; RAW_SEGMENT_DATA_SIZE] {
fn from(value: RawSegmentData) -> Self {
unsafe { std::mem::transmute(value) }
}
}
impl SerializableResult for RawSegmentData {
type BytesType = [u8; RAW_SEGMENT_DATA_SIZE];
fn from_bytes(bytes: Self::BytesType) -> Self {
unsafe { std::mem::transmute(bytes) }
}
fn as_bytes(&self) -> Self::BytesType {
let ptr = self as *const RawSegmentData as *const u8;
let bytes: &[u8] = unsafe { std::slice::from_raw_parts(ptr, RAW_SEGMENT_DATA_SIZE) };
let mut result = [0; RAW_SEGMENT_DATA_SIZE];
result.copy_from_slice(bytes);
result
}
// The generic trait doesn't know the size of the array. This is why the
// clone needs to be here even if it could be generic.
fn clone_to_slice(&self, slice: &mut [u8]) {
slice.clone_from_slice(&self.as_bytes());
let bytes = Self::BytesType::from(*self);
slice.clone_from_slice(&bytes);
}
}

View File

@@ -48,7 +48,7 @@ pub extern "C" fn calculate_bool(raw_bool_type: u8) -> *mut u8 {
let entries: Vec<Uuid> = bytes
.chunks(size_of::<<Uuid as SerializableResult>::BytesType>())
.map(|data| Uuid::from_bytes(data.try_into().unwrap()))
.map(|data| Uuid::try_from(data).unwrap())
.collect();
mem::free_bytes();

View File

@@ -415,24 +415,26 @@ pub extern "C" fn get_caret_position_at(x: f32, y: f32) -> i32 {
const RAW_POSITION_DATA_SIZE: usize = size_of::<shapes::PositionData>();
impl SerializableResult for shapes::PositionData {
type BytesType = [u8; RAW_POSITION_DATA_SIZE];
fn from_bytes(bytes: Self::BytesType) -> Self {
impl From<[u8; RAW_POSITION_DATA_SIZE]> for shapes::PositionData {
fn from(bytes: [u8; RAW_POSITION_DATA_SIZE]) -> Self {
unsafe { std::mem::transmute(bytes) }
}
fn as_bytes(&self) -> Self::BytesType {
let ptr = self as *const shapes::PositionData as *const u8;
let bytes: &[u8] = unsafe { std::slice::from_raw_parts(ptr, RAW_POSITION_DATA_SIZE) };
let mut result = [0; RAW_POSITION_DATA_SIZE];
result.copy_from_slice(bytes);
result
}
impl From<shapes::PositionData> for [u8; RAW_POSITION_DATA_SIZE] {
fn from(value: shapes::PositionData) -> Self {
unsafe { std::mem::transmute(value) }
}
}
impl SerializableResult for shapes::PositionData {
type BytesType = [u8; RAW_POSITION_DATA_SIZE];
// The generic trait doesn't know the size of the array. This is why the
// clone needs to be here even if it could be generic.
fn clone_to_slice(&self, slice: &mut [u8]) {
slice.clone_from_slice(&self.as_bytes());
let bytes = Self::BytesType::from(*self);
slice.clone_from_slice(&bytes);
}
}