1use crate::{
7 BlockFormat, BlockInfo, DocumentStats, FindMatch, FindOptions, FrameFormat, ListFormat,
8 TextFormat,
9};
10
11pub fn to_i64(v: usize) -> i64 {
14 debug_assert!(v <= i64::MAX as usize, "position overflow: {v}");
15 v as i64
16}
17
18pub fn to_usize(v: i64) -> usize {
19 assert!(v >= 0, "negative position: {v}");
20 v as usize
21}
22
23impl From<&frontend::document_inspection::DocumentStatsDto> for DocumentStats {
26 fn from(dto: &frontend::document_inspection::DocumentStatsDto) -> Self {
27 Self {
28 character_count: to_usize(dto.character_count),
29 word_count: to_usize(dto.word_count),
30 block_count: to_usize(dto.block_count),
31 frame_count: to_usize(dto.frame_count),
32 image_count: to_usize(dto.image_count),
33 list_count: to_usize(dto.list_count),
34 table_count: to_usize(dto.table_count),
35 }
36 }
37}
38
39impl From<&frontend::document_inspection::BlockInfoDto> for BlockInfo {
42 fn from(dto: &frontend::document_inspection::BlockInfoDto) -> Self {
43 Self {
44 block_id: to_usize(dto.block_id),
45 block_number: to_usize(dto.block_number),
46 start: to_usize(dto.block_start),
47 length: to_usize(dto.block_length),
48 }
49 }
50}
51
52impl FindOptions {
55 pub(crate) fn to_find_text_dto(
56 &self,
57 query: &str,
58 start_position: usize,
59 ) -> frontend::document_search::FindTextDto {
60 frontend::document_search::FindTextDto {
61 query: query.into(),
62 case_sensitive: self.case_sensitive,
63 whole_word: self.whole_word,
64 use_regex: self.use_regex,
65 search_backward: self.search_backward,
66 start_position: to_i64(start_position),
67 }
68 }
69
70 pub(crate) fn to_find_all_dto(&self, query: &str) -> frontend::document_search::FindAllDto {
71 frontend::document_search::FindAllDto {
72 query: query.into(),
73 case_sensitive: self.case_sensitive,
74 whole_word: self.whole_word,
75 use_regex: self.use_regex,
76 }
77 }
78
79 pub(crate) fn to_replace_dto(
80 &self,
81 query: &str,
82 replacement: &str,
83 replace_all: bool,
84 ) -> frontend::document_search::ReplaceTextDto {
85 frontend::document_search::ReplaceTextDto {
86 query: query.into(),
87 replacement: replacement.into(),
88 case_sensitive: self.case_sensitive,
89 whole_word: self.whole_word,
90 use_regex: self.use_regex,
91 replace_all,
92 }
93 }
94}
95
96pub fn find_result_to_match(dto: &frontend::document_search::FindResultDto) -> Option<FindMatch> {
97 if dto.found {
98 Some(FindMatch {
99 position: to_usize(dto.position),
100 length: to_usize(dto.length),
101 })
102 } else {
103 None
104 }
105}
106
107pub fn find_all_to_matches(dto: &frontend::document_search::FindAllResultDto) -> Vec<FindMatch> {
108 dto.positions
109 .iter()
110 .zip(dto.lengths.iter())
111 .map(|(&pos, &len)| FindMatch {
112 position: to_usize(pos),
113 length: to_usize(len),
114 })
115 .collect()
116}
117
118use frontend::document_formatting::dtos as fmt_dto;
127
128fn underline_style_to_dto(v: &crate::UnderlineStyle) -> fmt_dto::UnderlineStyle {
129 match v {
130 crate::UnderlineStyle::NoUnderline => fmt_dto::UnderlineStyle::NoUnderline,
131 crate::UnderlineStyle::SingleUnderline => fmt_dto::UnderlineStyle::SingleUnderline,
132 crate::UnderlineStyle::DashUnderline => fmt_dto::UnderlineStyle::DashUnderline,
133 crate::UnderlineStyle::DotLine => fmt_dto::UnderlineStyle::DotLine,
134 crate::UnderlineStyle::DashDotLine => fmt_dto::UnderlineStyle::DashDotLine,
135 crate::UnderlineStyle::DashDotDotLine => fmt_dto::UnderlineStyle::DashDotDotLine,
136 crate::UnderlineStyle::WaveUnderline => fmt_dto::UnderlineStyle::WaveUnderline,
137 crate::UnderlineStyle::SpellCheckUnderline => fmt_dto::UnderlineStyle::SpellCheckUnderline,
138 }
139}
140
141fn vertical_alignment_to_dto(v: &crate::CharVerticalAlignment) -> fmt_dto::CharVerticalAlignment {
142 match v {
143 crate::CharVerticalAlignment::Normal => fmt_dto::CharVerticalAlignment::Normal,
144 crate::CharVerticalAlignment::SuperScript => fmt_dto::CharVerticalAlignment::SuperScript,
145 crate::CharVerticalAlignment::SubScript => fmt_dto::CharVerticalAlignment::SubScript,
146 crate::CharVerticalAlignment::Middle => fmt_dto::CharVerticalAlignment::Middle,
147 crate::CharVerticalAlignment::Bottom => fmt_dto::CharVerticalAlignment::Bottom,
148 crate::CharVerticalAlignment::Top => fmt_dto::CharVerticalAlignment::Top,
149 crate::CharVerticalAlignment::Baseline => fmt_dto::CharVerticalAlignment::Baseline,
150 }
151}
152
153fn alignment_to_dto(v: &crate::Alignment) -> fmt_dto::Alignment {
154 match v {
155 crate::Alignment::Left => fmt_dto::Alignment::Left,
156 crate::Alignment::Right => fmt_dto::Alignment::Right,
157 crate::Alignment::Center => fmt_dto::Alignment::Center,
158 crate::Alignment::Justify => fmt_dto::Alignment::Justify,
159 }
160}
161
162fn marker_to_dto(v: &crate::MarkerType) -> fmt_dto::MarkerType {
163 match v {
164 crate::MarkerType::NoMarker => fmt_dto::MarkerType::NoMarker,
165 crate::MarkerType::Unchecked => fmt_dto::MarkerType::Unchecked,
166 crate::MarkerType::Checked => fmt_dto::MarkerType::Checked,
167 }
168}
169
170impl TextFormat {
176 pub(crate) fn to_set_dto(
177 &self,
178 position: usize,
179 anchor: usize,
180 ) -> frontend::document_formatting::SetTextFormatDto {
181 frontend::document_formatting::SetTextFormatDto {
182 position: to_i64(position),
183 anchor: to_i64(anchor),
184 font_family: self.font_family.clone(),
185 font_point_size: self.font_point_size.map(|v| v as i64),
186 font_weight: self.font_weight.map(|v| v as i64),
187 font_bold: self.font_bold,
188 font_italic: self.font_italic,
189 font_underline: self.font_underline,
190 font_overline: self.font_overline,
191 font_strikeout: self.font_strikeout,
192 letter_spacing: self.letter_spacing.map(|v| v as i64),
193 word_spacing: self.word_spacing.map(|v| v as i64),
194 underline_style: self.underline_style.as_ref().map(underline_style_to_dto),
195 vertical_alignment: self
196 .vertical_alignment
197 .as_ref()
198 .map(vertical_alignment_to_dto),
199 }
200 }
201
202 pub(crate) fn to_merge_dto(
203 &self,
204 position: usize,
205 anchor: usize,
206 ) -> frontend::document_formatting::MergeTextFormatDto {
207 frontend::document_formatting::MergeTextFormatDto {
208 position: to_i64(position),
209 anchor: to_i64(anchor),
210 font_family: self.font_family.clone(),
211 font_bold: self.font_bold,
212 font_italic: self.font_italic,
213 font_underline: self.font_underline,
214 font_strikeout: self.font_strikeout,
215 }
216 }
217}
218
219impl From<&frontend::common::format_runs::CharacterFormat> for TextFormat {
222 fn from(fmt: &frontend::common::format_runs::CharacterFormat) -> Self {
223 Self {
224 font_family: fmt.font_family.clone(),
225 font_point_size: fmt.font_point_size.map(|v| v as u32),
226 font_weight: fmt.font_weight.map(|v| v as u32),
227 font_bold: fmt.font_bold,
228 font_italic: fmt.font_italic,
229 font_underline: fmt.font_underline,
230 font_overline: fmt.font_overline,
231 font_strikeout: fmt.font_strikeout,
232 letter_spacing: fmt.letter_spacing.map(|v| v as i32),
233 word_spacing: fmt.word_spacing.map(|v| v as i32),
234 underline_style: fmt.underline_style.clone(),
235 vertical_alignment: fmt.vertical_alignment.clone(),
236 anchor_href: fmt.anchor_href.clone(),
237 anchor_names: fmt.anchor_names.clone(),
238 is_anchor: fmt.is_anchor,
239 tooltip: fmt.tooltip.clone(),
240 foreground_color: None,
241 background_color: None,
242 underline_color: None,
243 }
244 }
245}
246
247impl BlockFormat {
250 pub(crate) fn to_set_dto(
251 &self,
252 position: usize,
253 anchor: usize,
254 ) -> frontend::document_formatting::SetBlockFormatDto {
255 frontend::document_formatting::SetBlockFormatDto {
256 position: to_i64(position),
257 anchor: to_i64(anchor),
258 alignment: self.alignment.as_ref().map(alignment_to_dto),
259 heading_level: self.heading_level.map(|v| v as i64),
260 indent: self.indent.map(|v| v as i64),
261 marker: self.marker.as_ref().map(marker_to_dto),
262 line_height: self.line_height.map(|v| (v * 1000.0) as i64),
263 non_breakable_lines: self.non_breakable_lines,
264 direction: self.direction.clone(),
265 background_color: self.background_color.clone(),
266 is_code_block: self.is_code_block,
267 code_language: self.code_language.clone(),
268 top_margin: self.top_margin.map(|v| v as i64),
269 bottom_margin: self.bottom_margin.map(|v| v as i64),
270 left_margin: self.left_margin.map(|v| v as i64),
271 right_margin: self.right_margin.map(|v| v as i64),
272 text_indent: self.text_indent.map(|v| v as i64),
273 }
274 }
275}
276
277impl From<&frontend::block::dtos::BlockDto> for BlockFormat {
278 fn from(b: &frontend::block::dtos::BlockDto) -> Self {
279 Self {
280 alignment: b.fmt_alignment.clone(),
281 top_margin: b.fmt_top_margin.map(|v| v as i32),
282 bottom_margin: b.fmt_bottom_margin.map(|v| v as i32),
283 left_margin: b.fmt_left_margin.map(|v| v as i32),
284 right_margin: b.fmt_right_margin.map(|v| v as i32),
285 heading_level: b.fmt_heading_level.map(|v| v as u8),
286 indent: b.fmt_indent.map(|v| v as u8),
287 text_indent: b.fmt_text_indent.map(|v| v as i32),
288 marker: b.fmt_marker.clone(),
289 tab_positions: b.fmt_tab_positions.iter().map(|&v| v as i32).collect(),
290 line_height: b.fmt_line_height.map(|v| v as f32 / 1000.0),
291 non_breakable_lines: b.fmt_non_breakable_lines,
292 direction: b.fmt_direction.clone(),
293 background_color: b.fmt_background_color.clone(),
294 is_code_block: b.fmt_is_code_block,
295 code_language: b.fmt_code_language.clone(),
296 }
297 }
298}
299
300impl FrameFormat {
303 pub(crate) fn to_set_dto(
304 &self,
305 position: usize,
306 anchor: usize,
307 frame_id: usize,
308 ) -> frontend::document_formatting::SetFrameFormatDto {
309 frontend::document_formatting::SetFrameFormatDto {
310 position: to_i64(position),
311 anchor: to_i64(anchor),
312 frame_id: to_i64(frame_id),
313 height: self.height.map(|v| v as i64),
314 width: self.width.map(|v| v as i64),
315 top_margin: self.top_margin.map(|v| v as i64),
316 bottom_margin: self.bottom_margin.map(|v| v as i64),
317 left_margin: self.left_margin.map(|v| v as i64),
318 right_margin: self.right_margin.map(|v| v as i64),
319 padding: self.padding.map(|v| v as i64),
320 border: self.border.map(|v| v as i64),
321 is_blockquote: self.is_blockquote,
322 }
323 }
324}
325
326impl ListFormat {
329 pub(crate) fn to_set_dto(
330 &self,
331 list_id: usize,
332 ) -> frontend::document_formatting::SetListFormatDto {
333 frontend::document_formatting::SetListFormatDto {
334 list_id: to_i64(list_id),
335 style: self.style.clone(),
336 indent: self.indent.map(|v| v as i64),
337 prefix: self.prefix.clone(),
338 suffix: self.suffix.clone(),
339 }
340 }
341}
342
343impl crate::flow::TableFormat {
346 pub(crate) fn to_set_dto(
347 &self,
348 table_id: usize,
349 ) -> frontend::document_formatting::SetTableFormatDto {
350 frontend::document_formatting::SetTableFormatDto {
351 table_id: to_i64(table_id),
352 border: self.border.map(|v| v as i64),
353 cell_spacing: self.cell_spacing.map(|v| v as i64),
354 cell_padding: self.cell_padding.map(|v| v as i64),
355 width: self.width.map(|v| v as i64),
356 alignment: self.alignment.as_ref().map(alignment_to_dto),
357 }
358 }
359}
360
361fn cell_vertical_alignment_to_dto(
364 v: &crate::flow::CellVerticalAlignment,
365) -> fmt_dto::CellVerticalAlignment {
366 match v {
367 crate::flow::CellVerticalAlignment::Top => fmt_dto::CellVerticalAlignment::Top,
368 crate::flow::CellVerticalAlignment::Middle => fmt_dto::CellVerticalAlignment::Middle,
369 crate::flow::CellVerticalAlignment::Bottom => fmt_dto::CellVerticalAlignment::Bottom,
370 }
371}
372
373impl crate::flow::CellFormat {
374 pub(crate) fn to_set_dto(
375 &self,
376 cell_id: usize,
377 ) -> frontend::document_formatting::SetTableCellFormatDto {
378 frontend::document_formatting::SetTableCellFormatDto {
379 cell_id: to_i64(cell_id),
380 padding: self.padding.map(|v| v as i64),
381 border: self.border.map(|v| v as i64),
382 vertical_alignment: self
383 .vertical_alignment
384 .as_ref()
385 .map(cell_vertical_alignment_to_dto),
386 background_color: self.background_color.clone(),
387 }
388 }
389}