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 diacritic_sensitive: self.diacritic_sensitive,
65 language: self.language.clone(),
66 use_regex: self.use_regex,
67 search_backward: self.search_backward,
68 start_position: to_i64(start_position),
69 }
70 }
71
72 pub(crate) fn to_find_all_dto(&self, query: &str) -> frontend::document_search::FindAllDto {
73 frontend::document_search::FindAllDto {
74 query: query.into(),
75 case_sensitive: self.case_sensitive,
76 whole_word: self.whole_word,
77 diacritic_sensitive: self.diacritic_sensitive,
78 language: self.language.clone(),
79 use_regex: self.use_regex,
80 }
81 }
82}
83
84impl crate::ReplaceOptions {
85 pub(crate) fn to_replace_ranges_dto(
89 &self,
90 ranges: &[crate::ReplaceRange],
91 ) -> frontend::document_search::ReplaceRangesDto {
92 let mut positions = Vec::with_capacity(ranges.len());
93 let mut lengths = Vec::with_capacity(ranges.len());
94 let mut replacements = Vec::with_capacity(ranges.len());
95 for range in ranges {
96 positions.push(to_i64(range.position));
97 lengths.push(to_i64(range.length));
98 replacements.push(range.replacement.clone());
99 }
100 frontend::document_search::ReplaceRangesDto {
101 positions,
102 lengths,
103 replacements,
104 format_policy: self.format_policy,
105 }
106 }
107
108 pub(crate) fn to_replace_dto(
109 &self,
110 query: &str,
111 replacement: &str,
112 replace_all: bool,
113 ) -> frontend::document_search::ReplaceTextDto {
114 frontend::document_search::ReplaceTextDto {
115 query: query.into(),
116 replacement: replacement.into(),
117 case_sensitive: self.find.case_sensitive,
118 whole_word: self.find.whole_word,
119 diacritic_sensitive: self.find.diacritic_sensitive,
120 language: self.find.language.clone(),
121 use_regex: self.find.use_regex,
122 replace_all,
123 format_policy: self.format_policy,
124 }
125 }
126}
127
128pub fn find_result_to_match(dto: &frontend::document_search::FindResultDto) -> Option<FindMatch> {
129 if dto.found {
130 Some(FindMatch {
131 position: to_usize(dto.position),
132 length: to_usize(dto.length),
133 matched_text: dto.matched_text.clone(),
134 })
135 } else {
136 None
137 }
138}
139
140pub fn find_all_to_matches(dto: &frontend::document_search::FindAllResultDto) -> Vec<FindMatch> {
144 debug_assert_eq!(dto.positions.len(), dto.lengths.len());
145 debug_assert_eq!(dto.positions.len(), dto.matched_texts.len());
146 dto.positions
147 .iter()
148 .zip(dto.lengths.iter())
149 .zip(dto.matched_texts.iter())
150 .map(|((&pos, &len), text)| FindMatch {
151 position: to_usize(pos),
152 length: to_usize(len),
153 matched_text: text.clone(),
154 })
155 .collect()
156}
157
158use frontend::document_formatting::dtos as fmt_dto;
167
168fn underline_style_to_dto(v: &crate::UnderlineStyle) -> fmt_dto::UnderlineStyle {
169 match v {
170 crate::UnderlineStyle::NoUnderline => fmt_dto::UnderlineStyle::NoUnderline,
171 crate::UnderlineStyle::SingleUnderline => fmt_dto::UnderlineStyle::SingleUnderline,
172 crate::UnderlineStyle::DashUnderline => fmt_dto::UnderlineStyle::DashUnderline,
173 crate::UnderlineStyle::DotLine => fmt_dto::UnderlineStyle::DotLine,
174 crate::UnderlineStyle::DashDotLine => fmt_dto::UnderlineStyle::DashDotLine,
175 crate::UnderlineStyle::DashDotDotLine => fmt_dto::UnderlineStyle::DashDotDotLine,
176 crate::UnderlineStyle::WaveUnderline => fmt_dto::UnderlineStyle::WaveUnderline,
177 crate::UnderlineStyle::SpellCheckUnderline => fmt_dto::UnderlineStyle::SpellCheckUnderline,
178 }
179}
180
181fn vertical_alignment_to_dto(v: &crate::CharVerticalAlignment) -> fmt_dto::CharVerticalAlignment {
182 match v {
183 crate::CharVerticalAlignment::Normal => fmt_dto::CharVerticalAlignment::Normal,
184 crate::CharVerticalAlignment::SuperScript => fmt_dto::CharVerticalAlignment::SuperScript,
185 crate::CharVerticalAlignment::SubScript => fmt_dto::CharVerticalAlignment::SubScript,
186 crate::CharVerticalAlignment::Middle => fmt_dto::CharVerticalAlignment::Middle,
187 crate::CharVerticalAlignment::Bottom => fmt_dto::CharVerticalAlignment::Bottom,
188 crate::CharVerticalAlignment::Top => fmt_dto::CharVerticalAlignment::Top,
189 crate::CharVerticalAlignment::Baseline => fmt_dto::CharVerticalAlignment::Baseline,
190 }
191}
192
193fn alignment_to_dto(v: &crate::Alignment) -> fmt_dto::Alignment {
194 match v {
195 crate::Alignment::Left => fmt_dto::Alignment::Left,
196 crate::Alignment::Right => fmt_dto::Alignment::Right,
197 crate::Alignment::Center => fmt_dto::Alignment::Center,
198 crate::Alignment::Justify => fmt_dto::Alignment::Justify,
199 }
200}
201
202fn direction_to_dto(v: &crate::TextDirection) -> fmt_dto::TextDirection {
203 match v {
204 crate::TextDirection::LeftToRight => fmt_dto::TextDirection::LeftToRight,
205 crate::TextDirection::RightToLeft => fmt_dto::TextDirection::RightToLeft,
206 }
207}
208
209fn list_style_to_dto(v: &crate::ListStyle) -> fmt_dto::ListStyle {
210 match v {
211 crate::ListStyle::Disc => fmt_dto::ListStyle::Disc,
212 crate::ListStyle::Circle => fmt_dto::ListStyle::Circle,
213 crate::ListStyle::Square => fmt_dto::ListStyle::Square,
214 crate::ListStyle::Decimal => fmt_dto::ListStyle::Decimal,
215 crate::ListStyle::LowerAlpha => fmt_dto::ListStyle::LowerAlpha,
216 crate::ListStyle::UpperAlpha => fmt_dto::ListStyle::UpperAlpha,
217 crate::ListStyle::LowerRoman => fmt_dto::ListStyle::LowerRoman,
218 crate::ListStyle::UpperRoman => fmt_dto::ListStyle::UpperRoman,
219 }
220}
221
222fn marker_to_dto(v: &crate::MarkerType) -> fmt_dto::MarkerType {
223 match v {
224 crate::MarkerType::NoMarker => fmt_dto::MarkerType::NoMarker,
225 crate::MarkerType::Unchecked => fmt_dto::MarkerType::Unchecked,
226 crate::MarkerType::Checked => fmt_dto::MarkerType::Checked,
227 }
228}
229
230impl TextFormat {
236 pub(crate) fn to_set_dto(
237 &self,
238 position: usize,
239 anchor: usize,
240 ) -> frontend::document_formatting::SetTextFormatDto {
241 frontend::document_formatting::SetTextFormatDto {
242 position: to_i64(position),
243 anchor: to_i64(anchor),
244 font_family: self.font_family.clone(),
245 font_point_size: self.font_point_size.map(|v| v as i64),
246 font_weight: self.font_weight.map(|v| v as i64),
247 font_bold: self.font_bold,
248 font_italic: self.font_italic,
249 font_underline: self.font_underline,
250 font_overline: self.font_overline,
251 font_strikeout: self.font_strikeout,
252 letter_spacing: self.letter_spacing.map(|v| v as i64),
253 word_spacing: self.word_spacing.map(|v| v as i64),
254 underline_style: self.underline_style.as_ref().map(underline_style_to_dto),
255 vertical_alignment: self
256 .vertical_alignment
257 .as_ref()
258 .map(vertical_alignment_to_dto),
259 anchor_href: self.anchor_href.clone(),
260 clear_link: self.clear_link,
261 }
262 }
263
264 pub(crate) fn to_merge_dto(
265 &self,
266 position: usize,
267 anchor: usize,
268 ) -> frontend::document_formatting::MergeTextFormatDto {
269 frontend::document_formatting::MergeTextFormatDto {
270 position: to_i64(position),
271 anchor: to_i64(anchor),
272 font_family: self.font_family.clone(),
273 font_bold: self.font_bold,
274 font_italic: self.font_italic,
275 font_underline: self.font_underline,
276 font_strikeout: self.font_strikeout,
277 vertical_alignment: self
278 .vertical_alignment
279 .as_ref()
280 .map(vertical_alignment_to_dto),
281 anchor_href: self.anchor_href.clone(),
282 clear_link: self.clear_link,
283 }
284 }
285}
286
287impl From<&frontend::common::format_runs::CharacterFormat> for TextFormat {
290 fn from(fmt: &frontend::common::format_runs::CharacterFormat) -> Self {
291 Self {
292 font_family: fmt.font_family.clone(),
293 font_point_size: fmt.font_point_size.map(|v| v as u32),
294 font_weight: fmt.font_weight.map(|v| v as u32),
295 font_bold: fmt.font_bold,
296 font_italic: fmt.font_italic,
297 font_underline: fmt.font_underline,
298 font_overline: fmt.font_overline,
299 font_strikeout: fmt.font_strikeout,
300 letter_spacing: fmt.letter_spacing.map(|v| v as i32),
301 word_spacing: fmt.word_spacing.map(|v| v as i32),
302 underline_style: fmt.underline_style.clone(),
303 vertical_alignment: fmt.vertical_alignment.clone(),
304 anchor_href: fmt.anchor_href.clone(),
305 anchor_names: fmt.anchor_names.clone(),
306 is_anchor: fmt.is_anchor,
307 tooltip: fmt.tooltip.clone(),
308 clear_link: false,
311 foreground_color: None,
312 background_color: None,
313 underline_color: None,
314 }
315 }
316}
317
318impl BlockFormat {
321 pub(crate) fn to_set_dto(
322 &self,
323 position: usize,
324 anchor: usize,
325 ) -> frontend::document_formatting::SetBlockFormatDto {
326 frontend::document_formatting::SetBlockFormatDto {
327 position: to_i64(position),
328 anchor: to_i64(anchor),
329 alignment: self.alignment.as_ref().map(alignment_to_dto),
330 heading_level: self.heading_level.map(|v| v as i64),
331 indent: self.indent.map(|v| v as i64),
332 marker: self.marker.as_ref().map(marker_to_dto),
333 line_height: self.line_height.map(|v| (v * 1000.0) as i64),
334 non_breakable_lines: self.non_breakable_lines,
335 page_break_before: self.page_break_before,
336 direction: self.direction.as_ref().map(direction_to_dto),
337 clear_direction: self.clear_direction,
338 background_color: self.background_color.clone(),
339 is_code_block: self.is_code_block,
340 code_language: self.code_language.clone(),
341 hyphenate: self.hyphenate,
342 language: self.language.clone(),
343 top_margin: self.top_margin.map(|v| v as i64),
344 bottom_margin: self.bottom_margin.map(|v| v as i64),
345 left_margin: self.left_margin.map(|v| v as i64),
346 right_margin: self.right_margin.map(|v| v as i64),
347 text_indent: self.text_indent.map(|v| v as i64),
348 }
349 }
350}
351
352impl From<&frontend::block::dtos::BlockDto> for BlockFormat {
353 fn from(b: &frontend::block::dtos::BlockDto) -> Self {
354 Self {
355 alignment: b.fmt_alignment.clone(),
356 top_margin: b.fmt_top_margin.map(|v| v as i32),
357 bottom_margin: b.fmt_bottom_margin.map(|v| v as i32),
358 left_margin: b.fmt_left_margin.map(|v| v as i32),
359 right_margin: b.fmt_right_margin.map(|v| v as i32),
360 heading_level: b.fmt_heading_level.map(|v| v as u8),
361 indent: b.fmt_indent.map(|v| v as u8),
362 text_indent: b.fmt_text_indent.map(|v| v as i32),
363 marker: b.fmt_marker.clone(),
364 tab_positions: b.fmt_tab_positions.iter().map(|&v| v as i32).collect(),
365 line_height: b.fmt_line_height.map(|v| v as f32 / 1000.0),
366 non_breakable_lines: b.fmt_non_breakable_lines,
367 page_break_before: b.fmt_page_break_before,
368 direction: b.fmt_direction.clone(),
369 clear_direction: false,
371 background_color: b.fmt_background_color.clone(),
372 is_code_block: b.fmt_is_code_block,
373 code_language: b.fmt_code_language.clone(),
374 hyphenate: b.fmt_hyphenate,
375 language: b.fmt_language.clone(),
376 }
377 }
378}
379
380impl FrameFormat {
383 pub(crate) fn to_set_dto(
384 &self,
385 position: usize,
386 anchor: usize,
387 frame_id: usize,
388 ) -> frontend::document_formatting::SetFrameFormatDto {
389 frontend::document_formatting::SetFrameFormatDto {
390 position: to_i64(position),
391 anchor: to_i64(anchor),
392 frame_id: to_i64(frame_id),
393 height: self.height.map(|v| v as i64),
394 width: self.width.map(|v| v as i64),
395 top_margin: self.top_margin.map(|v| v as i64),
396 bottom_margin: self.bottom_margin.map(|v| v as i64),
397 left_margin: self.left_margin.map(|v| v as i64),
398 right_margin: self.right_margin.map(|v| v as i64),
399 padding: self.padding.map(|v| v as i64),
400 border: self.border.map(|v| v as i64),
401 is_blockquote: self.is_blockquote,
402 }
403 }
404}
405
406impl ListFormat {
409 pub(crate) fn to_set_dto(
410 &self,
411 list_id: usize,
412 ) -> frontend::document_formatting::SetListFormatDto {
413 frontend::document_formatting::SetListFormatDto {
414 list_id: to_i64(list_id),
415 style: self.style.as_ref().map(list_style_to_dto),
416 indent: self.indent.map(|v| v as i64),
417 prefix: self.prefix.clone(),
418 suffix: self.suffix.clone(),
419 }
420 }
421}
422
423impl crate::flow::TableFormat {
426 pub(crate) fn to_set_dto(
427 &self,
428 table_id: usize,
429 ) -> frontend::document_formatting::SetTableFormatDto {
430 frontend::document_formatting::SetTableFormatDto {
431 table_id: to_i64(table_id),
432 border: self.border.map(|v| v as i64),
433 cell_spacing: self.cell_spacing.map(|v| v as i64),
434 cell_padding: self.cell_padding.map(|v| v as i64),
435 width: self.width.map(|v| v as i64),
436 alignment: self.alignment.as_ref().map(alignment_to_dto),
437 }
438 }
439}
440
441fn cell_vertical_alignment_to_dto(
444 v: &crate::flow::CellVerticalAlignment,
445) -> fmt_dto::CellVerticalAlignment {
446 match v {
447 crate::flow::CellVerticalAlignment::Top => fmt_dto::CellVerticalAlignment::Top,
448 crate::flow::CellVerticalAlignment::Middle => fmt_dto::CellVerticalAlignment::Middle,
449 crate::flow::CellVerticalAlignment::Bottom => fmt_dto::CellVerticalAlignment::Bottom,
450 }
451}
452
453impl crate::flow::CellFormat {
454 pub(crate) fn to_set_dto(
455 &self,
456 cell_id: usize,
457 ) -> frontend::document_formatting::SetTableCellFormatDto {
458 frontend::document_formatting::SetTableCellFormatDto {
459 cell_id: to_i64(cell_id),
460 padding: self.padding.map(|v| v as i64),
461 border: self.border.map(|v| v as i64),
462 vertical_alignment: self
463 .vertical_alignment
464 .as_ref()
465 .map(cell_vertical_alignment_to_dto),
466 background_color: self.background_color.clone(),
467 }
468 }
469}