Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion sdk/storage_blobs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ serde_json = "1.0"
serde-xml-rs = "0.5"
uuid = { version = "1.0", features = ["v4"] }
url = "2.2"
thiserror = "1.0"

[dev-dependencies]
tokio = { version = "1.0", features = ["full"] }
Expand Down
56 changes: 31 additions & 25 deletions sdk/storage_blobs/src/ba512_range.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Not512ByteAlignedError, Parse512AlignedError};
use azure_core::error::{Error, ErrorKind, Result, ResultExt};
use azure_core::headers::{self, Header};
use azure_core::prelude::Range;
use std::convert::TryFrom;
Expand All @@ -19,12 +19,16 @@ impl BA512Range {
self.end
}

pub fn new(start: u64, end: u64) -> Result<Self, Not512ByteAlignedError> {
pub fn new(start: u64, end: u64) -> Result<Self> {
if start % 512 != 0 {
return Err(Not512ByteAlignedError::StartRange(start));
return Err(Error::with_message(ErrorKind::Other, || {
format!("start range not 512-byte aligned: {}", start)
}));
}
if (end + 1) % 512 != 0 {
return Err(Not512ByteAlignedError::EndRange(end));
return Err(Error::with_message(ErrorKind::Other, || {
format!("end range not 512-byte aligned: {}", end)
}));
}

Ok(Self { start, end })
Expand All @@ -46,17 +50,17 @@ impl From<BA512Range> for Range {
}

impl TryFrom<Range> for BA512Range {
type Error = Not512ByteAlignedError;
type Error = Error;

fn try_from(r: Range) -> Result<Self, Self::Error> {
fn try_from(r: Range) -> Result<Self> {
BA512Range::new(r.start, r.end)
}
}

impl TryFrom<(u64, u64)> for BA512Range {
type Error = Not512ByteAlignedError;
type Error = Error;

fn try_from((start, end): (u64, u64)) -> Result<Self, Self::Error> {
fn try_from((start, end): (u64, u64)) -> Result<Self> {
BA512Range::new(start, end)
}
}
Expand All @@ -72,17 +76,25 @@ impl Header for BA512Range {
}

impl FromStr for BA512Range {
type Err = Parse512AlignedError;
fn from_str(s: &str) -> Result<BA512Range, Self::Err> {
type Err = Error;
fn from_str(s: &str) -> Result<BA512Range> {
let v = s.split('/').collect::<Vec<&str>>();
if v.len() != 2 {
return Err(Parse512AlignedError::SplitNotFound);
return Err(Error::message(ErrorKind::Other, "split not found"));
}

let cp_start = v[0].parse::<u64>()?;
let cp_end = v[1].parse::<u64>()?;
let cp_start = v[0]
.parse::<u64>()
.with_context(ErrorKind::DataConversion, || {
format!("error parsing '{}' into u64", v[0])
})?;
let cp_end = v[1]
.parse::<u64>()
.with_context(ErrorKind::DataConversion, || {
format!("error parsing '{}' into u64", v[1])
})?;

Ok(BA512Range::new(cp_start, cp_end)?)
BA512Range::new(cp_start, cp_end)
}
}

Expand All @@ -104,7 +116,7 @@ impl<'a> From<&'a BA512Range> for Range {
#[cfg(test)]
mod test {
use super::*;
use crate::Not512ByteAlignedError::{EndRange, StartRange};
use azure_core::error::ErrorKind;

#[test]
fn test_512range_parse() {
Expand All @@ -117,31 +129,25 @@ mod test {
#[test]
fn test_512range_parse_panic_1() {
let err = "abba/2000".parse::<BA512Range>().unwrap_err();
assert!(matches!(err, Parse512AlignedError::ParseIntError(_)));
assert!(matches!(err.kind(), ErrorKind::DataConversion));
}

#[test]
fn test_512range_parse_panic_2() {
let err = "1000-2000".parse::<BA512Range>().unwrap_err();
assert_eq!(err, Parse512AlignedError::SplitNotFound);
assert!(matches!(err.kind(), ErrorKind::Other));
}

#[test]
fn test_512range_invalid_start_range() {
let err = "7/511".parse::<BA512Range>().unwrap_err();
assert_eq!(
err,
Parse512AlignedError::Not512ByteAlignedError(StartRange(7))
);
assert!(matches!(err.kind(), ErrorKind::Other));
}

#[test]
fn test_512range_invalid_end_range() {
let err = "0/100".parse::<BA512Range>().unwrap_err();
assert_eq!(
err,
Parse512AlignedError::Not512ByteAlignedError(EndRange(100))
);
assert!(matches!(err.kind(), ErrorKind::Other));
}

#[test]
Expand Down
13 changes: 10 additions & 3 deletions sdk/storage_blobs/src/blob/block_with_size_list.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::blob::BlobBlockType;
use crate::blob::BlobBlockWithSize;
use azure_core::error::{ErrorKind, ResultExt};

#[derive(Debug, Deserialize)]
struct Name {
#[serde(rename = "$value")]
Expand Down Expand Up @@ -41,7 +43,8 @@ pub struct BlockWithSizeList {

impl BlockWithSizeList {
pub fn try_from_xml(xml: &str) -> crate::Result<Self> {
let bl: BlockList = serde_xml_rs::de::from_reader(xml.as_bytes())?;
let bl: BlockList =
serde_xml_rs::de::from_reader(xml.as_bytes()).map_kind(ErrorKind::DataConversion)?;
debug!("bl == {:?}", bl);

let mut lbs = BlockWithSizeList { blocks: Vec::new() };
Expand All @@ -50,7 +53,9 @@ impl BlockWithSizeList {
for b_val in b {
lbs.blocks.push(BlobBlockWithSize {
block_list_type: BlobBlockType::Committed(
base64::decode(&b_val.name.value)?.into(),
base64::decode(&b_val.name.value)
.map_kind(ErrorKind::DataConversion)?
.into(),
),
size_in_bytes: b_val.size.value,
});
Expand All @@ -61,7 +66,9 @@ impl BlockWithSizeList {
for b_val in b {
lbs.blocks.push(BlobBlockWithSize {
block_list_type: BlobBlockType::Uncommitted(
base64::decode(&b_val.name.value)?.into(),
base64::decode(&b_val.name.value)
.map_kind(ErrorKind::DataConversion)?
.into(),
),
size_in_bytes: b_val.size.value,
});
Expand Down
73 changes: 46 additions & 27 deletions sdk/storage_blobs/src/blob/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub use self::page_range_list::PageRangeList;
pub mod requests;
pub mod responses;
use crate::AccessTier;
use azure_core::error::{Error, ErrorKind, ResultExt};
use azure_core::headers::{
BLOB_ACCESS_TIER, BLOB_SEQUENCE_NUMBER, BLOB_TYPE, COPY_COMPLETION_TIME, COPY_PROGRESS,
COPY_SOURCE, COPY_STATUS, COPY_STATUS_DESCRIPTION, CREATION_TIME, LEASE_DURATION, LEASE_STATE,
Expand Down Expand Up @@ -205,9 +206,11 @@ impl Blob {
let creation_time = {
let creation_time = h
.get(CREATION_TIME)
.ok_or_else(|| crate::Error::HeaderNotFound(CREATION_TIME.to_owned()))?
.to_str()?;
let creation_time = DateTime::parse_from_rfc2822(creation_time)?;
.ok_or_else(|| Error::message(ErrorKind::DataConversion, CREATION_TIME))?
.to_str()
.map_kind(ErrorKind::DataConversion)?;
let creation_time =
DateTime::parse_from_rfc2822(creation_time).map_kind(ErrorKind::DataConversion)?;
let creation_time = DateTime::from_utc(creation_time.naive_utc(), Utc);
trace!("creation_time == {:?}", creation_time);
creation_time
Expand All @@ -224,22 +227,24 @@ impl Blob {
.get(header::CONTENT_LENGTH)
.ok_or_else(|| {
static CL: header::HeaderName = header::CONTENT_LENGTH;
crate::Error::HeaderNotFound(CL.as_str().to_owned())
Error::message(ErrorKind::DataConversion, CL.as_str())
})?
.to_str()?
.parse::<u64>()?;
.to_str()
.map_kind(ErrorKind::DataConversion)?
.parse::<u64>()
.map_kind(ErrorKind::DataConversion)?;
trace!("content_length == {:?}", content_length);

let last_modified = h.get_as_str(header::LAST_MODIFIED).ok_or_else(|| {
static LM: header::HeaderName = header::LAST_MODIFIED;
crate::Error::HeaderNotFound(LM.as_str().to_owned())
Error::message(ErrorKind::DataConversion, LM.as_str())
})?;
let last_modified = from_azure_time(last_modified)?;
let last_modified = from_azure_time(last_modified).map_kind(ErrorKind::DataConversion)?;
trace!("last_modified == {:?}", last_modified);

let etag = h.get_as_string(header::ETAG).ok_or_else(|| {
static E: header::HeaderName = header::ETAG;
crate::Error::HeaderNotFound(E.as_str().to_owned())
Error::message(ErrorKind::DataConversion, E.as_str())
})?;
let etag = etag.into();
trace!("etag == {:?}", etag);
Expand All @@ -249,17 +254,21 @@ impl Blob {

let blob_type = h
.get_as_str(BLOB_TYPE)
.ok_or_else(|| crate::Error::HeaderNotFound(BLOB_TYPE.to_owned()))?
.parse::<BlobType>()?;
.ok_or_else(|| Error::message(ErrorKind::DataConversion, BLOB_TYPE))?
.parse::<BlobType>()
.map_kind(ErrorKind::DataConversion)?;
trace!("blob_type == {:?}", blob_type);

let blob_type = h
.get_as_str(BLOB_TYPE)
.ok_or_else(|| crate::Error::HeaderNotFound(BLOB_TYPE.to_owned()))?
.parse::<BlobType>()?;
.ok_or_else(|| Error::message(ErrorKind::DataConversion, BLOB_TYPE))?
.parse::<BlobType>()
.map_kind(ErrorKind::DataConversion)?;
trace!("blob_type == {:?}", blob_type);

let access_tier = h.get_as_enum(BLOB_ACCESS_TIER)?;
let access_tier = h
.get_as_enum(BLOB_ACCESS_TIER)
.map_kind(ErrorKind::DataConversion)?;
trace!("blob_access_tier == {:?}", access_tier);

let content_encoding = h.get_as_string(header::CONTENT_ENCODING);
Expand All @@ -271,39 +280,48 @@ impl Blob {
let content_md5 = h
.get_header(CONTENT_MD5)
.map(|header| ConsistencyMD5::decode(header.as_bytes()))
.transpose()?;
.transpose()
.map_kind(ErrorKind::DataConversion)?;
trace!("content_md5 == {:?}", content_md5);

let content_crc64 = h
.get_header(CONTENT_CRC64)
.map(|header| ConsistencyCRC64::decode(header.as_bytes()))
.transpose()?;
.transpose()
.map_kind(ErrorKind::DataConversion)?;
trace!("content_crc64 == {:?}", content_crc64);

let cache_control = h.get_as_string(header::CACHE_CONTROL);

let content_disposition = h.get_as_string(header::CONTENT_DISPOSITION);

let lease_status = h
.get_as_enum(LEASE_STATUS)?
.ok_or_else(|| crate::Error::HeaderNotFound(LEASE_STATUS.to_owned()))?;
.get_as_enum(LEASE_STATUS)
.map_kind(ErrorKind::DataConversion)?
.ok_or_else(|| Error::message(ErrorKind::DataConversion, LEASE_STATUS))?;
trace!("lease_status == {:?}", lease_status);

let lease_state = h
.get_as_enum(LEASE_STATE)?
.ok_or_else(|| crate::Error::HeaderNotFound(LEASE_STATE.to_owned()))?;
.get_as_enum(LEASE_STATE)
.map_kind(ErrorKind::DataConversion)?
.ok_or_else(|| Error::message(ErrorKind::DataConversion, LEASE_STATE))?;
trace!("lease_state == {:?}", lease_state);

let lease_duration = h.get_as_enum(LEASE_DURATION)?;
let lease_duration = h
.get_as_enum(LEASE_DURATION)
.map_kind(ErrorKind::DataConversion)?;
trace!("lease_duration == {:?}", lease_duration);

let copy_id = h
.get_as_string(COPY_ID)
.map(|c| (&c as &str).try_into())
.transpose()?;
.transpose()
.map_kind(ErrorKind::DataConversion)?;
trace!("copy_id == {:?}", copy_id);

let copy_status = h.get_as_enum(COPY_STATUS)?;
let copy_status = h
.get_as_enum(COPY_STATUS)
.map_kind(ErrorKind::DataConversion)?;
trace!("copy_status == {:?}", copy_status);

let copy_source = h.get_as_string(COPY_SOURCE);
Expand All @@ -328,8 +346,9 @@ impl Blob {

let server_encrypted = h
.get_as_str(SERVER_ENCRYPTED)
.ok_or_else(|| crate::Error::HeaderNotFound(SERVER_ENCRYPTED.to_owned()))?
.parse::<bool>()?;
.ok_or_else(|| Error::message(ErrorKind::DataConversion, SERVER_ENCRYPTED))?
.parse::<bool>()
.map_kind(ErrorKind::DataConversion)?;

let mut metadata = HashMap::new();
for (name, value) in h.iter() {
Expand Down Expand Up @@ -402,6 +421,6 @@ impl Blob {
pub(crate) fn copy_status_from_headers(headers: &http::HeaderMap) -> crate::Result<CopyStatus> {
let val = headers
.get_as_str(azure_core::headers::COPY_STATUS)
.ok_or_else(|| crate::Error::HeaderNotFound(azure_core::headers::COPY_STATUS.to_owned()))?;
Ok(CopyStatus::from_str(val)?)
.ok_or_else(|| Error::message(ErrorKind::DataConversion, COPY_STATUS))?;
CopyStatus::from_str(val).map_kind(ErrorKind::DataConversion)
}
4 changes: 3 additions & 1 deletion sdk/storage_blobs/src/blob/page_range_list.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use azure_core::error::{ErrorKind, ResultExt};
use azure_core::prelude::Range;

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -33,7 +34,8 @@ pub struct PageRangeList {

impl PageRangeList {
pub fn try_from_xml(xml: &str) -> crate::Result<Self> {
let pl: PageList = serde_xml_rs::de::from_reader(xml.as_bytes())?;
let pl: PageList =
serde_xml_rs::de::from_reader(xml.as_bytes()).map_kind(ErrorKind::DataConversion)?;
debug!("pl == {:?}", pl);

let mut prl = PageRangeList { ranges: Vec::new() };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::blob::responses::GetBlobPropertiesResponse;
use crate::prelude::*;
use azure_core::error::Result;
use azure_core::headers::{add_optional_header, add_optional_header_ref};
use azure_core::prelude::*;

Expand Down Expand Up @@ -30,9 +31,7 @@ impl<'a> GetBlobPropertiesBuilder<'a> {
client_request_id: ClientRequestId => Some(client_request_id),
}

pub async fn execute(
&self,
) -> Result<GetBlobPropertiesResponse, Box<dyn std::error::Error + Send + Sync>> {
pub async fn execute(&self) -> Result<GetBlobPropertiesResponse> {
let mut url = self.blob_client.url_with_segments(None)?;

self.timeout.append_to_url_query(&mut url);
Expand Down Expand Up @@ -62,9 +61,6 @@ impl<'a> GetBlobPropertiesBuilder<'a> {
// TODO: Fix this
//let blob = Blob::from_headers(&blob_name, &container_name, snapshot_time, &headers)?;
let blob = Blob::from_headers(self.blob_client.blob_name(), response.headers())?;
Ok(GetBlobPropertiesResponse::from_response(
response.headers(),
blob,
)?)
GetBlobPropertiesResponse::from_response(response.headers(), blob)
}
}
Loading