pub struct Text<'a, 'b, 'c, 'd, 'e, 'f> {
pub android: AndroidText<'a, 'b, 'c>,
pub apple: &'d str,
pub windows: WindowsText<'e, 'f>,
}
pub struct AndroidText<'a, 'b, 'c> {
pub title: &'a str,
pub subtitle: Option<&'b str>,
pub description: Option<&'c str>,
}
pub struct WindowsText<'a, 'b> {
#[allow(dead_code)]
pub(crate) title: &'a str,
#[allow(dead_code)]
pub(crate) description: &'b str,
}
impl<'a, 'b> WindowsText<'a, 'b> {
#[cfg(target_os = "windows")]
pub const fn new(title: &'a str, description: &'b str) -> Option<Self> {
use windows::Win32::Security::Credentials::{
CREDUI_MAX_CAPTION_LENGTH, CREDUI_MAX_MESSAGE_LENGTH,
};
if title.len() <= CREDUI_MAX_CAPTION_LENGTH as usize
&& description.len() <= CREDUI_MAX_MESSAGE_LENGTH as usize
{
Some(Self { title, description })
} else {
None
}
}
#[cfg(not(target_os = "windows"))]
pub const fn new(title: &'a str, description: &'b str) -> Option<Self> {
Some(Self { title, description })
}
#[cfg(target_os = "windows")]
pub fn new_truncated(title: &'a str, description: &'b str) -> Self {
use windows::Win32::Security::Credentials::{
CREDUI_MAX_CAPTION_LENGTH, CREDUI_MAX_MESSAGE_LENGTH,
};
Self {
title: truncate_to_char_boundary(title, CREDUI_MAX_CAPTION_LENGTH as usize),
description: truncate_to_char_boundary(
description,
CREDUI_MAX_MESSAGE_LENGTH as usize,
),
}
}
#[cfg(not(target_os = "windows"))]
pub fn new_truncated(title: &'a str, description: &'b str) -> Self {
Self { title, description }
}
}
#[cfg(target_os = "windows")]
fn truncate_to_char_boundary(s: &str, max_len: usize) -> &str {
if s.len() <= max_len {
return s;
}
let mut end = max_len;
while !s.is_char_boundary(end) {
end -= 1;
}
&s[..end]
}