qr_code_styling/config/
options.rs1use super::{
4 BackgroundOptions, CornersDotOptions, CornersSquareOptions, DotsOptions, ImageOptions,
5 QROptions,
6};
7use crate::error::{QRError, Result};
8use crate::types::ShapeType;
9
10#[derive(Debug, Clone, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct QRCodeStylingOptions {
14 pub data: String,
16 pub width: u32,
18 pub height: u32,
20 pub margin: u32,
22 pub shape: ShapeType,
24 pub image: Option<Vec<u8>>,
26 pub qr_options: QROptions,
28 pub dots_options: DotsOptions,
30 pub corners_square_options: CornersSquareOptions,
32 pub corners_dot_options: CornersDotOptions,
34 pub background_options: BackgroundOptions,
36 pub image_options: ImageOptions,
38}
39
40impl Default for QRCodeStylingOptions {
41 fn default() -> Self {
42 Self {
43 data: String::new(),
44 width: 300,
45 height: 300,
46 margin: 0,
47 shape: ShapeType::Square,
48 image: None,
49 qr_options: QROptions::default(),
50 dots_options: DotsOptions::default(),
51 corners_square_options: CornersSquareOptions::default(),
52 corners_dot_options: CornersDotOptions::default(),
53 background_options: BackgroundOptions::default(),
54 image_options: ImageOptions::default(),
55 }
56 }
57}
58
59#[derive(Debug, Default, Clone)]
61pub struct QRCodeStylingBuilder {
62 data: Option<String>,
63 width: Option<u32>,
64 height: Option<u32>,
65 margin: Option<u32>,
66 shape: Option<ShapeType>,
67 image: Option<Vec<u8>>,
68 qr_options: Option<QROptions>,
69 dots_options: Option<DotsOptions>,
70 corners_square_options: Option<CornersSquareOptions>,
71 corners_dot_options: Option<CornersDotOptions>,
72 background_options: Option<BackgroundOptions>,
73 image_options: Option<ImageOptions>,
74}
75
76impl QRCodeStylingBuilder {
77 pub fn new() -> Self {
79 Self::default()
80 }
81
82 pub fn data(mut self, data: impl Into<String>) -> Self {
84 self.data = Some(data.into());
85 self
86 }
87
88 pub fn width(mut self, width: u32) -> Self {
90 self.width = Some(width);
91 self
92 }
93
94 pub fn height(mut self, height: u32) -> Self {
96 self.height = Some(height);
97 self
98 }
99
100 pub fn size(mut self, size: u32) -> Self {
102 self.width = Some(size);
103 self.height = Some(size);
104 self
105 }
106
107 pub fn margin(mut self, margin: u32) -> Self {
109 self.margin = Some(margin);
110 self
111 }
112
113 pub fn shape(mut self, shape: ShapeType) -> Self {
115 self.shape = Some(shape);
116 self
117 }
118
119 pub fn image(mut self, image: Vec<u8>) -> Self {
121 self.image = Some(image);
122 self
123 }
124
125 pub fn qr_options(mut self, options: QROptions) -> Self {
127 self.qr_options = Some(options);
128 self
129 }
130
131 pub fn dots_options(mut self, options: DotsOptions) -> Self {
133 self.dots_options = Some(options);
134 self
135 }
136
137 pub fn corners_square_options(mut self, options: CornersSquareOptions) -> Self {
139 self.corners_square_options = Some(options);
140 self
141 }
142
143 pub fn corners_dot_options(mut self, options: CornersDotOptions) -> Self {
145 self.corners_dot_options = Some(options);
146 self
147 }
148
149 pub fn background_options(mut self, options: BackgroundOptions) -> Self {
151 self.background_options = Some(options);
152 self
153 }
154
155 pub fn image_options(mut self, options: ImageOptions) -> Self {
157 self.image_options = Some(options);
158 self
159 }
160
161 pub(crate) fn build_options(self) -> Result<QRCodeStylingOptions> {
163 let data = self.data.ok_or(QRError::MissingData)?;
164
165 if data.is_empty() {
166 return Err(QRError::MissingData);
167 }
168
169 let width = self.width.unwrap_or(300);
170 let height = self.height.unwrap_or(300);
171
172 if width < 21 || height < 21 {
173 return Err(QRError::CanvasTooSmall { width, height });
174 }
175
176 Ok(QRCodeStylingOptions {
177 data,
178 width,
179 height,
180 margin: self.margin.unwrap_or(0),
181 shape: self.shape.unwrap_or(ShapeType::Square),
182 image: self.image,
183 qr_options: self.qr_options.unwrap_or_default(),
184 dots_options: self.dots_options.unwrap_or_default(),
185 corners_square_options: self.corners_square_options.unwrap_or_default(),
186 corners_dot_options: self.corners_dot_options.unwrap_or_default(),
187 background_options: self.background_options.unwrap_or_default(),
188 image_options: self.image_options.unwrap_or_default(),
189 })
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn test_builder_basic() {
199 let options = QRCodeStylingBuilder::new()
200 .data("https://example.com")
201 .width(400)
202 .height(400)
203 .build_options()
204 .unwrap();
205
206 assert_eq!(options.data, "https://example.com");
207 assert_eq!(options.width, 400);
208 assert_eq!(options.height, 400);
209 }
210
211 #[test]
212 fn test_builder_missing_data() {
213 let result = QRCodeStylingBuilder::new().build_options();
214 assert!(result.is_err());
215 }
216
217 #[test]
218 fn test_builder_empty_data() {
219 let result = QRCodeStylingBuilder::new().data("").build_options();
220 assert!(result.is_err());
221 }
222}