formal_ai/
document_formats.rs1#[cfg(feature = "meta-language")]
10use meta_language::{
11 canonical_document_format, document_format_profile, docx_package_is_recognized,
12 docx_profile_is_recognized, parse_markup_document, pdf_profile_is_recognized,
13 render_docx_package, LinkNetwork, ParseConfiguration, CROSS_FORMAT_CONCEPTS, DOCUMENT_FORMATS,
14};
15
16pub const DOCUMENT_FORMAT_ENGINE: &str = "meta_language";
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct DocumentFormatCapabilities {
22 pub format: String,
24 pub native_concepts: Vec<String>,
26 pub fallbacks: Vec<(String, String)>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct DocumentConversion {
33 pub source_format: String,
35 pub target_format: String,
37 pub output: String,
39 pub target_capabilities: DocumentFormatCapabilities,
41 pub package_bytes: Option<Vec<u8>>,
46}
47
48#[must_use]
50pub const fn supported_document_formats() -> &'static [&'static str] {
51 #[cfg(feature = "meta-language")]
52 {
53 DOCUMENT_FORMATS
54 }
55 #[cfg(not(feature = "meta-language"))]
56 {
57 &[]
58 }
59}
60
61#[must_use]
63pub const fn cross_format_document_concepts() -> &'static [&'static str] {
64 #[cfg(feature = "meta-language")]
65 {
66 CROSS_FORMAT_CONCEPTS
67 }
68 #[cfg(not(feature = "meta-language"))]
69 {
70 &[]
71 }
72}
73
74#[must_use]
76pub fn canonical_document_format_label(format: &str) -> Option<&'static str> {
77 #[cfg(feature = "meta-language")]
78 {
79 canonical_document_format(format)
80 }
81 #[cfg(not(feature = "meta-language"))]
82 {
83 let _ = format;
84 None
85 }
86}
87
88#[must_use]
90pub fn document_format_capabilities(format: &str) -> Option<DocumentFormatCapabilities> {
91 #[cfg(not(feature = "meta-language"))]
92 {
93 let _ = format;
94 return None;
95 }
96 #[cfg(feature = "meta-language")]
97 {
98 let canonical = canonical_document_format(format)?;
99 let profile = document_format_profile(canonical)?;
100 let native_concepts = CROSS_FORMAT_CONCEPTS
101 .iter()
102 .copied()
103 .filter(|concept| profile.supports_concept(concept))
104 .map(str::to_owned)
105 .collect();
106 let fallbacks = CROSS_FORMAT_CONCEPTS
107 .iter()
108 .copied()
109 .filter_map(|concept| {
110 profile
111 .concept_fallback(concept)
112 .map(|fallback| (concept.to_owned(), fallback.to_owned()))
113 })
114 .collect();
115
116 Some(DocumentFormatCapabilities {
117 format: canonical.to_owned(),
118 native_concepts,
119 fallbacks,
120 })
121 }
122}
123
124#[must_use]
130pub fn document_profile_is_recognized(format: &str, text: &str) -> bool {
131 #[cfg(not(feature = "meta-language"))]
132 {
133 let _ = (format, text);
134 return false;
135 }
136 #[cfg(feature = "meta-language")]
137 {
138 match canonical_document_format(format) {
139 Some("PDF") => pdf_profile_is_recognized(text),
140 Some("DOCX") => docx_profile_is_recognized(text),
141 Some(canonical) => parse_markup_document(canonical, text)
142 .is_some_and(|document| !document.blocks.is_empty()),
143 None => false,
144 }
145 }
146}
147
148#[must_use]
154pub fn document_package_is_recognized(format: &str, bytes: &[u8]) -> bool {
155 #[cfg(not(feature = "meta-language"))]
156 {
157 let _ = (format, bytes);
158 return false;
159 }
160 #[cfg(feature = "meta-language")]
161 {
162 match canonical_document_format(format) {
163 Some("DOCX") => docx_package_is_recognized(bytes),
164 _ => false,
165 }
166 }
167}
168
169#[must_use]
171pub fn convert_document_format(
172 source_format: &str,
173 target_format: &str,
174 source_text: &str,
175) -> Option<DocumentConversion> {
176 #[cfg(not(feature = "meta-language"))]
177 {
178 let _ = (source_format, target_format, source_text);
179 return None;
180 }
181 #[cfg(feature = "meta-language")]
182 {
183 let source = canonical_document_format(source_format)?;
184 let target = canonical_document_format(target_format)?;
185 let network = LinkNetwork::parse(source_text, source, ParseConfiguration::default());
186 let output = network.reconstruct_text_as(target, ParseConfiguration::default());
187 let target_capabilities = document_format_capabilities(target)?;
188 let package_bytes = package_bytes_for_target(source, target, source_text);
189
190 Some(DocumentConversion {
191 source_format: source.to_owned(),
192 target_format: target.to_owned(),
193 output,
194 target_capabilities,
195 package_bytes,
196 })
197 }
198}
199
200#[cfg(feature = "meta-language")]
201fn package_bytes_for_target(
202 source_format: &str,
203 target_format: &str,
204 source_text: &str,
205) -> Option<Vec<u8>> {
206 if target_format != "DOCX" {
207 return None;
208 }
209 let document = parse_markup_document(source_format, source_text)?;
210 (!document.blocks.is_empty()).then(|| render_docx_package(&document))
211}