google_maps 3.9.5

An unofficial Google Maps Platform client library for the Rust programming language.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
//! Contains the `StructuredFormat` struct for place and query predictions.
//!
//! Structured format breaks down predictions into main text (the primary name) and secondary text
//! (additional context), enabling better UI layouts and formatting control.

use crate::places_new::autocomplete::response::FormattableText;

// -------------------------------------------------------------------------------------------------
//
/// A breakdown of a prediction into main text and secondary text.
///
/// Separates predictions into two components: main text (the primary identifier like a place name
/// or query) and secondary text (additional disambiguating context like a city or region).
///
/// This structure enables UI designs where the main text can be emphasized while secondary text
/// provides supporting context:
///
/// * For Place predictions, the main text typically contains the specific name of the place, while
///   secondary text includes the address or location details.
///
/// * For query predictions, the main text contains the query itself, while secondary text provides
///   additional context.
///
/// # Examples
///
/// ```rust,ignore
/// // Place prediction
/// let format = StructuredFormat {
///     main_text: FormattableText::from("Pizza Hut"),
///     secondary_text: Some(FormattableText::from("123 Main St, San Francisco")),
/// };
///
/// println!("{}", format.main_text.text());     // "Pizza Hut"
/// println!("{}", format.secondary_text.unwrap().text()); // "123 Main St, San Francisco"
///
/// // With HTML highlighting on main text
/// let highlighted = format.main_text().to_html("strong");
/// // "<strong>Pizza</strong> Hut"
/// ```
#[derive(
    // std
    Clone,
    Debug,
    Eq,
    PartialEq,
    // serde
    serde::Deserialize,
    serde::Serialize,
    // getset
    getset::Getters,
    getset::MutGetters,
    getset::Setters,

)]
#[serde(rename_all = "camelCase")]
pub struct StructuredFormat {
    /// The main text representing the name of the Place or query.
    ///
    /// Contains the primary identifier or display name:
    /// * For places, this is typically the business or location name.
    /// * For queries, this is the search text itself.
    ///
    /// This text usually has match highlighting and should be displayed more prominently in the UI.
    #[getset(set = "pub", get_mut = "pub")]
    pub main_text: FormattableText,

    /// Additional disambiguating features for context.
    ///
    /// Contains secondary information like city, region, address, or other context that helps
    /// identify or refine the prediction.
    ///
    /// May be `None` if no additional context is available.
    ///
    /// Display this text with less emphasis than the main text, such as in a smaller font or muted
    /// color.
    #[getset(set = "pub", get_mut = "pub")]
    pub secondary_text: Option<FormattableText>,
}

// -------------------------------------------------------------------------------------------------
//
// Method Implementations

impl StructuredFormat {
    /// Creates a new `StructuredFormat` with main and optional secondary text.
    ///
    /// Use this when constructing structured formats from API responses or when manually creating
    /// formatted predictions.
    #[must_use]
    pub const fn new(main_text: FormattableText, secondary_text: Option<FormattableText>) -> Self {
        Self {
            main_text,
            secondary_text,
        }
    }

    /// Creates a new `StructuredFormat` with only main text.
    ///
    /// Use this when you have a primary name or query but no additional context information.
    #[must_use]
    pub const fn new_main_only(main_text: FormattableText) -> Self {
        Self {
            main_text,
            secondary_text: None,
        }
    }

    /// Returns a reference to the main text.
    ///
    /// The primary identifier or name that should be displayed prominently. Use the returned
    /// `FormattableText` to access match ranges and apply HTML highlighting.
    ///
    /// For example: `format.main_text().to_html("mark")` to highlight matched portions.
    #[must_use]
    pub const fn main_text(&self) -> &FormattableText {
        &self.main_text
    }

    /// Returns a reference to the secondary text if present.
    ///
    /// Additional context or disambiguating information.
    ///
    /// Use the returned `FormattableText` to access match ranges and apply HTML highlighting.
    ///
    /// For example: `format.secondary_text().map(|t| t.to_html("em"))` to emphasize matched
    /// portions.
    #[must_use]
    pub const fn secondary_text(&self) -> Option<&FormattableText> {
        self.secondary_text.as_ref()
    }

