gcs_reader/
uri.rs

1use color_eyre::eyre::{ensure, Result};
2
3use crate::errors::GCSObjectURIError;
4
5#[derive(Debug)]
6pub struct GCSObjectURI {
7    bucket: String,
8    object: String,
9}
10
11impl GCSObjectURI {
12    pub fn new(uri: &str) -> Result<Self> {
13        ensure!(&uri[..5] == "gs://", GCSObjectURIError::InvalidPrefix(uri.to_string()));
14        let mut parts = uri.splitn(2, "://");
15        let _ = parts.next().unwrap();
16        let path = parts.next().unwrap();
17        let mut parts = path.splitn(2, '/');
18        let bucket = parts.next().ok_or(GCSObjectURIError::MissingBucket)?;
19        let object = parts.next().ok_or(GCSObjectURIError::MissingObject)?;
20        ensure!(!bucket.is_empty(), GCSObjectURIError::MissingBucket);
21        ensure!(!object.is_empty(), GCSObjectURIError::MissingObject);
22        Ok(Self {
23            bucket: bucket.to_string(),
24            object: object.to_string(),
25        })
26    }
27
28    pub(crate) fn bucket(&self) -> &str {
29        &self.bucket
30    }
31
32    pub(crate) fn object(&self) -> &str {
33        &self.object
34    }
35
36    pub(crate) fn endpoint(&self) -> String {
37        let object = self.object.replace('/', "%2F");
38        format!(
39            "https://storage.googleapis.com/storage/v1/b/{}/o/{}",
40            self.bucket, object
41        )
42    }
43
44    pub(crate) fn uri(&self) -> String {
45        format!("gs://{}/{}", self.bucket, self.object)
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use crate::setup;
53
54    #[test]
55    fn test_valid_uri() {
56        setup();
57        let uri = "gs://my_bucket/my_object";
58        let gcs_obj = GCSObjectURI::new(uri).unwrap();
59        assert_eq!(gcs_obj.bucket(), "my_bucket");
60        assert_eq!(gcs_obj.object(), "my_object");
61    }
62
63    #[test]
64    fn test_invalid_prefix() {
65        setup();
66        let uri = "s3://my_bucket/my_object";
67        let gcs_obj = GCSObjectURI::new(uri);
68        assert!(gcs_obj.is_err());
69    }
70
71    #[test]
72    fn test_missing_object() {
73        setup();
74        let uri = "gs://my_bucket/";
75        let gcs_obj = GCSObjectURI::new(uri);
76        assert!(gcs_obj.is_err());
77    }
78
79    #[test]
80    fn test_missing_bucket_and_object() {
81        setup();
82        let uri = "gs://";
83        let gcs_obj = GCSObjectURI::new(uri);
84        assert!(gcs_obj.is_err());
85    }
86
87    #[test]
88    fn test_uri_method() {
89        setup();
90        let uri = "gs://my_bucket/my_object/folder";
91        let gcs_obj = GCSObjectURI::new(uri).unwrap();
92        assert_eq!(gcs_obj.uri(), "gs://my_bucket/my_object/folder");
93    }
94
95    #[test]
96    fn test_endpoint_method() {
97        setup();
98        let uri = "gs://my_bucket/my_object/folder";
99        let gcs_obj = GCSObjectURI::new(uri).unwrap();
100        assert_eq!(
101            gcs_obj.endpoint(),
102            "https://storage.googleapis.com/storage/v1/b/my_bucket/o/my_object%2Ffolder"
103        );
104    }
105}