Skip to content
This repository was archived by the owner on Oct 6, 2020. It is now read-only.

Commit 6cd03e3

Browse files
committed
Merge pull request #5 from MindFlavor/candidate
put and clear page, max_results and next_marker in Blob::list, refactoring
2 parents e464b09 + e0185e1 commit 6cd03e3

File tree

15 files changed

+681
-230
lines changed

15 files changed

+681
-230
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ env:
4343
# override the default `--features unstable` used for the nightly branch (optional)
4444
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
4545
# encrypted github token for doc upload (see `GH_TOKEN` link above)
46-
- secure: "..."
46+
- secure: "${GH_TOKEN}"

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Change Log
22

3+
## [0.0.6](https://github.com/MindFlavor/AzureSDKForRust/releases/tag/0.0.6) (2016-01-12)
4+
5+
**Implemented features:**
6+
* Added support for max_results in list_blobs. Now you can limit how many blobs could be returned by a single call.
7+
* Added support for next_marker in list_blobs. Now you can continue enumerating your blobs in subsequent calls.
8+
* Added put page for page blobs.
9+
* Added clear page for page blobs.
10+
11+
**Refactoring:**
12+
* Added page constraints (512-bytes aligned).
13+
* Most methods moved from storage::Client to correct structs (ie storage::container::Container and storage::blob::Blob).
14+
* Moved list_blobs options in a separate structure (```azure::storage::blob::ListBlobOptions```).
15+
316
## [0.0.5](https://github.com/MindFlavor/AzureSDKForRust/releases/tag/0.0.5) (2016-01-05)
417

518
**Implemented features:**

Cargo.lock

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "azure_sdk_for_rust"
3-
version = "0.0.5"
3+
version = "0.0.6"
44
authors = ["Francesco Cogno <[email protected]>"]
55

66
[dependencies]

README.md

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,89 @@ Although I am a Microsoft employee, this is not a Microsoft endorsed project. It
1616
You can find examples in the test section (not yet existent as far as Azure is concerned) and in the main.rs file. Here is a sample however:
1717

1818
```rust
19-
use azure::storage::client;
20-
use azure::storage::container::PublicAccess;
19+
extern crate azure_sdk_for_rust;
20+
extern crate chrono;
21+
#[macro_use]
22+
extern crate mime;
23+
24+
use azure::storage::{LeaseState, LeaseStatus};
25+
use azure::storage::client::Client;
26+
use azure::storage::blob::{Blob, BlobType};
27+
use azure::storage::container::{Container, PublicAccess};
28+
29+
use chrono::UTC;
30+
31+
use mime::Mime;
2132

2233
fn main() {
23-
let azure_storage_account = &"azure_storage_account";
24-
let azure_storage_key= &"azure_storage_key";
25-
26-
// create the client struct. The third argument, if false, forces to use
27-
// http instead of https. It's useful if you have trouble compiling
28-
// hyper with openSSL activated.
29-
let client = client::new(azure_storage_account, azure_storage_key, false);
30-
31-
// This call will create a new Azure Container called "wow"
32-
// with public blob access (see https://msdn.microsoft.com/en-us/library/azure/dd179468.aspx).
33-
client.create_container("wow", PublicAccess::Blob).unwrap();
34-
35-
// This call will list your containers.
36-
let mut ret = client.list_containers().unwrap();
37-
println!("{:?}", ret);
38-
39-
// This code will look for the "todelete" container and
40-
// remove from Azure.
41-
let mut to_delete = ret.iter_mut().find(|x| x.name == "todelete").unwrap();
42-
to_delete.delete(&client).unwrap();
43-
println!("{:?} deleted!", to_delete);
34+
let azure_storage_account = &"azure_storage_account";
35+
let azure_storage_key= &"azure_storage_key";
36+
37+
// create the client struct. The third argument, if false, forces to use
38+
// http instead of https. It's useful if you have trouble compiling
39+
// hyper with openSSL activated.
40+
let client = client::new(azure_storage_account, azure_storage_key, false);
41+
42+
43+
// This call will list your containers.
44+
let containers = Container::list(&client).unwrap();
45+
println!("{:?}", ret);
46+
47+
// This call will create a new Azure Container called "wow"
48+
// with public blob access (see https://msdn.microsoft.com/en-us/library/azure/dd179468.aspx)
49+
// if it doesn't exist already.
50+
let cont = containers.iter().find(|x| x.name == container_name);
51+
if let None = cont {
52+
Container::create(&client, container_name, PublicAccess::Blob).unwrap();
53+
}
54+
55+
// this code will upload a file to the container just created.
56+
{
57+
use std::fs::metadata;
58+
use std::fs::File;
59+
60+
let file_name: &'static str = "C:\\temp\\from_rust.txt";
61+
let container_name: &'static str = "wow";
62+
63+
let metadata = metadata(file_name).unwrap();
64+
let mut file = File::open(file_name).unwrap();
65+
66+
let new_blob = Blob {
67+
name: "from_rust.txt".to_owned(),
68+
snapshot_time: None,
69+
last_modified: UTC::now(),
70+
etag: "".to_owned(),
71+
content_length: metadata.len(),
72+
content_type: "application/octet-stream".parse::<Mime>().unwrap(),
73+
content_encoding: None,
74+
content_language: None,
75+
content_md5: None,
76+
cache_control: None,
77+
x_ms_blob_sequence_number: None,
78+
blob_type: BlobType::BlockBlob,
79+
lease_status: LeaseStatus::Unlocked,
80+
lease_state: LeaseState::Available,
81+
lease_duration: None,
82+
copy_id: None,
83+
copy_status: None,
84+
copy_source: None,
85+
copy_progress: None,
86+
copy_completion: None,
87+
copy_status_description: None,
88+
};
89+
90+
new_blob.put(&client,
91+
container_name,
92+
None,
93+
Some((&mut file, metadata.len())))
94+
.unwrap();
95+
}
96+
97+
// This code will look for the "todelete" container and
98+
// remove from Azure.
99+
let mut to_delete = ret.iter_mut().find(|x| x.name == "todelete").unwrap();
100+
to_delete.delete(&client).unwrap();
101+
println!("{:?} deleted!", to_delete);
44102
}
45103
```
46104