    /// Checks if secondary text is present.
    ///
    /// Returns `true` if additional context information is available.
    #[must_use]
    pub const fn has_secondary_text(&self) -> bool {
        self.secondary_text.is_some()
    }

    /// Returns a combined display string with main and secondary text.
    ///
    /// Formats as `main_text`, `secondary_text` if both are present, or just `main_text` if
    /// secondary text is absent.
    ///
    /// Use this for simple text display without HTML formatting. For formatted output, use the
    /// individual getters with `to_html()` methods.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// let format = StructuredFormat {
    ///     main_text: FormattableText::from("Pizza Hut"),
    ///     secondary_text: Some(FormattableText::from("San Francisco")),
    /// };
    ///
    /// println!("{}", format.combined_text());
    /// // "Pizza Hut, San Francisco"
    /// ```
    #[must_use]
    pub fn combined_text(&self) -> String {
        self.secondary_text
            .as_ref()
            .map_or_else(
                || self.main_text.text().clone(),
                |secondary| format!(
                    "{main}, {secondary}",
                    main = self.main_text.text(),
                    secondary = secondary.text()
                )

            )
    }

    /// Formats the main text with HTML highlighting.
    ///
    /// Convenience method that wraps `main_text().to_html(tag)`. Use this to quickly generate
    /// HTML-highlighted main text for UI display.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// let html = format.main_html("strong");
    /// // "<strong>Pizza</strong> Hut"
    /// ```
    #[must_use]
    pub fn main_html(&self, tag: &str) -> String {
        self.main_text.to_html(tag)
    }

    /// Formats the secondary text with HTML highlighting if present.
    ///
    /// Convenience method that wraps `secondary_text().map(|t| t.to_html(tag))`.
    ///
    /// Use this to quickly generate HTML-highlighted secondary text for UI display. Returns
    /// `None` if no secondary text is available.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// if let Some(html) = format.secondary_html("em") {
    ///     println!("{}", html);
    ///     // "<em>San</em> Francisco"
    /// }
    /// ```
    #[must_use]
    pub fn secondary_html(&self, tag: &str) -> Option<String> {
        self.secondary_text.as_ref().map(|text| text.to_html(tag))
    }

    /// Formats the combined text with separate HTML tags for main and secondary.
    ///
    /// Applies different HTML tags to main and secondary text portions, then combines them with a
    /// comma separator. Use this to create formatted output where main and secondary text have
    /// different visual emphasis.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// let html = format.combined_html("strong", "em");
    /// // "<strong>Pizza</strong> Hut, <em>San</em> Francisco"
    /// ```
    #[must_use]
    pub fn combined_html(&self, main_tag: &str, secondary_tag: &str) -> String {
        self.secondary_text
            .as_ref()
            .map_or_else(
                || self.main_text.to_html(main_tag),
                |secondary| format!(
                    "{main}, {secondary}",
                    main = self.main_text.to_html(main_tag),
                    secondary = secondary.to_html(secondary_tag)
                ))
    }

    /// Formats the main text with a custom formatter function.
    ///
    /// Applies a custom formatting function to the main text, distinguishing between matched and
    /// unmatched portions.
    ///
    /// This provides maximum flexibility for output formats beyond HTML, such as ANSI terminal
    /// codes, Markdown, or custom markup languages.
    ///
    /// # Examples
    ///
    /// **ANSI terminal colors (bold green for matches):**
    /// ```rust,ignore
    /// let formatted = format.main_format_with(|text, is_matched| {
    ///     if is_matched {
    ///         format!("\x1b[1;32m{}\x1b[0m", text)  // Bold green
    ///     } else {
    ///         text.to_string()
    ///     }
    /// });
    /// // "\x1b[1;32mPizza\x1b[0m Hut"
    /// ```
    ///
    /// **Markdown:**
    /// ```rust,ignore
    /// let formatted = format.main_format_with(|text, is_matched| {
    ///     if is_matched {
    ///         format!("**{}**", text)
    ///     } else {
    ///         text.to_string()
    ///     }
    /// });
    /// // "**Pizza** Hut"
    /// ```
    #[must_use]
    pub fn main_format_with<F>(&self, formatter: F) -> String
    where
        F: FnMut(&str, bool) -> String,
    {
        self.main_text.format_with(formatter)
    }

