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 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 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 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 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}