#![recursion_limit = "256"]
#![allow(clippy::needless_lifetimes)]
#![allow(clippy::enum_variant_names)]
#![allow(clippy::new_without_default)]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate azure_core;
mod authorization;
pub mod clients;
mod cloud_location;
mod connection_string;
mod connection_string_builder;
mod copy_id;
mod copy_progress;
mod macros;
pub mod prelude;
pub mod shared_access_signature;
pub use self::connection_string::{ConnectionString, EndpointProtocol};
pub use self::connection_string_builder::ConnectionStringBuilder;
pub use authorization::{StorageCredentials, StorageCredentialsInner};
pub use cloud_location::*;
pub mod headers;
pub use copy_id::{copy_id_from_headers, CopyId};
pub use copy_progress::CopyProgress;
pub mod parsing_xml;
mod stored_access_policy;
pub use azure_core::error::{Error, ErrorKind, ResultExt};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IPRange {
pub start: std::net::IpAddr,
pub end: std::net::IpAddr,
}
pub use stored_access_policy::{StoredAccessPolicy, StoredAccessPolicyList};
pub use consistency::{ConsistencyCRC64, ConsistencyMD5};
mod consistency {
use azure_core::{
base64,
error::{Error, ErrorKind},
};
use bytes::Bytes;
use serde::{Deserialize, Deserializer};
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConsistencyCRC64(Bytes);
const CRC64_BYTE_LENGTH: usize = 8;
impl ConsistencyCRC64 {
pub fn decode(input: impl AsRef<[u8]>) -> azure_core::Result<Self> {
let bytes = base64::decode(input)?;
let bytes = Bytes::from(bytes);
match bytes.len() {
CRC64_BYTE_LENGTH => Ok(Self(bytes)),
len => Err(Error::with_message(ErrorKind::Other, || {
format!("CRC64 not 8 bytes long. len: {len}")
})),
}
}
pub fn bytes(&self) -> &Bytes {
&self.0
}
pub fn as_slice(&self) -> &[u8; CRC64_BYTE_LENGTH] {
self.0.as_ref().try_into().unwrap()
}
}
impl AsRef<[u8; CRC64_BYTE_LENGTH]> for ConsistencyCRC64 {
fn as_ref(&self) -> &[u8; CRC64_BYTE_LENGTH] {
self.as_slice()
}
}
impl<'de> Deserialize<'de> for ConsistencyCRC64 {
fn deserialize<D>(
deserializer: D,
) -> std::result::Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
let bytes = String::deserialize(deserializer)?;
ConsistencyCRC64::decode(bytes).map_err(serde::de::Error::custom)
}
}
impl FromStr for ConsistencyCRC64 {
type Err = azure_core::error::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::decode(s)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConsistencyMD5(Bytes);
const MD5_BYTE_LENGTH: usize = 16;
impl ConsistencyMD5 {
pub fn decode(input: impl AsRef<[u8]>) -> azure_core::Result<Self> {
let bytes = base64::decode(input)?;
let bytes = Bytes::from(bytes);
match bytes.len() {
MD5_BYTE_LENGTH => Ok(Self(bytes)),
len => Err(Error::with_message(ErrorKind::Other, || {
format!("MD5 digest not 16 bytes long. len: {len}")
})),
}
}
pub fn bytes(&self) -> &Bytes {
&self.0
}
pub fn as_slice(&self) -> &[u8; MD5_BYTE_LENGTH] {
self.0.as_ref().try_into().unwrap()
}
}
impl AsRef<[u8; MD5_BYTE_LENGTH]> for ConsistencyMD5 {
fn as_ref(&self) -> &[u8; MD5_BYTE_LENGTH] {
self.as_slice()
}
}
impl<'de> Deserialize<'de> for ConsistencyMD5 {
fn deserialize<D>(
deserializer: D,
) -> std::result::Result<Self, <D as Deserializer<'de>>::Error>
where
D: Deserializer<'de>,
{
let bytes = String::deserialize(deserializer)?;
ConsistencyMD5::decode(bytes).map_err(serde::de::Error::custom)
}
}
impl FromStr for ConsistencyMD5 {
type Err = azure_core::error::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::decode(s)
}
}
#[cfg(test)]
mod test {
use super::*;
use serde::de::value::{Error, StringDeserializer};
use serde::de::IntoDeserializer;
#[test]
fn should_deserialize_consistency_crc64() {
let input = base64::encode([1, 2, 4, 8, 16, 32, 64, 128]);
let deserializer: StringDeserializer<Error> = input.into_deserializer();
let content_crc64 = ConsistencyCRC64::deserialize(deserializer).unwrap();
assert_eq!(
content_crc64,
ConsistencyCRC64(Bytes::from_static(&[1, 2, 4, 8, 16, 32, 64, 128]))
);
}
#[test]
fn should_deserialize_consistency_md5() {
let input = base64::encode([1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128]);
let deserializer: StringDeserializer<Error> = input.into_deserializer();
let content_md5 = ConsistencyMD5::deserialize(deserializer).unwrap();
assert_eq!(
content_md5,
ConsistencyMD5(Bytes::from_static(&[
1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128
]))
);
}
}
}