    /// Formats the secondary text with a custom formatter function if present.
    ///
    /// Applies a custom formatting function to the secondary text, distinguishing between matched
    /// and unmatched portions.
    ///
    /// Returns `None` if no secondary text is available. Use this for flexible formatting of
    /// contextual information in any output format.
    ///
    /// # Examples
    ///
    /// **ANSI terminal colors (italic cyan for matches):**
    /// ```rust,ignore
    /// if let Some(formatted) = format.secondary_format_with(|text, is_matched| {
    ///     if is_matched {
    ///         format!("\x1b[3;36m{}\x1b[0m", text)  // Italic cyan
    ///     } else {
    ///         text.to_string()
    ///     }
    /// }) {
    ///     println!("{}", formatted);
    ///     // "\x1b[3;36mSan\x1b[0m Francisco"
    /// }
    /// ```
    ///
    /// **Markdown:**
    /// ```rust,ignore
    /// if let Some(formatted) = format.secondary_format_with(|text, is_matched| {
    ///     if is_matched {
    ///         format!("*{}*", text)
    ///     } else {
    ///         text.to_string()
    ///     }
    /// }) {
    ///     println!("{}", formatted);
    ///     // "*San* Francisco"
    /// }
    /// ```
    #[must_use]
    pub fn secondary_format_with<F>(&self, formatter: F) -> Option<String>
    where
        F: FnMut(&str, bool) -> String,
    {
        self.secondary_text
            .as_ref()
            .map(|text| text.format_with(formatter))
    }

    /// Formats the combined text with separate custom formatters for main and secondary.
    ///
    /// Applies different formatting functions to main and secondary text portions, then combines
    /// them with a comma separator.
    ///
    /// Use this to create formatted output where main and secondary text have different visual
    /// styles in any output format (ANSI, Markdown, custom markup, etc.).
    ///
    /// # Examples
    ///
    /// **ANSI terminal colors (bold green main, italic cyan secondary):**
    /// ```rust,ignore
    /// let formatted = format.combined_format_with(
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("\x1b[1;32m{}\x1b[0m", text)  // Bold green
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     },
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("\x1b[3;36m{}\x1b[0m", text)  // Italic cyan
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     }
    /// );
    /// // "\x1b[1;32mPizza\x1b[0m Hut, \x1b[3;36mSan\x1b[0m Francisco"
    /// ```
    ///
    /// **Markdown (bold main, italic secondary):**
    /// ```rust,ignore
    /// let formatted = format.combined_format_with(
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("**{}**", text)
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     },
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("*{}*", text)
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     }
    /// );
    /// // "**Pizza** Hut, *San* Francisco"
    /// ```
    ///
    /// **Custom markers (main: <<>>, secondary: [[]]):**
    /// ```rust,ignore
    /// let formatted = format.combined_format_with(
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("<<{}>>", text)
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     },
    ///     |text, is_matched| {
    ///         if is_matched {
    ///             format!("[[{}]]", text)
    ///         } else {
    ///             text.to_string()
    ///         }
    ///     }
    /// );
    /// // "<<Pizza>> Hut, [[San]] Francisco"
    /// ```
    #[must_use]
    #[allow(clippy::similar_names)]
    pub fn combined_format_with<F, G>(&self, mut main_formatter: F, secondary_formatter: G) -> String
    where
        F: FnMut(&str, bool) -> String,
        G: FnMut(&str, bool) -> String,
    {
        let main_formatted = self.main_text.format_with(&mut main_formatter);
        match &self.secondary_text {
            Some(secondary) => {
                format!(
                    "{main}, {secondary}",
                    main = main_formatted,
                    secondary = secondary.format_with(secondary_formatter)
                )
            }
            None => main_formatted,
        }
    }
}

// -------------------------------------------------------------------------------------------------
//
// Trait Implementations

impl std::fmt::Display for StructuredFormat {
    /// Formats as the combined plain text.
    ///
    /// Returns `main_text`, `secondary_text` for machine-readable output without HTML formatting.
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.combined_text())
    }
}