azure_storage/
lib.rs

1#![doc = include_str!("../README.md")]
2#![recursion_limit = "256"]
3#![allow(clippy::needless_lifetimes)]
4#![allow(clippy::enum_variant_names)]
5#![allow(clippy::new_without_default)]
6
7#[macro_use]
8extern crate serde_derive;
9#[macro_use]
10extern crate azure_core;
11
12mod authorization;
13pub mod clients;
14mod cloud_location;
15mod connection_string;
16mod connection_string_builder;
17mod copy_id;
18mod copy_progress;
19mod macros;
20pub mod prelude;
21pub mod shared_access_signature;
22
23pub use self::connection_string::{ConnectionString, EndpointProtocol};
24pub use self::connection_string_builder::ConnectionStringBuilder;
25pub use authorization::{StorageCredentials, StorageCredentialsInner};
26pub use cloud_location::*;
27pub mod headers;
28pub use copy_id::{copy_id_from_headers, CopyId};
29pub use copy_progress::CopyProgress;
30pub mod parsing_xml;
31mod stored_access_policy;
32pub use azure_core::error::{Error, ErrorKind, ResultExt};
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct IPRange {
36    pub start: std::net::IpAddr,
37    pub end: std::net::IpAddr,
38}
39
40pub use stored_access_policy::{StoredAccessPolicy, StoredAccessPolicyList};
41
42pub use consistency::{ConsistencyCRC64, ConsistencyMD5};
43
44mod consistency {
45    use azure_core::{
46        base64,
47        error::{Error, ErrorKind},
48    };
49    use bytes::Bytes;
50    use serde::{Deserialize, Deserializer};
51    use std::str::FromStr;
52
53    #[derive(Debug, Clone, PartialEq, Eq)]
54    pub struct ConsistencyCRC64(Bytes);
55
56    const CRC64_BYTE_LENGTH: usize = 8;
57
58    impl ConsistencyCRC64 {
59        /// Decodes from base64 encoded input
60        pub fn decode(input: impl AsRef<[u8]>) -> azure_core::Result<Self> {
61            let bytes = base64::decode(input)?;
62            let bytes = Bytes::from(bytes);
63            match bytes.len() {
64                CRC64_BYTE_LENGTH => Ok(Self(bytes)),
65                len => Err(Error::with_message(ErrorKind::Other, || {
66                    format!("CRC64 not 8 bytes long. len: {len}")
67                })),
68            }
69        }
70        pub fn bytes(&self) -> &Bytes {
71            &self.0
72        }
73        pub fn as_slice(&self) -> &[u8; CRC64_BYTE_LENGTH] {
74            // we check the length when decoding, so this unwrap is safe
75            self.0.as_ref().try_into().unwrap()
76        }
77    }
78
79    impl AsRef<[u8; CRC64_BYTE_LENGTH]> for ConsistencyCRC64 {
80        fn as_ref(&self) -> &[u8; CRC64_BYTE_LENGTH] {
81            self.as_slice()
82        }
83    }
84
85    impl<'de> Deserialize<'de> for ConsistencyCRC64 {
86        fn deserialize<D>(
87            deserializer: D,
88        ) -> std::result::Result<Self, <D as Deserializer<'de>>::Error>
89        where
90            D: Deserializer<'de>,
91        {
92            let bytes = String::deserialize(deserializer)?;
93            ConsistencyCRC64::decode(bytes).map_err(serde::de::Error::custom)
94        }
95    }
96
97    impl FromStr for ConsistencyCRC64 {
98        type Err = azure_core::error::Error;
99
100        fn from_str(s: &str) -> Result<Self, Self::Err> {
101            Self::decode(s)
102        }
103    }
104
105    #[derive(Debug, Clone, PartialEq, Eq)]
106    pub struct ConsistencyMD5(Bytes);
107
108    const MD5_BYTE_LENGTH: usize = 16;
109
110    impl ConsistencyMD5 {
111        /// Decodes from base64 encoded input
112        pub fn decode(input: impl AsRef<[u8]>) -> azure_core::Result<Self> {
113            let bytes = base64::decode(input)?;
114            let bytes = Bytes::from(bytes);
115            match bytes.len() {
116                MD5_BYTE_LENGTH => Ok(Self(bytes)),
117                len => Err(Error::with_message(ErrorKind::Other, || {
118                    format!("MD5 digest not 16 bytes long. len: {len}")
119                })),
120            }
121        }
122        pub fn bytes(&self) -> &Bytes {
123            &self.0
124        }
125        pub fn as_slice(&self) -> &[u8; MD5_BYTE_LENGTH] {
126            // we check the length when decoding, so this unwrap is safe
127            self.0.as_ref().try_into().unwrap()
128        }
129    }
130
131    impl AsRef<[u8; MD5_BYTE_LENGTH]> for ConsistencyMD5 {
132        fn as_ref(&self) -> &[u8; MD5_BYTE_LENGTH] {
133            self.as_slice()
134        }
135    }
136
137    impl<'de> Deserialize<'de> for ConsistencyMD5 {
138        fn deserialize<D>(
139            deserializer: D,
140        ) -> std::result::Result<Self, <D as Deserializer<'de>>::Error>
141        where
142            D: Deserializer<'de>,
143        {
144            let bytes = String::deserialize(deserializer)?;
145            ConsistencyMD5::decode(bytes).map_err(serde::de::Error::custom)
146        }
147    }
148
149    impl FromStr for ConsistencyMD5 {
150        type Err = azure_core::error::Error;
151
152        fn from_str(s: &str) -> Result<Self, Self::Err> {
153            Self::decode(s)
154        }
155    }
156
157    #[cfg(test)]
158    mod test {
159        use super::*;
160        use serde::de::value::{Error, StringDeserializer};
161        use serde::de::IntoDeserializer;
162
163        #[test]
164        fn should_deserialize_consistency_crc64() {
165            let input = base64::encode([1, 2, 4, 8, 16, 32, 64, 128]);
166            let deserializer: StringDeserializer<Error> = input.into_deserializer();
167            let content_crc64 = ConsistencyCRC64::deserialize(deserializer).unwrap();
168            assert_eq!(
169                content_crc64,
170                ConsistencyCRC64(Bytes::from_static(&[1, 2, 4, 8, 16, 32, 64, 128]))
171            );
172        }
173
174        #[test]
175        fn should_deserialize_consistency_md5() {
176            let input = base64::encode([1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128]);
177            let deserializer: StringDeserializer<Error> = input.into_deserializer();
178            let content_md5 = ConsistencyMD5::deserialize(deserializer).unwrap();
179            assert_eq!(
180                content_md5,
181                ConsistencyMD5(Bytes::from_static(&[
182                    1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128
183                ]))
184            );
185        }
186    }
187}