1use serde::{Deserialize, Serialize};
4
5use crate::node::{Common, IntoNode, Node};
6
7#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
9#[serde(untagged)]
10pub enum ImageSource {
11 #[serde(rename_all = "camelCase")]
13 Data {
14 data: String,
16 mime_type: String,
18 },
19 #[serde(rename_all = "camelCase")]
21 Path {
22 path: String,
24 },
25 #[serde(rename_all = "camelCase")]
27 Blob {
28 blob: String,
30 },
31}
32
33impl ImageSource {
34 #[must_use]
36 pub fn data(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
37 Self::Data {
38 data: data.into(),
39 mime_type: mime_type.into(),
40 }
41 }
42
43 #[must_use]
45 pub fn path(path: impl Into<String>) -> Self {
46 Self::Path { path: path.into() }
47 }
48
49 #[must_use]
51 pub fn blob(blob: impl Into<String>) -> Self {
52 Self::Blob { blob: blob.into() }
53 }
54
55 #[must_use]
58 pub fn decoded_len_estimate(&self) -> usize {
59 match self {
60 Self::Data { data, .. } => data.len() * 3 / 4,
61 _ => 0,
62 }
63 }
64}
65
66#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
68pub enum Fit {
69 #[default]
71 Contain,
72 Cover,
74}
75
76#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
79#[serde(rename_all = "camelCase")]
80pub struct Image {
81 #[serde(flatten)]
83 pub common: Common,
84 pub src: ImageSource,
86 pub alt: String,
88 #[serde(default, skip_serializing_if = "Option::is_none")]
90 pub fit: Option<Fit>,
91 #[serde(default, skip_serializing_if = "Option::is_none")]
93 pub max_width: Option<u16>,
94 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub max_height: Option<u16>,
97}
98
99impl Image {
100 #[must_use]
102 pub fn new(src: ImageSource, alt: impl Into<String>) -> Self {
103 Self {
104 common: Common::new(),
105 src,
106 alt: alt.into(),
107 fit: None,
108 max_width: None,
109 max_height: None,
110 }
111 }
112
113 #[must_use]
115 pub fn fit(mut self, fit: Fit) -> Self {
116 self.fit = Some(fit);
117 self
118 }
119
120 #[must_use]
122 pub fn max_width(mut self, width: u16) -> Self {
123 self.max_width = Some(width);
124 self
125 }
126
127 #[must_use]
129 pub fn max_height(mut self, height: u16) -> Self {
130 self.max_height = Some(height);
131 self
132 }
133}
134
135impl IntoNode for Image {}
136impl From<Image> for Node {
137 fn from(i: Image) -> Self {
138 Node::Image(i)
139 }
140}