1use chrono::Utc;
20use serde::{Deserialize, Deserializer, Serialize};
21use serde_json;
22use std::io::Read;
23use urlencoding;
24use validator::Validate;
25
26const ROTATION_DET_EPS: f64 = 0.005;
28
29pub fn is_rotation_matrix(t: &[f64]) -> bool {
36 let &[a00, a10, a20, a01, a11, a21, a02, a12, a22] = t else {
37 return false;
38 };
39 let det = a00 * (a11 * a22 - a12 * a21) - a01 * (a10 * a22 - a12 * a20)
40 + a02 * (a10 * a21 - a11 * a20);
41 (det.abs() - 1.0).abs() <= ROTATION_DET_EPS
42}
43
44#[derive(PartialEq, Serialize, Deserialize, Debug, Default, Clone)]
49#[serde(rename_all = "snake_case")]
50pub enum KindT {
51 #[default]
52 Root,
53 Camera,
54 Canvas,
55 Color,
56 ColorFromSource,
57 ColorFromUri,
58 Component,
59 ComponentFromSource,
60 ComponentFromUri,
61 Download,
62 Focus,
63 GenericVisuals,
64 Label,
65 LabelFromSource,
66 LabelFromUri,
67 Line,
68 Parse,
69 Representation,
70 Sphere,
71 Structure,
72 Tooltip,
73 TooltipFromSource,
74 TooltipFromUri,
75 Transform,
76 Volume,
77 VolumeRepresentation,
78}
79
80#[derive(Serialize, Deserialize, Debug, Clone)]
85#[serde(untagged)]
86pub enum NodeParams {
87 DownloadParams(DownloadParams),
88 ParseParams(ParseParams),
89 StructureParams(StructureParams),
90 RepresentationParams(RepresentationParams),
91 DataFromUriParams(DataFromUriParams),
92 DataFromSourceParams(DataFromSourceParams),
93 ComponentInlineParams(ComponentInlineParams),
94 ComponentFromUriParams(ComponentFromUriParams),
95 ComponentFromSourceParams(ComponentFromSourceParams),
96 ColorInlineParams(ColorInlineParams),
97 ColorFromUriParams(ColorFromUriParams),
98 ColorFromSourceParams(ColorFromSourceParams),
99 LabelInlineParams(LabelInlineParams),
100 LabelFromUriParams(LabelFromUriParams),
101 LabelFromSourceParams(LabelFromSourceParams),
102 TooltipInlineParams(TooltipInlineParams),
103 TooltipFromUriParams(TooltipFromUriParams),
104 TooltipFromSourceParams(TooltipFromSourceParams),
105 FocusInlineParams(FocusInlineParams),
106 TransformParams(TransformParams),
107 CameraParams(CameraParams),
108 CanvasParams(CanvasParams),
109 SphereParams(SphereParams),
110 LineParams(LineParams),
111 VolumeParams(VolumeParams),
112 VolumeRepresentationParams(VolumeRepresentationParams),
113}
114
115fn deserialize_children<'de, D>(deserializer: D) -> Result<Option<Vec<Node>>, D::Error>
118where
119 D: serde::Deserializer<'de>,
120{
121 let opt = Option::<Vec<Node>>::deserialize(deserializer)?;
122 Ok(opt.filter(|v| !v.is_empty()))
123}
124
125#[derive(Serialize, Debug, Default, Clone)]
132pub struct Node {
133 pub kind: KindT,
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub params: Option<NodeParams>,
136 #[serde(
137 skip_serializing_if = "Option::is_none",
138 deserialize_with = "deserialize_children",
139 default
140 )]
141 pub children: Option<Vec<Node>>,
142}
143impl Node {
144 pub fn new(kind: KindT, params: Option<NodeParams>) -> Node {
146 Node {
147 kind,
148 params,
149 children: None,
150 }
151 }
152 pub fn add_child(&mut self, node: Node) {
153 match &mut self.children {
154 Some(children) => children.push(node),
155 None => self.children = Some(vec![node]),
156 }
157 }
158 pub fn get_kind(&self) -> &KindT {
159 &self.kind
160 }
161 pub fn download(&mut self, url: &str) -> Option<&mut Node> {
163 if self.kind == KindT::Root {
164 let url = url.to_string();
165 let download_node = Node::new(
166 KindT::Download,
167 Some(NodeParams::DownloadParams(DownloadParams { url })),
168 );
169
170 self.children
171 .get_or_insert_with(Vec::new)
172 .push(download_node);
173 self.children.as_mut().unwrap().last_mut()
174 } else {
175 None
176 }
177 }
178 pub fn parse(&mut self, params: ParseParams) -> Option<&mut Node> {
180 if self.kind == KindT::Download {
181 let parse_node = Node::new(KindT::Parse, Some(NodeParams::ParseParams(params)));
182 self.children.get_or_insert_with(Vec::new).push(parse_node);
183 self.children.as_mut().unwrap().last_mut()
184 } else {
185 None
186 }
187 }
188
189 pub fn model_structure(&mut self, params: StructureParams) -> Option<&mut Node> {
193 if self.kind == KindT::Parse {
194 let struct_node =
195 Node::new(KindT::Structure, Some(NodeParams::StructureParams(params)));
196 self.children.get_or_insert_with(Vec::new).push(struct_node);
197 self.children.as_mut().unwrap().last_mut()
198 } else {
199 None
200 }
201 }
202 pub fn assembly_structure(&mut self, params: StructureParams) -> Option<&mut Node> {
204 if self.kind == KindT::Parse {
205 let struct_node =
206 Node::new(KindT::Structure, Some(NodeParams::StructureParams(params)));
207 self.children.get_or_insert_with(Vec::new).push(struct_node);
208 self.children.as_mut().unwrap().last_mut()
209 } else {
210 None
211 }
212 }
213 pub fn symmetry_structure(&mut self, params: StructureParams) -> Option<&mut Node> {
215 if self.kind == KindT::Parse {
217 let struct_node =
218 Node::new(KindT::Structure, Some(NodeParams::StructureParams(params)));
219 self.children.get_or_insert_with(Vec::new).push(struct_node);
220 self.children.as_mut().unwrap().last_mut()
221 } else {
222 None
223 }
224 }
225
226 pub fn symmetry_mates_structure(&mut self, params: StructureParams) -> Option<&mut Node> {
228 if self.kind == KindT::Parse {
230 let struct_node =
231 Node::new(KindT::Structure, Some(NodeParams::StructureParams(params)));
232 self.children.get_or_insert_with(Vec::new).push(struct_node);
233 self.children.as_mut().unwrap().last_mut()
234 } else {
235 None
236 }
237 }
238
239 pub fn volume(&mut self, params: VolumeParams) -> Option<&mut Node> {
241 if self.kind == KindT::Parse {
242 let volume_node = Node::new(KindT::Volume, Some(NodeParams::VolumeParams(params)));
243 self.children.get_or_insert_with(Vec::new).push(volume_node);
244 self.children.as_mut().unwrap().last_mut()
245 } else {
246 None
247 }
248 }
249
250 pub fn volume_representation(
254 &mut self,
255 params: VolumeRepresentationParams,
256 ) -> Option<&mut Node> {
257 if self.kind == KindT::Volume {
258 let node = Node::new(
259 KindT::VolumeRepresentation,
260 Some(NodeParams::VolumeRepresentationParams(params)),
261 );
262 self.children.get_or_insert_with(Vec::new).push(node);
263 self.children.as_mut().unwrap().last_mut()
264 } else {
265 None
266 }
267 }
268
269 pub fn component(&mut self, selector: ComponentSelector) -> Option<&mut Node> {
273 if self.kind == KindT::Structure {
274 let component_node = match selector {
275 ComponentSelector::Selector(sel) => Node::new(
276 KindT::Component,
277 Some(NodeParams::ComponentInlineParams(ComponentInlineParams {
278 selector: ComponentSelector::Selector(sel),
279 })),
280 ),
281 ComponentSelector::Expression(expr) => Node::new(
287 KindT::Component,
288 Some(NodeParams::ComponentInlineParams(ComponentInlineParams {
289 selector: ComponentSelector::Expression(expr),
290 })),
291 ),
292 ComponentSelector::ExpressionList(expr_list) => Node::new(
293 KindT::Component,
294 Some(NodeParams::ComponentInlineParams(ComponentInlineParams {
295 selector: ComponentSelector::ExpressionList(expr_list),
296 })),
297 ),
298 };
299 self.children
300 .get_or_insert_with(Vec::new)
301 .push(component_node);
302 self.children.as_mut().unwrap().last_mut()
303 } else {
304 None
305 }
306 }
307 pub fn component_from_uri(&mut self, params: ComponentFromUriParams) -> Option<&mut Node> {
308 if self.kind == KindT::Structure {
309 let node = Node::new(
310 KindT::ComponentFromUri,
311 Some(NodeParams::ComponentFromUriParams(params)),
312 );
313 self.children.get_or_insert_with(Vec::new).push(node);
314 self.children.as_mut().unwrap().last_mut()
315 } else {
316 None
317 }
318 }
319 pub fn component_from_source(
320 &mut self,
321 params: ComponentFromSourceParams,
322 ) -> Option<&mut Node> {
323 if self.kind == KindT::Structure {
324 let node = Node::new(
325 KindT::ComponentFromSource,
326 Some(NodeParams::ComponentFromSourceParams(params)),
327 );
328 self.children.get_or_insert_with(Vec::new).push(node);
329 self.children.as_mut().unwrap().last_mut()
330 } else {
331 None
332 }
333 }
334 pub fn label_from_uri(&mut self, params: LabelFromUriParams) -> Option<&mut Node> {
336 self.push_structure_child(KindT::LabelFromUri, NodeParams::LabelFromUriParams(params))
337 }
338
339 pub fn label_from_source(&mut self, params: LabelFromSourceParams) -> Option<&mut Node> {
341 self.push_structure_child(
342 KindT::LabelFromSource,
343 NodeParams::LabelFromSourceParams(params),
344 )
345 }
346
347 pub fn tooltip_from_uri(&mut self, params: TooltipFromUriParams) -> Option<&mut Node> {
349 self.push_structure_child(
350 KindT::TooltipFromUri,
351 NodeParams::TooltipFromUriParams(params),
352 )
353 }
354
355 pub fn tooltip_from_source(&mut self, params: TooltipFromSourceParams) -> Option<&mut Node> {
357 self.push_structure_child(
358 KindT::TooltipFromSource,
359 NodeParams::TooltipFromSourceParams(params),
360 )
361 }
362
363 fn push_structure_child(&mut self, kind: KindT, params: NodeParams) -> Option<&mut Node> {
365 if self.kind != KindT::Structure {
366 return None;
367 }
368 let children = self.children.get_or_insert_with(Vec::new);
369 children.push(Node::new(kind, Some(params)));
370 children.last_mut()
371 }
372
373 pub fn transform(&mut self, params: TransformParams) -> Option<&mut Node> {
379 if let Some(rotation) = ¶ms.rotation
380 && !rotation.is_empty()
381 && !is_rotation_matrix(rotation)
382 {
383 return None;
384 }
385 if self.kind == KindT::Structure {
386 let transform_node =
387 Node::new(KindT::Transform, Some(NodeParams::TransformParams(params)));
388 self.children
389 .get_or_insert_with(Vec::new)
390 .push(transform_node);
391 self.children.as_mut().unwrap().last_mut()
392 } else {
393 None
394 }
395 }
396 pub fn representation(
402 &mut self,
403 representation_type: RepresentationTypeT,
404 ) -> Option<&mut Node> {
405 self.representation_with_theme(representation_type, None)
406 }
407
408 pub fn representation_with_theme(
409 &mut self,
410 representation_type: RepresentationTypeT,
411 color_theme: Option<ColorThemeT>,
412 ) -> Option<&mut Node> {
413 if self.kind == KindT::Component {
414 let representation_node = Node::new(
415 KindT::Representation,
416 Some(NodeParams::RepresentationParams(RepresentationParams {
417 representation_type,
418 color_theme,
419 })),
420 );
421 self.children
422 .get_or_insert_with(Vec::new)
423 .push(representation_node);
424 self.children.as_mut().unwrap().last_mut()
425 } else {
426 None
427 }
428 }
429
430 pub fn label(&mut self, label: String) -> Option<&mut Node> {
431 if self.kind == KindT::Component {
432 let label_node = Node::new(
433 KindT::Label,
434 Some(NodeParams::LabelInlineParams(LabelInlineParams {
435 text: label,
436 })),
437 );
438 self.children.get_or_insert_with(Vec::new).push(label_node);
439 self.children.as_mut().unwrap().last_mut()
440 } else {
441 None
442 }
443 }
444 pub fn tooltip(&mut self, text: String) -> Option<&mut Node> {
445 if self.kind == KindT::Component {
446 let node = Node::new(
447 KindT::Tooltip,
448 Some(NodeParams::TooltipInlineParams(TooltipInlineParams {
449 text,
450 })),
451 );
452 self.children.get_or_insert_with(Vec::new).push(node);
453 self.children.as_mut().unwrap().last_mut()
454 } else {
455 None
456 }
457 }
458 pub fn focus(
459 &mut self,
460 direction: Option<(f64, f64, f64)>,
461 up: Option<(f64, f64, f64)>,
462 ) -> Option<&mut Node> {
463 if self.kind == KindT::Component {
464 let node = Node::new(
465 KindT::Focus,
466 Some(NodeParams::FocusInlineParams(FocusInlineParams {
467 direction,
468 up,
469 })),
470 );
471 self.children.get_or_insert_with(Vec::new).push(node);
472 self.children.as_mut().unwrap().last_mut()
473 } else {
474 None
475 }
476 }
477
478 pub fn color_from_source(&mut self, params: ColorFromSourceParams) -> Option<&mut Node> {
481 if self.kind == KindT::Representation {
482 let node = Node::new(
483 KindT::ColorFromSource,
484 Some(NodeParams::ColorFromSourceParams(params)),
485 );
486 self.children.get_or_insert_with(Vec::new).push(node);
487 self.children.as_mut().unwrap().last_mut()
488 } else {
489 None
490 }
491 }
492 pub fn color_from_uri(&mut self, params: ColorFromUriParams) -> Option<&mut Node> {
493 if self.kind == KindT::Representation {
494 let node = Node::new(
495 KindT::ColorFromUri,
496 Some(NodeParams::ColorFromUriParams(params)),
497 );
498 self.children.get_or_insert_with(Vec::new).push(node);
499 self.children.as_mut().unwrap().last_mut()
500 } else {
501 None
502 }
503 }
504 pub fn color(&mut self, color: ColorT, selector: ComponentSelector) -> Option<&mut Node> {
507 if self.kind == KindT::Representation {
508 let color_node = Node::new(
509 KindT::Color,
510 Some(NodeParams::ColorInlineParams(ColorInlineParams {
511 base: ComponentInlineParams { selector },
512 color,
513 })),
514 );
515 self.children.get_or_insert_with(Vec::new).push(color_node);
516 self.children.as_mut().unwrap().last_mut()
517 } else {
518 None
519 }
520 }
521
522 pub fn sphere(&mut self, params: SphereParams) -> Option<&mut Node> {
524 if self.kind == KindT::GenericVisuals {
525 let node = Node::new(KindT::Sphere, Some(NodeParams::SphereParams(params)));
526 self.children.get_or_insert_with(Vec::new).push(node);
527 self.children.as_mut().unwrap().last_mut()
528 } else {
529 None
530 }
531 }
532 pub fn line(&mut self, params: LineParams) -> Option<&mut Node> {
533 if self.kind == KindT::GenericVisuals {
534 let node = Node::new(KindT::Line, Some(NodeParams::LineParams(params)));
535 self.children.get_or_insert_with(Vec::new).push(node);
536 self.children.as_mut().unwrap().last_mut()
537 } else {
538 None
539 }
540 }
541}
542
543impl<'de> Deserialize<'de> for Node {
544 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
545 #[derive(Deserialize)]
546 struct NodeHelper {
547 kind: KindT,
548 #[serde(default)]
549 params: Option<serde_json::Value>,
550 #[serde(default, deserialize_with = "deserialize_children")]
551 children: Option<Vec<Node>>,
552 }
553
554 let helper = NodeHelper::deserialize(deserializer)?;
555
556 let params = match helper.params {
557 None | Some(serde_json::Value::Null) => None,
559 Some(v) => {
560 let p: NodeParams = match &helper.kind {
561 KindT::Download => {
562 serde_json::from_value::<DownloadParams>(v).map(NodeParams::DownloadParams)
563 }
564 KindT::Parse => {
565 serde_json::from_value::<ParseParams>(v).map(NodeParams::ParseParams)
566 }
567 KindT::Structure => serde_json::from_value::<StructureParams>(v)
568 .map(NodeParams::StructureParams),
569 KindT::Representation => serde_json::from_value::<RepresentationParams>(v)
570 .map(NodeParams::RepresentationParams),
571 KindT::Component => serde_json::from_value::<ComponentInlineParams>(v)
572 .map(NodeParams::ComponentInlineParams),
573 KindT::ComponentFromUri => serde_json::from_value::<ComponentFromUriParams>(v)
574 .map(NodeParams::ComponentFromUriParams),
575 KindT::ComponentFromSource => {
576 serde_json::from_value::<ComponentFromSourceParams>(v)
577 .map(NodeParams::ComponentFromSourceParams)
578 }
579 KindT::Color => serde_json::from_value::<ColorInlineParams>(v)
580 .map(NodeParams::ColorInlineParams),
581 KindT::ColorFromUri => serde_json::from_value::<ColorFromUriParams>(v)
582 .map(NodeParams::ColorFromUriParams),
583 KindT::ColorFromSource => serde_json::from_value::<ColorFromSourceParams>(v)
584 .map(NodeParams::ColorFromSourceParams),
585 KindT::Label => serde_json::from_value::<LabelInlineParams>(v)
586 .map(NodeParams::LabelInlineParams),
587 KindT::LabelFromUri => serde_json::from_value::<LabelFromUriParams>(v)
588 .map(NodeParams::LabelFromUriParams),
589 KindT::LabelFromSource => serde_json::from_value::<LabelFromSourceParams>(v)
590 .map(NodeParams::LabelFromSourceParams),
591 KindT::Tooltip => serde_json::from_value::<TooltipInlineParams>(v)
592 .map(NodeParams::TooltipInlineParams),
593 KindT::TooltipFromUri => serde_json::from_value::<TooltipFromUriParams>(v)
594 .map(NodeParams::TooltipFromUriParams),
595 KindT::TooltipFromSource => {
596 serde_json::from_value::<TooltipFromSourceParams>(v)
597 .map(NodeParams::TooltipFromSourceParams)
598 }
599 KindT::Focus => serde_json::from_value::<FocusInlineParams>(v)
600 .map(NodeParams::FocusInlineParams),
601 KindT::Transform => serde_json::from_value::<TransformParams>(v)
602 .map(NodeParams::TransformParams),
603 KindT::Camera => {
604 serde_json::from_value::<CameraParams>(v).map(NodeParams::CameraParams)
605 }
606 KindT::Canvas => {
607 serde_json::from_value::<CanvasParams>(v).map(NodeParams::CanvasParams)
608 }
609 KindT::Sphere => {
610 serde_json::from_value::<SphereParams>(v).map(NodeParams::SphereParams)
611 }
612 KindT::Line => {
613 serde_json::from_value::<LineParams>(v).map(NodeParams::LineParams)
614 }
615 KindT::Volume => {
616 serde_json::from_value::<VolumeParams>(v).map(NodeParams::VolumeParams)
617 }
618 KindT::VolumeRepresentation => {
619 serde_json::from_value::<VolumeRepresentationParams>(v)
620 .map(NodeParams::VolumeRepresentationParams)
621 }
622 KindT::Root | KindT::GenericVisuals => {
624 return Ok(Node {
625 kind: helper.kind,
626 params: None,
627 children: helper.children,
628 });
629 }
630 }
631 .map_err(|e| serde::de::Error::custom(e.to_string()))?;
632 Some(p)
633 }
634 };
635
636 Ok(Node {
637 kind: helper.kind,
638 params,
639 children: helper.children,
640 })
641 }
642}
643
644#[derive(Serialize, Deserialize, Debug, Clone)]
645#[serde(rename_all = "snake_case")]
646pub enum DescriptionFormatT {
647 Markdown,
648 Plaintext,
649}
650
651#[derive(Serialize, Deserialize, Debug, Default)]
657pub struct Metadata {
658 pub version: String,
659 #[serde(skip_serializing_if = "Option::is_none")]
660 pub title: Option<String>,
661 #[serde(skip_serializing_if = "Option::is_none")]
662 pub description: Option<String>,
663 #[serde(skip_serializing_if = "Option::is_none")]
664 pub description_format: Option<DescriptionFormatT>,
665 pub timestamp: String,
666}
667
668#[derive(Serialize, Deserialize, Debug)]
674pub struct State {
675 pub root: Node,
676 pub metadata: Metadata,
677}
678impl Default for State {
679 fn default() -> Self {
680 Self::new()
681 }
682}
683
684impl State {
685 pub fn new() -> Self {
686 State {
687 root: Node::new(KindT::Root, None),
688 metadata: Metadata {
689 version: "1.0".to_string(),
690 timestamp: Utc::now().to_rfc3339().to_string(),
691 ..Default::default()
692 },
693 }
694 }
695
696 #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> serde_json::Result<State> {
699 serde_json::from_str(s)
700 }
701
702 pub fn from_reader<R: Read>(reader: R) -> serde_json::Result<State> {
704 serde_json::from_reader(reader)
705 }
706
707 pub fn camera(&mut self, params: CameraParams) -> Option<&mut Node> {
709 if self.root.kind == KindT::Root {
710 let camera_node = Node::new(KindT::Camera, Some(NodeParams::CameraParams(params)));
711 self.root
712 .children
713 .get_or_insert_with(Vec::new)
714 .push(camera_node);
715 self.root.children.as_mut().unwrap().last_mut()
716 } else {
717 None
718 }
719 }
720
721 pub fn canvas(&mut self, params: CanvasParams) -> Option<&mut Node> {
723 if self.root.kind == KindT::Root {
724 let node = Node::new(KindT::Canvas, Some(NodeParams::CanvasParams(params)));
725 self.root.children.get_or_insert_with(Vec::new).push(node);
726 self.root.children.as_mut().unwrap().last_mut()
727 } else {
728 None
729 }
730 }
731
732 pub fn download(&mut self, url: &str) -> Option<&mut Node> {
734 self.root.download(url)
735 }
736
737 pub fn generic_visuals(&mut self) -> Option<&mut Node> {
739 if self.root.kind == KindT::Root {
740 let node = Node::new(KindT::GenericVisuals, None);
741 self.root.children.get_or_insert_with(Vec::new).push(node);
742 self.root.children.as_mut().unwrap().last_mut()
743 } else {
744 None
745 }
746 }
747
748 pub fn into_snapshot(self) -> Snapshot {
750 Snapshot {
751 root: self.root,
752 title: None,
753 description: None,
754 description_format: None,
755 key: None,
756 linger_duration_ms: None,
757 transition_duration_ms: None,
758 }
759 }
760
761 pub fn to_url(&self) -> String {
762 let json = serde_json::to_string(&self).expect("Json conversion");
763 let encoded = urlencoding::encode(&json);
764 format!(
765 "https://molstar.org/viewer/?mvs-format=mvsj&mvs-data={}",
766 encoded
767 )
768 }
769}
770
771#[derive(Serialize, Deserialize, Debug, Clone)]
778pub struct Snapshot {
779 pub root: Node,
780 #[serde(skip_serializing_if = "Option::is_none")]
781 pub title: Option<String>,
782 #[serde(skip_serializing_if = "Option::is_none")]
783 pub description: Option<String>,
784 #[serde(skip_serializing_if = "Option::is_none")]
785 pub description_format: Option<DescriptionFormatT>,
786 #[serde(skip_serializing_if = "Option::is_none")]
787 pub key: Option<String>,
788 #[serde(skip_serializing_if = "Option::is_none")]
789 pub linger_duration_ms: Option<u64>,
790 #[serde(skip_serializing_if = "Option::is_none")]
791 pub transition_duration_ms: Option<u64>,
792}
793
794#[derive(Serialize, Deserialize, Debug)]
800pub struct MvsjFile {
801 pub metadata: Metadata,
802 pub snapshots: Vec<Snapshot>,
803}
804impl MvsjFile {
805 #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> serde_json::Result<MvsjFile> {
808 serde_json::from_str(s)
809 }
810
811 pub fn from_reader<R: Read>(reader: R) -> serde_json::Result<MvsjFile> {
813 serde_json::from_reader(reader)
814 }
815}
816
817#[derive(Serialize, Deserialize, Debug, Clone)]
819#[serde(rename_all = "lowercase")]
820pub enum ParseFormatT {
821 Mmcif,
822 Bcif,
823 Pdb,
824}
825
826#[derive(Serialize, Deserialize, Debug, Clone)]
827#[serde(rename = "parse")]
828pub struct ParseParams {
829 pub format: ParseFormatT,
830}
831
832#[derive(Serialize, Deserialize, Debug, Clone)]
834#[serde(rename_all = "snake_case")]
835#[derive(Default)]
836pub enum StructureTypeT {
837 Model,
838 #[default]
839 Assembly,
840 Symmetry,
841 SymmetryMates,
842}
843
844#[derive(Serialize, Deserialize, Debug, Clone, Default)]
846pub struct StructureParams {
847 #[serde(rename = "type")]
848 pub structure_type: StructureTypeT,
849 #[serde(skip_serializing_if = "Option::is_none")]
850 pub assembly_id: Option<String>,
851 #[serde(skip_serializing_if = "Option::is_none")]
852 pub assembly_index: Option<i32>,
853 #[serde(skip_serializing_if = "Option::is_none")]
854 pub model_index: Option<i32>,
855 #[serde(skip_serializing_if = "Option::is_none")]
856 pub block_index: Option<i32>,
857 #[serde(skip_serializing_if = "Option::is_none")]
858 pub block_header: Option<String>,
859 #[serde(skip_serializing_if = "Option::is_none")]
860 pub radius: Option<f64>,
861 #[serde(skip_serializing_if = "Option::is_none")]
862 pub ijk_min: Option<(i32, i32, i32)>,
863 #[serde(skip_serializing_if = "Option::is_none")]
864 pub ijk_max: Option<(i32, i32, i32)>,
865}
866
867#[derive(Serialize, Deserialize, Debug, Clone)]
872#[serde(rename_all = "snake_case")]
873pub enum ComponentSelectorT {
874 All,
875 Polymer,
876 Protein,
877 Nucleic,
878 Branched,
879 Ligand,
880 Ion,
881 Water,
882}
883#[derive(Serialize, Deserialize, Debug, Clone, Default)]
885pub struct ComponentExpression {
886 #[serde(skip_serializing_if = "Option::is_none")]
887 pub label_entity_id: Option<String>,
888 #[serde(skip_serializing_if = "Option::is_none")]
889 pub label_asym_id: Option<String>,
890 #[serde(skip_serializing_if = "Option::is_none")]
891 pub auth_asym_id: Option<String>,
892 #[serde(skip_serializing_if = "Option::is_none")]
893 pub label_seq_id: Option<i32>,
894 #[serde(skip_serializing_if = "Option::is_none")]
895 pub auth_seq_id: Option<i32>,
896 #[serde(skip_serializing_if = "Option::is_none")]
897 pub pdbx_pdb_ins_code: Option<String>,
898 #[serde(skip_serializing_if = "Option::is_none")]
899 pub beg_label_seq_id: Option<i32>,
900 #[serde(skip_serializing_if = "Option::is_none")]
901 pub end_label_seq_id: Option<i32>,
902 #[serde(skip_serializing_if = "Option::is_none")]
903 pub beg_auth_seq_id: Option<i32>,
904 #[serde(skip_serializing_if = "Option::is_none")]
905 pub end_auth_seq_id: Option<i32>,
906 #[serde(skip_serializing_if = "Option::is_none")]
907 pub residue_index: Option<i32>,
908 #[serde(skip_serializing_if = "Option::is_none")]
909 pub label_atom_id: Option<String>,
910 #[serde(skip_serializing_if = "Option::is_none")]
911 pub auth_atom_id: Option<String>,
912 #[serde(skip_serializing_if = "Option::is_none")]
913 pub type_symbol: Option<String>,
914 #[serde(skip_serializing_if = "Option::is_none")]
915 pub atom_id: Option<i32>,
916 #[serde(skip_serializing_if = "Option::is_none")]
917 pub atom_index: Option<i32>,
918}
919
920#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
922#[serde(rename_all = "snake_case")]
923pub enum RepresentationTypeT {
924 BallAndStick,
925 Cartoon,
926 Line,
928 Putty,
930 Spacefill,
932 Surface,
933}
934
935#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
940#[serde(rename_all = "snake_case")]
941pub enum ColorThemeT {
942 #[default]
944 ElementSymbol,
945 ChainId,
947 SecondaryStructure,
949 Uniform,
951 Uncertainty,
954 PlddtConfidence,
957 Occupancy,
960}
961
962#[derive(Serialize, Deserialize, Debug, Clone)]
964#[serde(rename_all = "lowercase")]
965pub enum ColorNamesT {
966 Aliceblue,
967 Antiquewhite,
968 Aqua,
969 Aquamarine,
970 Azure,
971 Beige,
972 Bisque,
973 Black,
974 Blanchedalmond,
975 Blue,
976 Blueviolet,
977 Brown,
978 Burlywood,
979 Cadetblue,
980 Chartreuse,
981 Chocolate,
982 Coral,
983 Cornflowerblue,
984 Cornsilk,
985 Crimson,
986 Cyan,
987 Darkblue,
988 Darkcyan,
989 Darkgoldenrod,
990 Darkgray,
991 Darkgreen,
992 Darkgrey,
993 Darkkhaki,
994 Darkmagenta,
995 Darkolivegreen,
996 Darkorange,
997 Darkorchid,
998 Darkred,
999 Darksalmon,
1000 Darkseagreen,
1001 Darkslateblue,
1002 Darkslategray,
1003 Darkslategrey,
1004 Darkturquoise,
1005 Darkviolet,
1006 Deeppink,
1007 Deepskyblue,
1008 Dimgray,
1009 Dimgrey,
1010 Dodgerblue,
1011 Firebrick,
1012 Floralwhite,
1013 Forestgreen,
1014 Fuchsia,
1015 Gainsboro,
1016 Ghostwhite,
1017 Gold,
1018 Goldenrod,
1019 Gray,
1020 Green,
1021 Greenyellow,
1022 Grey,
1023 Honeydew,
1024 Hotpink,
1025 Indianred,
1026 Indigo,
1027 Ivory,
1028 Khaki,
1029 Lavender,
1030 Lavenderblush,
1031 Lawngreen,
1032 Lemonchiffon,
1033 Lightblue,
1034 Lightcoral,
1035 Lightcyan,
1036 Lightgoldenrodyellow,
1037 Lightgray,
1038 Lightgreen,
1039 Lightgrey,
1040 Lightpink,
1041 Lightsalmon,
1042 Lightseagreen,
1043 Lightskyblue,
1044 Lightslategray,
1045 Lightslategrey,
1046 Lightsteelblue,
1047 Lightyellow,
1048 Lime,
1049 Limegreen,
1050 Linen,
1051 Magenta,
1052 Maroon,
1053 Mediumaquamarine,
1054 Mediumblue,
1055 Mediumorchid,
1056 Mediumpurple,
1057 Mediumseagreen,
1058 Mediumslateblue,
1059 Mediumspringgreen,
1060 Mediumturquoise,
1061 Mediumvioletred,
1062 Midnightblue,
1063 Mintcream,
1064 Mistyrose,
1065 Moccasin,
1066 Navajowhite,
1067 Navy,
1068 Oldlace,
1069 Olive,
1070 Olivedrab,
1071 Orange,
1072 Orangered,
1073 Orchid,
1074 Palegoldenrod,
1075 Palegreen,
1076 Paleturquoise,
1077 Palevioletred,
1078 Papayawhip,
1079 Peachpuff,
1080 Peru,
1081 Pink,
1082 Plum,
1083 Powderblue,
1084 Purple,
1085 Red,
1086 Rosybrown,
1087 Royalblue,
1088 Saddlebrown,
1089 Salmon,
1090 Sandybrown,
1091 Seagreen,
1092 Seashell,
1093 Sienna,
1094 Silver,
1095 Skyblue,
1096 Slateblue,
1097 Slategray,
1098 Slategrey,
1099 Snow,
1100 Springgreen,
1101 Steelblue,
1102 Tan,
1103 Teal,
1104 Thistle,
1105 Tomato,
1106 Turquoise,
1107 Violet,
1108 Wheat,
1109 White,
1110 Whitesmoke,
1111 Yellow,
1112 Yellowgreen,
1113}
1114
1115#[derive(Serialize, Deserialize, Debug, Clone)]
1117#[serde(untagged)]
1118pub enum ColorT {
1119 Named(ColorNamesT),
1120 Hex(String),
1121}
1122
1123#[derive(Serialize, Deserialize, Debug, Clone)]
1124pub struct RepresentationParams {
1125 #[serde(rename = "type")]
1126 pub representation_type: RepresentationTypeT,
1127 #[serde(skip_serializing_if = "Option::is_none")]
1130 pub color_theme: Option<ColorThemeT>,
1131}
1132
1133#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1136pub struct VolumeParams {
1137 #[serde(skip_serializing_if = "Option::is_none")]
1138 pub channel_id: Option<String>,
1139}
1140
1141#[derive(Serialize, Deserialize, Debug, Clone)]
1143#[serde(rename_all = "snake_case")]
1144pub enum VolumeRepresentationTypeT {
1145 Isosurface,
1146 GridSlice,
1147}
1148
1149#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1155pub struct IsoSurfaceParams {
1156 #[serde(skip_serializing_if = "Option::is_none")]
1157 pub isovalue: Option<f64>,
1158 #[serde(skip_serializing_if = "Option::is_none")]
1159 pub relative_isovalue: Option<f32>,
1160 #[serde(skip_serializing_if = "Option::is_none")]
1161 pub wireframe: Option<bool>,
1162 #[serde(skip_serializing_if = "Option::is_none")]
1163 pub opacity: Option<f32>,
1164}
1165
1166#[derive(Serialize, Deserialize, Debug, Clone)]
1167pub struct VolumeRepresentationParams {
1168 #[serde(rename = "type")]
1169 pub representation_type: VolumeRepresentationTypeT,
1170 #[serde(flatten)]
1171 pub isosurface: Option<IsoSurfaceParams>,
1172}
1173
1174#[derive(Serialize, Deserialize, Debug, Clone)]
1175#[serde(rename_all = "snake_case")]
1176pub enum SchemaT {
1177 WholeStructure,
1178 Entity,
1179 Chain,
1180 AuthChain,
1181 Residue,
1182 AuthResidue,
1183 ResidueRange,
1184 AuthResidueRange,
1185 Atom,
1186 AuthAtom,
1187 AllAtomic,
1188}
1189
1190#[derive(Serialize, Deserialize, Debug, Clone)]
1191#[serde(rename_all = "lowercase")]
1192pub enum SchemaFormatT {
1193 Cif,
1194 Bcif,
1195 Json,
1196}
1197
1198#[derive(Serialize, Deserialize, Debug, Clone)]
1199pub struct DataFromUriParams {
1200 pub uri: String,
1201 pub format: SchemaFormatT,
1202 #[serde(skip_serializing_if = "Option::is_none")]
1203 pub category_name: Option<String>,
1204 #[serde(skip_serializing_if = "Option::is_none")]
1205 pub field_name: Option<String>,
1206 #[serde(skip_serializing_if = "Option::is_none")]
1207 pub block_header: Option<String>,
1208 #[serde(skip_serializing_if = "Option::is_none")]
1209 pub block_index: Option<i32>,
1210 #[serde(rename = "schema")]
1211 pub schema_: SchemaT,
1212}
1213
1214#[derive(Serialize, Deserialize, Debug, Clone)]
1215pub struct DataFromSourceParams {
1216 pub category_name: String,
1217 #[serde(skip_serializing_if = "Option::is_none")]
1218 pub field_name: Option<String>,
1219 #[serde(skip_serializing_if = "Option::is_none")]
1220 pub block_header: Option<String>,
1221 #[serde(skip_serializing_if = "Option::is_none")]
1222 pub block_index: Option<i32>,
1223 #[serde(rename = "schema")]
1224 pub schema_: SchemaT,
1225}
1226
1227#[derive(Serialize, Deserialize, Debug, Clone)]
1228pub struct ComponentInlineParams {
1229 pub selector: ComponentSelector,
1230}
1231
1232#[derive(Serialize, Deserialize, Debug, Clone)]
1233#[serde(untagged)]
1234#[allow(clippy::large_enum_variant)] pub enum ComponentSelector {
1236 Selector(ComponentSelectorT),
1237 Expression(ComponentExpression),
1238 ExpressionList(Vec<ComponentExpression>),
1239}
1240impl Default for ComponentSelector {
1241 fn default() -> Self {
1242 ComponentSelector::Selector(ComponentSelectorT::All)
1243 }
1244}
1245
1246#[derive(Serialize, Deserialize, Debug, Clone)]
1247pub struct ComponentFromUriParams {
1248 #[serde(flatten)]
1249 pub base: DataFromUriParams,
1250 #[serde(skip_serializing_if = "Option::is_none")]
1251 pub field_values: Option<Vec<String>>,
1252}
1253
1254#[derive(Serialize, Deserialize, Debug, Clone)]
1255pub struct ComponentFromSourceParams {
1256 #[serde(flatten)]
1257 pub base: DataFromSourceParams,
1258 #[serde(skip_serializing_if = "Option::is_none")]
1259 pub field_values: Option<Vec<String>>,
1260}
1261
1262#[derive(Serialize, Deserialize, Debug, Clone)]
1263pub struct ColorInlineParams {
1264 #[serde(flatten)]
1265 pub base: ComponentInlineParams,
1266 pub color: ColorT,
1267}
1268
1269#[derive(Serialize, Deserialize, Debug, Clone)]
1270pub struct ColorFromUriParams {
1271 #[serde(flatten)]
1272 pub base: DataFromUriParams,
1273}
1274
1275#[derive(Serialize, Deserialize, Debug, Clone)]
1276pub struct ColorFromSourceParams {
1277 #[serde(flatten)]
1278 pub base: DataFromSourceParams,
1279}
1280
1281#[derive(Serialize, Deserialize, Debug, Clone)]
1282pub struct LabelInlineParams {
1283 pub text: String,
1284}
1285
1286#[derive(Serialize, Deserialize, Debug, Clone)]
1287pub struct LabelFromUriParams {
1288 #[serde(flatten)]
1289 pub base: DataFromUriParams,
1290}
1291
1292#[derive(Serialize, Deserialize, Debug, Clone)]
1293pub struct LabelFromSourceParams {
1294 #[serde(flatten)]
1295 pub base: DataFromSourceParams,
1296}
1297
1298#[derive(Serialize, Deserialize, Debug, Clone)]
1299pub struct TooltipInlineParams {
1300 pub text: String,
1301}
1302
1303#[derive(Serialize, Deserialize, Debug, Clone)]
1304pub struct TooltipFromUriParams {
1305 #[serde(flatten)]
1306 pub base: DataFromUriParams,
1307}
1308
1309#[derive(Serialize, Deserialize, Debug, Clone)]
1310pub struct TooltipFromSourceParams {
1311 #[serde(flatten)]
1312 pub base: DataFromSourceParams,
1313}
1314
1315#[derive(Serialize, Deserialize, Debug, Clone)]
1316pub struct FocusInlineParams {
1317 #[serde(skip_serializing_if = "Option::is_none")]
1318 pub direction: Option<(f64, f64, f64)>,
1319 #[serde(skip_serializing_if = "Option::is_none")]
1320 pub up: Option<(f64, f64, f64)>,
1321}
1322
1323#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1324pub struct TransformParams {
1325 #[serde(skip_serializing_if = "Option::is_none")]
1326 pub rotation: Option<Vec<f64>>,
1327 #[serde(skip_serializing_if = "Option::is_none")]
1328 pub translation: Option<(f64, f64, f64)>,
1329}
1330
1331#[derive(Serialize, Deserialize, Debug, Clone)]
1332pub struct SphereParams {
1333 pub position: (f64, f64, f64),
1334 pub radius: f64,
1335 pub color: ColorT,
1336 #[serde(skip_serializing_if = "Option::is_none")]
1337 pub label: Option<String>,
1338 #[serde(skip_serializing_if = "Option::is_none")]
1339 pub tooltip: Option<String>,
1340}
1341
1342#[derive(Serialize, Deserialize, Debug, Clone)]
1343pub struct LineParams {
1344 pub position1: (f64, f64, f64),
1345 pub position2: (f64, f64, f64),
1346 pub radius: f64,
1347 pub color: ColorT,
1348 #[serde(skip_serializing_if = "Option::is_none")]
1349 pub label: Option<String>,
1350 #[serde(skip_serializing_if = "Option::is_none")]
1351 pub tooltip: Option<String>,
1352}
1353
1354#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1355pub struct CameraParams {
1356 pub target: (f64, f64, f64),
1357 pub position: (f64, f64, f64),
1358 #[serde(skip_serializing_if = "Option::is_none")]
1359 pub up: Option<(f64, f64, f64)>,
1360}
1361
1362#[derive(Serialize, Deserialize, Debug, Clone)]
1363pub struct CanvasParams {
1364 pub background_color: ColorT,
1365}
1366
1367#[derive(Debug, Serialize, Deserialize, Validate, Clone)]
1368pub struct DownloadParams {
1369 pub url: String,
1370}