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}