1use uuid::Uuid;
2
3use crate::model::{
4 dto::drawings::{
5 EllipseProperties, FreeLineProperties, ImageProperties, LabelTextProperties,
6 PolygonProperties, RectangleProperties,
7 },
8 entity::drawing_properties::{
9 BezierPolygonEntity, BezierPolygonPointEntity, EllipseEntity, FreeLineEntity,
10 FreeLinePointEntity, ImageEntity, LabelTextEntity, RectangleEntity,
11 },
12};
13pub enum DrawingVariantEntity {
14 Rectangle(RectangleEntity),
15 Ellipse(EllipseEntity),
16 FreeLine(Freeline),
17 BezierPolygon(BezierPolygon),
18 LabelText(LabelTextEntity),
19 Image(ImageEntity),
20}
21
22pub struct Freeline {
23 pub freeline_props: FreeLineEntity,
24 pub freeline_points: Vec<FreeLinePointEntity>,
25}
26
27pub struct BezierPolygon {
28 pub bezier_props: BezierPolygonEntity,
29 pub bezier_points: Vec<BezierPolygonPointEntity>,
30}
31
32#[derive(Debug)]
33pub enum ConversionError {
34 InvalidPoint,
35 IndexOutOfRange,
36}
37
38impl From<(Uuid, RectangleProperties)> for RectangleEntity {
39 fn from((drawings_id, dto): (Uuid, RectangleProperties)) -> Self {
40 Self {
41 drawings_id,
42 width: dto.width,
43 height: dto.height,
44 color: dto.color,
45 fill_pattern: dto.fill_pattern,
46 stroke_width: dto.stroke_width,
47 }
48 }
49}
50
51impl From<(Uuid, EllipseProperties)> for EllipseEntity {
52 fn from((drawings_id, dto): (Uuid, EllipseProperties)) -> Self {
53 Self {
54 drawings_id,
55 axis_x: dto.radius_x,
56 axis_y: dto.radius_y,
57 color: dto.color,
58 fill_pattern: dto.fill_pattern,
59 stroke_width: dto.stroke_width,
60 }
61 }
62}
63
64impl TryFrom<(Uuid, FreeLineProperties)> for Freeline {
65 type Error = ConversionError;
66
67 fn try_from((drawings_id, dto): (Uuid, FreeLineProperties)) -> Result<Self, Self::Error> {
68 let freeline_props = FreeLineEntity {
69 drawings_id,
70 color: dto.color,
71 fill_pattern: dto.fill_pattern,
72 stroke_width: dto.stroke_width,
73 };
74
75 let freeline_points = dto
76 .points
77 .into_iter()
78 .enumerate()
79 .map(|(idx, p)| {
80 let idx = i32::try_from(idx).map_err(|_| ConversionError::IndexOutOfRange)?;
81 match p.as_slice() {
82 [x, y] => Ok(FreeLinePointEntity {
83 id: drawings_id,
84 idx,
85 x: *x,
86 y: *y,
87 }),
88 _ => Err(ConversionError::InvalidPoint),
89 }
90 })
91 .collect::<Result<Vec<_>, _>>()?;
92 Ok(Self {
93 freeline_props,
94 freeline_points,
95 })
96 }
97}
98
99impl TryFrom<(Uuid, PolygonProperties)> for BezierPolygon {
100 type Error = ConversionError;
101
102 fn try_from((drawings_id, dto): (Uuid, PolygonProperties)) -> Result<Self, Self::Error> {
103 let bezier_props = BezierPolygonEntity {
104 drawings_id,
105 color: dto.color,
106 fill_pattern: dto.fill_pattern,
107 stroke_width: dto.stroke_width,
108 };
109
110 let bezier_points = dto
111 .points
112 .into_iter()
113 .enumerate()
114 .map(|(idx, p)| {
115 let idx = i32::try_from(idx).map_err(|_| ConversionError::IndexOutOfRange)?;
116 match p.as_slice() {
117 [x, y] => Ok(BezierPolygonPointEntity {
118 id: drawings_id,
119 idx,
120 x: *x,
121 y: *y,
122 }),
123
124 _ => Err(ConversionError::InvalidPoint),
125 }
126 })
127 .collect::<Result<Vec<_>, _>>()?;
128
129 Ok(Self {
130 bezier_props,
131 bezier_points,
132 })
133 }
134}
135
136impl From<(Uuid, LabelTextProperties)> for LabelTextEntity {
137 fn from((drawings_id, dto): (Uuid, LabelTextProperties)) -> Self {
138 Self {
139 drawings_id,
140 label_text: dto.text,
141 width: dto.width,
142 height: dto.height,
143 color: dto.color,
144 }
145 }
146}
147
148impl From<(Uuid, ImageProperties)> for ImageEntity {
149 fn from((drawings_id, dto): (Uuid, ImageProperties)) -> Self {
150 Self {
151 drawings_id,
152 file_path: dto.path,
153 }
154 }
155}
156
157impl From<RectangleEntity> for RectangleProperties {
158 fn from(p: RectangleEntity) -> Self {
159 Self {
160 width: p.width,
161 height: p.height,
162 color: p.color,
163 fill_pattern: p.fill_pattern,
164 stroke_width: p.stroke_width,
165 }
166 }
167}
168
169impl From<EllipseEntity> for EllipseProperties {
170 fn from(p: EllipseEntity) -> Self {
171 Self {
172 radius_x: p.axis_x,
173 radius_y: p.axis_y,
174 color: p.color,
175 fill_pattern: p.fill_pattern,
176 stroke_width: p.stroke_width,
177 }
178 }
179}
180
181impl From<LabelTextEntity> for LabelTextProperties {
182 fn from(p: LabelTextEntity) -> Self {
183 Self {
184 text: p.label_text,
185 width: p.width,
186 height: p.height,
187 color: p.color,
188 }
189 }
190}
191
192impl From<ImageEntity> for ImageProperties {
193 fn from(p: ImageEntity) -> Self {
194 Self { path: p.file_path }
195 }
196}
197
198impl From<Freeline> for FreeLineProperties {
199 fn from(f: Freeline) -> Self {
200 let Freeline {
201 freeline_props,
202 mut freeline_points,
203 } = f;
204
205 freeline_points.sort_by_key(|pt| pt.idx);
206
207 let points: Vec<Vec<i32>> = freeline_points
208 .into_iter()
209 .map(|pt| vec![pt.x, pt.y])
210 .collect();
211
212 Self {
213 points,
214 color: freeline_props.color,
215 fill_pattern: freeline_props.fill_pattern,
216 stroke_width: freeline_props.stroke_width,
217 }
218 }
219}
220
221impl From<BezierPolygon> for PolygonProperties {
222 fn from(b: BezierPolygon) -> Self {
223 let BezierPolygon {
224 bezier_props,
225 mut bezier_points,
226 } = b;
227
228 bezier_points.sort_by_key(|pt| pt.idx);
229
230 let points: Vec<Vec<i32>> = bezier_points
231 .into_iter()
232 .map(|pt| vec![pt.x, pt.y])
233 .collect();
234
235 Self {
236 points,
237 color: bezier_props.color,
238 fill_pattern: bezier_props.fill_pattern,
239 stroke_width: bezier_props.stroke_width,
240 }
241 }
242}