libreoffice_rs/
urls.rs

1use std::fmt;
2use std::path::Path;
3use url::Url;
4
5use crate::error::Error;
6
7/// Type-safe URL "container" for LibreOffice documents
8#[derive(Debug, Clone)]
9pub struct DocUrl(String);
10
11impl fmt::Display for DocUrl {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13        write!(f, "{}", self.0)
14    }
15}
16
17/// Construct a type-safe `DocUrl` instance for a given path
18/// - This method **does check** if the file actually exists, which you may not want
19/// - If the provided file path is relative, then it'll be converted to an absolute path
20/// - Once the absolute path is obtained, this delegates to [local_as_abs]
21///
22/// # Arguments
23/// * `path` - An relative or absolute path that for an existing local file
24///
25/// ```
26/// use libreoffice_rs::urls;
27///
28/// # fn  main() -> Result<(), Box<dyn std::error::Error>> {
29/// let valid_url_ret = urls::local_into_abs("./test_data/test.odt");
30/// assert!(valid_url_ret.is_ok(), "{}", valid_url_ret.err().unwrap());
31///
32/// let invalid_url_ret = urls::local_into_abs("does_not_exist.odt");
33/// assert!(invalid_url_ret.is_err(), "Computed an absolute path URL for a nonexistent file!");
34///
35/// #  Ok(())
36/// # }
37/// ```
38pub fn local_into_abs<S: Into<String>>(path: S) -> Result<DocUrl, Error> {
39    let doc_path = path.into();
40
41    match std::fs::canonicalize(&doc_path) {
42        Ok(doc_abspath) => local_as_abs(doc_abspath.display().to_string()),
43        Err(ex) => {
44            let msg = format!("Does the file exist at {}? {}", doc_path, ex.to_string());
45            Err(Error::new(msg))
46        }
47    }
48}
49
50/// Construct a type-safe `DocUrl` instance for a given absolute local path
51/// - This method doesn't check if the file actually exists yet
52/// - The provided file path must be an absolute location, per LibreOffice expectations
53///
54/// # Arguments
55/// * `path` - An absolute path on the local filesystem
56///
57/// ```
58/// use libreoffice_rs::urls;
59///
60/// # fn  main() -> Result<(), Box<dyn std::error::Error>> {
61/// let relative_path_ret = urls::local_as_abs("./test_data/test.odt");
62/// assert!(relative_path_ret.is_err(), "{}", relative_path_ret.err().unwrap());
63///
64/// #  Ok(())
65/// # }
66/// ```
67pub fn local_as_abs<S: Into<String>>(path: S) -> Result<DocUrl, Error> {
68    let uri_location = path.into();
69    let p = Path::new(&uri_location);
70
71    if !p.is_absolute() {
72        return Err(Error::new(format!(
73            "The file path {} must be absolute!",
74            &uri_location
75        )));
76    }
77
78    let url_ret = Url::from_file_path(&uri_location);
79
80    match url_ret {
81        Ok(url_value) => Ok(DocUrl(url_value.as_str().to_owned())),
82        Err(ex) => {
83            return Err(Error::new(format!(
84                "Failed to parse as URL {}! {:?}",
85                uri_location, ex
86            )));
87        }
88    }
89}
90
91/// Construct a type-safe DocUrl instance if the document remote URI is valid
92///
93/// # Arguments
94/// * `uri` - A document URI
95///
96/// # Example
97///
98/// ```
99/// use libreoffice_rs::urls;
100///
101/// # fn  main() -> Result<(), Box<dyn std::error::Error>> {
102/// let valid_url_ret = urls::remote("http://google.com");
103///
104/// assert!(valid_url_ret.is_ok(), "{:?}", valid_url_ret.err());
105///
106/// #  Ok(())
107/// # }
108/// ```
109pub fn remote<S: Into<String>>(uri: S) -> Result<DocUrl, Error> {
110    let uri_location = uri.into();
111    let uri_location_str = uri_location.as_str();
112
113    if let Err(ex) = Url::parse(uri_location_str) {
114        return Err(Error::new(format!(
115            "Failed to parse URI {}! {}",
116            uri_location,
117            ex.to_string()
118        )));
119    }
120
121    Ok(DocUrl(uri_location))
122}