Skip to content

Commit 0b95c40

Browse files
authored
Added support for x-ms-blob-content-md5 in PutBlockList (#148)
* Added support for x-ms-blob-content-md5 in PutBlockList * removed borrow in favor of Bytes * BlobBlockType now accepts BlockId * Implemented suggestions from rylev and ctaggart
1 parent 793878d commit 0b95c40

16 files changed

+155
-161
lines changed

sdk/storage/examples/blob_04.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use azure_core::prelude::*;
22
use azure_storage::blob::prelude::*;
33
use azure_storage::core::prelude::*;
4+
use bytes::{BufMut, Bytes};
45
use std::error::Error;
56
use std::sync::Arc;
67

@@ -27,15 +28,29 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
2728
.as_container_client(&container_name)
2829
.as_blob_client("test1");
2930

30-
let data = b"1337 azure blob test";
31+
// this example fills a 1 KB file with ASCII text and
32+
// sends it in chunks of 256 bytes (4 chunks).
33+
// It then finalizes the block blob by calling
34+
// PutBlockList. Finally it gets back
35+
// the blob as a whole.
36+
let mut data = bytes::BytesMut::with_capacity(1 * 1024);
37+
for _ in 0..1 * (1024 / 64) {
38+
data.put("the brown fox jumped over the lazy dog. 123456789Pangram12345678".as_bytes());
39+
}
40+
let data = data.freeze();
41+
42+
println!("data to send is {} bytes.", data.len());
43+
3144
let mut block_ids = Vec::new();
32-
for (i, block) in data.chunks(64 * 1024 * 1024 /* 64 MiB */).enumerate() {
33-
block_ids.push(i.to_be_bytes());
34-
let hash = md5::compute(block).into();
35-
let block_id = (&i.to_be_bytes() as &[u8]).into();
45+
for i in 0..(1024 / 256) {
46+
let slice = data.slice(i * 256..(i + 1) * 256);
47+
48+
let block_id = Bytes::from(format!("{}", i));
49+
block_ids.push(block_id.clone());
50+
let hash = md5::compute(slice.clone()).into();
3651

3752
let put_block_response = blob
38-
.put_block(&block_id, block)
53+
.put_block(block_id, slice)
3954
.hash(&hash)
4055
.execute()
4156
.await?;
@@ -44,9 +59,22 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
4459
}
4560

4661
let mut block_list = BlockList::default();
47-
for id in block_ids.iter() {
48-
block_list.blocks.push(BlobBlockType::Uncommitted(&id[..]));
62+
for id in block_ids.into_iter() {
63+
block_list.blocks.push(BlobBlockType::new_uncommitted(id));
4964
}
5065

66+
let res = blob
67+
.put_block_list(&block_list)
68+
.content_md5(md5::compute(data))
69+
.execute()
70+
.await?;
71+
println!("PutBlockList == {:?}", res);
72+
73+
let retrieved_blob = blob.get().execute().await?;
74+
println!("retrieved_blob == {:?}", retrieved_blob);
75+
76+
let s = String::from_utf8(retrieved_blob.data)?;
77+
println!("retrieved contents == {}", s);
78+
5179
Ok(())
5280
}

sdk/storage/examples/put_block_blob_00.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,15 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
5656
let mut block_list = BlockList::default();
5757
block_list
5858
.blocks
59-
.push(BlobBlockType::Uncommitted(b"satanasso" as &[u8]));
59+
.push(BlobBlockType::new_uncommitted("satanasso"));
6060
block_list
6161
.blocks
62-
.push(BlobBlockType::Uncommitted(b"pollastro" as &[u8]));
62+
.push(BlobBlockType::new_uncommitted("pollastro"));
6363

64-
let res = blob
65-
.put_block(&("satanasso".into()), data.clone())
66-
.execute()
67-
.await?;
64+
let res = blob.put_block("satanasso", data.clone()).execute().await?;
6865
println!("2-put_block {:?}", res);
6966

70-
let res = blob
71-
.put_block(&("pollastro".into()), data)
72-
.execute()
73-
.await?;
67+
let res = blob.put_block("pollastro", data).execute().await?;
7468
println!("3-put_block {:?}", res);
7569

7670
let ret = blob
Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1-
use std::borrow::Borrow;
1+
use crate::BlockId;
22

3-
// TODO: Change from Borrow<[u8]> to BlockId
4-
// Also, why Borrow? :| :|
53
#[derive(Debug, Clone, PartialEq)]
6-
pub enum BlobBlockType<T>
7-
where
8-
T: Borrow<[u8]>,
9-
{
10-
Committed(T),
11-
Uncommitted(T),
12-
Latest(T),
4+
pub enum BlobBlockType {
5+
Committed(BlockId),
6+
Uncommitted(BlockId),
7+
Latest(BlockId),
8+
}
9+
10+
impl BlobBlockType {
11+
pub fn new_committed(b: impl Into<BlockId>) -> Self {
12+
BlobBlockType::Committed(b.into())
13+
}
14+
15+
pub fn new_uncommitted(b: impl Into<BlockId>) -> Self {
16+
BlobBlockType::Uncommitted(b.into())
17+
}
18+
19+
pub fn new_latest(b: impl Into<BlockId>) -> Self {
20+
BlobBlockType::Latest(b.into())
21+
}
1322
}
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
use crate::blob::blob::BlobBlockType;
2-
use std::borrow::Borrow;
32

43
#[derive(Debug, Clone, PartialEq)]
5-
pub struct BlobBlockWithSize<T>
6-
where
7-
T: Borrow<[u8]>,
8-
{
9-
pub block_list_type: BlobBlockType<T>,
4+
pub struct BlobBlockWithSize {
5+
pub block_list_type: BlobBlockType,
106
pub size_in_bytes: u64,
117
}

sdk/storage/src/blob/blob/block_list.rs

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,12 @@
11
use crate::blob::blob::{BlobBlockType, BlockWithSizeList};
2-
use std::borrow::Borrow;
32

43
#[derive(Default, Debug, Clone, PartialEq)]
5-
pub struct BlockList<T>
6-
where
7-
T: Borrow<[u8]>,
8-
{
9-
pub blocks: Vec<BlobBlockType<T>>,
4+
pub struct BlockList {
5+
pub blocks: Vec<BlobBlockType>,
106
}
117

12-
impl<'a> BlockList<&'a [u8]> {
13-
pub fn to_owned(&self) -> BlockList<Vec<u8>> {
14-
let mut bl: BlockList<Vec<u8>> = BlockList {
15-
blocks: Vec::with_capacity(self.blocks.len()),
16-
};
17-
18-
for entry in &self.blocks {
19-
bl.blocks.push(match entry {
20-
BlobBlockType::Committed(id) => BlobBlockType::Committed(id.to_vec()),
21-
BlobBlockType::Uncommitted(id) => BlobBlockType::Uncommitted(id.to_vec()),
22-
BlobBlockType::Latest(id) => BlobBlockType::Latest(id.to_vec()),
23-
});
24-
}
25-
26-
bl
27-
}
28-
}
29-
30-
impl<T> From<BlockWithSizeList<T>> for BlockList<T>
31-
where
32-
T: Borrow<[u8]> + Default,
33-
{
34-
fn from(b: BlockWithSizeList<T>) -> BlockList<T> {
8+
impl From<BlockWithSizeList> for BlockList {
9+
fn from(b: BlockWithSizeList) -> BlockList {
3510
let mut bl = BlockList::default();
3611
for block in b.blocks {
3712
bl.blocks.push(block.block_list_type);
@@ -40,25 +15,24 @@ where
4015
}
4116
}
4217

43-
impl<T> BlockList<T>
44-
where
45-
T: Borrow<[u8]>,
46-
{
18+
impl BlockList {
4719
pub fn to_xml(&self) -> String {
4820
let mut s = String::new();
4921
s.push_str("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<BlockList>\n");
5022
for bl in &self.blocks {
5123
let node = match bl {
52-
BlobBlockType::Committed(content) => format!(
53-
"\t<Committed>{}</Committed>\n",
54-
base64::encode(content.borrow())
55-
),
24+
BlobBlockType::Committed(content) => {
25+
format!(
26+
"\t<Committed>{}</Committed>\n",
27+
base64::encode(content.as_ref())
28+
)
29+
}
5630
BlobBlockType::Uncommitted(content) => format!(
5731
"\t<Uncommitted>{}</Uncommitted>\n",
58-
base64::encode(content.borrow())
32+
base64::encode(content.as_ref())
5933
),
6034
BlobBlockType::Latest(content) => {
61-
format!("\t<Latest>{}</Latest>\n", base64::encode(content.borrow()))
35+
format!("\t<Latest>{}</Latest>\n", base64::encode(content.as_ref()))
6236
}
6337
};
6438

@@ -73,22 +47,21 @@ where
7347
#[cfg(test)]
7448
mod test {
7549
use super::*;
50+
use bytes::Bytes;
7651

7752
#[test]
7853
fn to_xml() {
7954
let mut blocks = BlockList { blocks: Vec::new() };
8055
blocks
8156
.blocks
82-
.push(BlobBlockType::Committed(Vec::from(b"numero1" as &[u8])));
83-
blocks
84-
.blocks
85-
.push(BlobBlockType::Uncommitted(Vec::from(b"numero2" as &[u8])));
57+
.push(BlobBlockType::new_committed(Bytes::from_static(b"numero1")));
8658
blocks
8759
.blocks
88-
.push(BlobBlockType::Uncommitted(Vec::from(b"numero3" as &[u8])));
60+
.push(BlobBlockType::new_uncommitted("numero2"));
8961
blocks
9062
.blocks
91-
.push(BlobBlockType::Latest(Vec::from(b"numero4" as &[u8])));
63+
.push(BlobBlockType::new_uncommitted("numero3"));
64+
blocks.blocks.push(BlobBlockType::new_latest("numero4"));
9265

9366
let _retu: &str = &blocks.to_xml();
9467

sdk/storage/src/blob/blob/block_with_size_list.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::blob::blob::BlobBlockType;
22
use crate::blob::blob::BlobBlockWithSize;
33
use azure_core::errors::AzureError;
4-
use std::borrow::Borrow;
54

65
#[derive(Debug, Deserialize)]
76
struct Name {
@@ -38,15 +37,12 @@ struct BlockList {
3837
}
3938

4039
#[derive(Default, Debug, Clone, PartialEq)]
41-
pub struct BlockWithSizeList<T>
42-
where
43-
T: Borrow<[u8]>,
44-
{
45-
pub blocks: Vec<BlobBlockWithSize<T>>,
40+
pub struct BlockWithSizeList {
41+
pub blocks: Vec<BlobBlockWithSize>,
4642
}
4743

48-
impl BlockWithSizeList<Vec<u8>> {
49-
pub fn try_from(xml: &str) -> Result<BlockWithSizeList<Vec<u8>>, AzureError> {
44+
impl BlockWithSizeList {
45+
pub fn try_from_xml(xml: &str) -> Result<Self, AzureError> {
5046
let bl: BlockList = serde_xml_rs::de::from_reader(xml.as_bytes())?;
5147
debug!("bl == {:?}", bl);
5248

@@ -56,7 +52,7 @@ impl BlockWithSizeList<Vec<u8>> {
5652
for b_val in b {
5753
lbs.blocks.push(BlobBlockWithSize {
5854
block_list_type: BlobBlockType::Committed(
59-
base64::decode(&b_val.name.value)?.to_owned(),
55+
base64::decode(&b_val.name.value)?.into(),
6056
),
6157
size_in_bytes: b_val.size.value,
6258
});
@@ -67,7 +63,7 @@ impl BlockWithSizeList<Vec<u8>> {
6763
for b_val in b {
6864
lbs.blocks.push(BlobBlockWithSize {
6965
block_list_type: BlobBlockType::Uncommitted(
70-
base64::decode(&b_val.name.value)?.to_owned(),
66+
base64::decode(&b_val.name.value)?.into(),
7167
),
7268
size_in_bytes: b_val.size.value,
7369
});
@@ -100,16 +96,15 @@ mod test {
10096
</UncommittedBlocks>
10197
</BlockList> ";
10298

103-
let bl = BlockWithSizeList::try_from(range).unwrap();
99+
let bl = BlockWithSizeList::try_from_xml(range).unwrap();
104100
assert!(bl.blocks.len() == 2);
105101
assert!(bl.blocks[0].size_in_bytes == 200);
106102
assert!(bl.blocks[1].size_in_bytes == 4096);
107103

108104
assert!(
109-
bl.blocks[0].block_list_type
110-
== BlobBlockType::Committed(Vec::from(b"base64-encoded-block-id" as &[u8]))
105+
bl.blocks[0].block_list_type == BlobBlockType::new_committed("base64-encoded-block-id")
111106
);
112-
let b2 = BlobBlockType::Uncommitted(Vec::from(b"base64-encoded-block-id-number2" as &[u8]));
107+
let b2 = BlobBlockType::new_uncommitted("base64-encoded-block-id-number2");
113108
assert!(
114109
bl.blocks[1].block_list_type == b2,
115110
"bl.blocks[1].block_list_type == {:?}, b2 == {:?}",
@@ -122,7 +117,7 @@ mod test {
122117
fn try_parse2() {
123118
let range = "<?xml version=\"1.0\" encoding=\"utf-8\"?><BlockList><CommittedBlocks /><UncommittedBlocks><Block><Name>YmxvY2sx</Name><Size>62</Size></Block><Block><Name>YmxvY2sy</Name><Size>62</Size></Block><Block><Name>YmxvY2sz</Name><Size>62</Size></Block></UncommittedBlocks></BlockList>";
124119

125-
let bl = BlockWithSizeList::try_from(range).unwrap();
120+
let bl = BlockWithSizeList::try_from_xml(range).unwrap();
126121
assert!(bl.blocks.len() == 3);
127122
assert!(bl.blocks[0].size_in_bytes == 62);
128123
assert!(bl.blocks[1].size_in_bytes == 62);

sdk/storage/src/blob/blob/mod.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use azure_core::{
3333
use chrono::{DateTime, Utc};
3434
use hyper::header;
3535
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
36-
use std::borrow::Borrow;
3736
use std::collections::HashMap;
3837
use std::str::FromStr;
3938
use xml::Element;
@@ -66,25 +65,6 @@ pub trait BlockListTypeRequired {
6665
}
6766
}
6867

69-
pub trait BlockListSupport<'a, T>
70-
where
71-
T: Borrow<[u8]>,
72-
{
73-
type O;
74-
fn with_block_list(self, _: &'a BlockList<T>) -> Self::O;
75-
}
76-
77-
pub trait BlockListRequired<'a, T>
78-
where
79-
T: Borrow<[u8]> + 'a,
80-
{
81-
fn block_list(&self) -> &'a BlockList<T>;
82-
83-
fn to_string(&self) -> String {
84-
self.block_list().to_xml()
85-
}
86-
}
87-
8868
create_enum!(
8969
BlobType,
9070
(BlockBlob, "BlockBlob"),

sdk/storage/src/blob/blob/requests/put_block_builder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use bytes::Bytes;
88
#[derive(Debug, Clone)]
99
pub struct PutBlockBuilder<'a> {
1010
blob_client: &'a BlobClient,
11-
block_id: &'a BlockId,
11+
block_id: BlockId,
1212
body: Bytes,
1313
hash: Option<&'a Hash>,
1414
client_request_id: Option<ClientRequestId<'a>>,
@@ -19,12 +19,12 @@ pub struct PutBlockBuilder<'a> {
1919
impl<'a> PutBlockBuilder<'a> {
2020
pub(crate) fn new(
2121
blob_client: &'a BlobClient,
22-
block_id: &'a BlockId,
22+
block_id: impl Into<BlockId>,
2323
body: impl Into<Bytes>,
2424
) -> Self {
2525
Self {
2626
blob_client,
27-
block_id,
27+
block_id: block_id.into(),
2828
body: body.into(),
2929
hash: None,
3030
client_request_id: None,

0 commit comments

Comments
 (0)