docx_reader/documents/elements/
instr_tc.rs

1use serde::Serialize;
2
3use crate::documents::*;
4
5// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TCTC_topic_ID0EU2N1.html
6#[derive(Serialize, Debug, Clone, PartialEq, Default)]
7#[serde(rename_all = "camelCase")]
8pub struct InstrTC {
9	pub text: String,
10	// \n Omits the page number for the entry.
11	pub omits_page_number: bool,
12	pub level: Option<usize>,
13	// \f
14	pub item_type_identifier: Option<String>,
15}
16
17impl InstrTC {
18	pub fn new(text: impl Into<String>) -> Self {
19		Self {
20			text: text.into(),
21			..Default::default()
22		}
23	}
24
25	pub fn omits_page_number(mut self) -> Self {
26		self.omits_page_number = true;
27		self
28	}
29
30	pub fn level(mut self, level: usize) -> Self {
31		self.level = Some(level);
32		self
33	}
34
35	pub fn item_type_identifier(mut self, t: impl Into<String>) -> Self {
36		self.item_type_identifier = Some(t.into());
37		self
38	}
39}
40
41fn parse_level(i: &str) -> Option<usize> {
42	let r = i.replace("&quot;", "").replace("\"", "");
43	if let Ok(l) = usize::from_str(&r) {
44		return Some(l);
45	}
46	None
47}
48
49impl std::str::FromStr for InstrTC {
50	type Err = ();
51
52	fn from_str(instr: &str) -> Result<Self, Self::Err> {
53		let mut s = instr.split(' ');
54		let text = s.next();
55		let mut tc = InstrTC::new(text.unwrap_or_default());
56		loop {
57			if let Some(i) = s.next() {
58				match i {
59					"\\f" => {
60						if let Some(r) = s.next() {
61							let r = r.replace("&quot;", "").replace("\"", "");
62							tc = tc.item_type_identifier(r);
63						}
64					}
65					"\\l" => {
66						if let Some(r) = s.next() {
67							if let Some(l) = parse_level(r) {
68								tc = tc.level(l);
69							}
70						}
71					}
72					"\\n" => tc = tc.omits_page_number(),
73					_ => {}
74				}
75			} else {
76				return Ok(tc);
77			}
78		}
79	}
80}