src/azure/core/ba512_range.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use std::str::FromStr;
2+
use std::fmt;
3+
use std::num::ParseIntError;
4+
use azure::core::range::Range;
5+
use std::convert::Into;
6+
7+
#[derive(Debug, Copy, Clone, PartialEq)]
8+
pub struct BA512Range {
9+
start: u64,
10+
end: u64,
11+
}
12+
13+
impl BA512Range {
14+
pub fn start(&self) -> u64 {
15+
self.start
16+
}
17+
pub fn end(&self) -> u64 {
18+
self.end
19+
}
20+
21+
pub fn new(start: u64, end: u64) -> Result<BA512Range, Not512ByteAlignedError> {
22+
if start % 512 != 0 {
23+
return Err(Not512ByteAlignedError::StartRange(start));
24+
}
25+
if (end + 1) % 512 != 0 {
26+
return Err(Not512ByteAlignedError::EndRange(end));
27+
}
28+
29+
Ok(BA512Range {
30+
start: start,
31+
end: end,
32+
})
33+
}
34+
}
35+
36+
#[derive(Debug, Clone, PartialEq)]
37+
pub enum Not512ByteAlignedError {
38+
StartRange(u64),
39+
EndRange(u64),
40+
}
41+
42+
#[derive(Debug, Clone, PartialEq)]
43+
pub enum ParseError {
44+
SplitNotFound,
45+
ParseIntError(ParseIntError),
46+
Not512ByteAlignedError(Not512ByteAlignedError),
47+
}
48+
49+
impl From<ParseIntError> for ParseError {
50+
fn from(pie: ParseIntError) -> ParseError {
51+
ParseError::ParseIntError(pie)
52+
}
53+
}
54+
55+
impl From<Not512ByteAlignedError> for ParseError {
56+
fn from(nae: Not512ByteAlignedError) -> ParseError {
57+
ParseError::Not512ByteAlignedError(nae)
58+
}
59+
}
60+
61+
impl Into<Range> for BA512Range {
62+
fn into(self) -> Range {
63+
Range {
64+
start: self.start(),
65+
end: self.end(),
66+
}
67+
}
68+
}
69+
70+
impl FromStr for BA512Range {
71+
type Err = ParseError;
72+
fn from_str(s: &str) -> Result<BA512Range, ParseError> {
73+
let v = s.split("/").collect::<Vec<&str>>();
74+
if v.len() != 2 {
75+
return Err(ParseError::SplitNotFound);
76+
}
77+
78+
let cp_start = try!(v[0].parse::<u64>());
79+
let cp_end = try!(v[1].parse::<u64>());
80+
81+
82+
83+
Ok(try!(BA512Range::new(cp_start, cp_end)))
84+
}
85+
}
86+
87+
impl fmt::Display for BA512Range {
88+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89+
write!(f, "{}/{}", self.start, self.end)
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod test {
95+
use super::*;
96+
97+
#[test]
98+
fn test_512range_parse() {
99+
let range = "0/511".parse::<BA512Range>().unwrap();
100+
101+
assert_eq!(range.start, 0);
102+
assert_eq!(range.end, 511);
103+
}
104+
105+
#[test]
106+
#[should_panic(expected = "ParseIntError(ParseIntError { kind: InvalidDigit })")]
107+
fn test_512range_parse_panic_1() {
108+
"abba/2000".parse::<BA512Range>().unwrap();
109+
}
110+
111+
#[test]
112+
#[should_panic(expected = "SplitNotFound")]
113+
fn test_512range_parse_panic_2() {
114+
"1000-2000".parse::<BA512Range>().unwrap();
115+
}
116+
117+
#[test]
118+
#[should_panic(expected = "Not512ByteAlignedError(StartRange(7))")]
119+
fn test_512range_invalid_start_range() {
120+
"7/511".parse::<BA512Range>().unwrap();
121+
}
122+
123+
#[test]
124+
#[should_panic(expected = "Not512ByteAlignedError(EndRange(100))")]
125+
fn test_512range_invalid_end_range() {
126+
"0/100".parse::<BA512Range>().unwrap();
127+
}
128+
129+
#[test]
130+
fn test_512range_display() {
131+
let range = BA512Range {
132+
start: 0,
133+
end: 511,
134+
};
135+
136+
let txt = format!("{}", range);
137+
138+
assert_eq!(txt, "0/511");
139+
}
140+
}

0 commit comments

Comments
 (0)