sybot/rcs/
des.rs

1use core::cell::RefCell;
2use std::collections::HashMap;
3
4use alloc::rc::Rc;
5use glam::{Vec3, Mat3};
6use serde::{Serialize, Deserialize};
7
8use crate::rcs::{Position, WorldObj, PointRef, Point};
9
10#[derive(Clone, Debug, Serialize, Deserialize)]
11struct PositionDes {
12    pub pos : [f32; 3],
13    pub ori : Option<[[f32; 3]; 3]>
14}
15
16impl From<Position> for PositionDes {
17    fn from(pos : Position) -> Self {
18        PositionDes { 
19            pos: pos.pos.to_array(), 
20            ori: Some(pos.ori.to_cols_array_2d())
21        }
22    }
23}
24
25impl Into<Position> for PositionDes {
26    fn into(self) -> Position {
27        if let Some(ori) = &self.ori {
28            Position::new_ori(
29                Vec3::from(self.pos),
30                Mat3::from_cols_array_2d(ori)
31            )
32        } else {
33            Position::from_vec3(
34                Vec3::from(self.pos)
35            )
36        }
37    }
38}
39
40impl Serialize for Position {
41    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42        where
43            S: serde::Serializer {
44        let pos = PositionDes::from(self.clone());
45        pos.serialize(serializer)
46    }
47}
48
49impl<'de> Deserialize<'de> for Position {
50    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51        where
52            D: serde::Deserializer<'de> {   
53        Ok(PositionDes::deserialize(deserializer)?.into())
54    }
55}
56
57#[derive(Serialize, Deserialize)]
58#[serde(untagged)]
59enum PointEnum {
60    Pos { ori : Option<[[f32; 3]; 3]>, pos : [f32; 3] }, 
61    Wo { pos : Position, sub : HashMap<String, PointRef> },
62    WoDir { pos: [f32; 3], sub : HashMap<String, PointRef> }
63}
64
65impl From<PointRef> for PointEnum {
66    fn from(value: PointRef) -> Self {
67        let poi = value.borrow();
68
69        if let Some(wo) = poi.as_wo() {
70            if wo.pos.ori == Mat3::IDENTITY {
71                Self::WoDir { pos: wo.pos.pos().to_array(), sub: wo.sub.clone() }
72            } else {
73                Self::Wo { pos: wo.pos.clone(), sub: wo.sub.clone() }
74            }
75        } else if let Some(pos) = poi.as_pos() {
76            if pos.ori == Mat3::IDENTITY {
77                Self::Pos { pos: pos.pos.to_array(), ori: None }
78            } else {
79                Self::Pos { ori: Some(pos.ori.to_cols_array_2d()), pos: pos.pos.to_array() }
80            }
81        } else {
82            panic!("Bad implementation of the trait 'Point'!")
83        }
84    }
85}
86
87impl Serialize for PointRef {
88    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89        where
90            S: serde::Serializer {
91        PointEnum::from(self.clone()).serialize(serializer)
92    }
93}
94
95impl<'de> Deserialize<'de> for PointRef {
96    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
97        where
98            D: serde::Deserializer<'de> {
99        let point = PointEnum::deserialize(deserializer)?;
100        
101        Ok(match point {
102            PointEnum::Pos { ori, pos } => 
103                PointRef(Rc::new(RefCell::new(Position::new_ori(Vec3::from(pos), if let Some(o) = &ori {
104                    Mat3::from_cols_array_2d(o)
105                } else {
106                    Mat3::IDENTITY
107                })))),
108            PointEnum::Wo { pos, sub } => 
109                PointRef(Rc::new(RefCell::new(WorldObj::from_pos_sub(pos, sub)))),
110            PointEnum::WoDir { pos, sub } => 
111                PointRef(Rc::new(RefCell::new(WorldObj::from_pos_sub(Position::from_vec3(Vec3::from(pos)), sub))))
112        })
113    }
114}