1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use data::{self, DataFile, DataDir, DataType, DataObject, XDataType, XErrorMessage};
use client::HttpClient;
use error::*;
use hyper::Url;
use hyper::status::StatusCode;
pub trait HasDataPath {
fn new(client: HttpClient, path: &str) -> Self;
fn path(&self) -> &str;
fn client(&self) -> &HttpClient;
/// Get the API Endpoint URL for a particular data URI
fn to_url(&self) -> Url {
let url_string = format!("{}/{}/{}", self.client().base_url, data::DATA_BASE_PATH, self.path());
Url::parse(&url_string).unwrap()
}
/// Get the Algorithmia data URI a given Data Object
///
/// ```
/// # use algorithmia::Algorithmia;
/// # use algorithmia::data::HasDataPath;
/// # let client = Algorithmia::client("111112222233333444445555566");
/// let my_dir = client.dir(".my/my_dir");
/// assert_eq!(my_dir.to_data_uri(), "data://.my/my_dir");
/// ```
fn to_data_uri(&self) -> String {
format!("data://{}", self.path())
}
/// Get the parent off a given Data Object
///
/// ```
/// # use algorithmia::Algorithmia;
/// # use algorithmia::data::HasDataPath;
/// # let client = Algorithmia::client("111112222233333444445555566");
/// let my_file = client.file("data://.my/my_dir/my_file");
/// assert_eq!(my_file.parent().unwrap().path(), ".my/my_dir");
/// ```
fn parent(&self) -> Option<DataDir>{
match self.path().rsplitn(2, "/").nth(1) {
Some(path) => Some(DataDir::new(self.client().clone(), &*path)),
None => None
}
}
/// Get the basename from the Data Object's path (i.e. unix `basename`)
///
/// ```
/// # use algorithmia::Algorithmia;
/// # use algorithmia::data::HasDataPath;
/// # let client = Algorithmia::client("111112222233333444445555566");
/// let my_dir = client.dir("data:///.my/my_dir");
/// assert_eq!(my_dir.basename().unwrap(), "my_dir");
/// ```
fn basename(&self) -> Option<String> {
match self.path().rsplitn(2, "/").next() {
Some(s) => Some(s.to_string()),
None => None
}
}
/// Determine if a file or directory exists for a particular data URI
///
/// ```no_run
/// # use algorithmia::Algorithmia;
/// # use algorithmia::data::HasDataPath;
/// # let client = Algorithmia::client("111112222233333444445555566");
/// let my_file = client.data("data://.my/my_dir/my_file");
/// assert_eq!(my_file.exists().unwrap(), true);
/// ```
fn exists(&self) -> Result<bool, Error> {
let req = self.client().head(self.to_url());
let res = try!(req.send());
match res.status {
StatusCode::Ok => Ok(true),
StatusCode::NotFound => Ok(false),
status => {
let msg = match res.headers.get::<XErrorMessage>() {
Some(err_header) => format!("{}: {}", status, err_header),
None => format!("{}", status),
};
Err(ApiError{message: msg, stacktrace: None}.into())
},
}
}
}
pub struct DataPath {
path: String,
client: HttpClient,
}
impl HasDataPath for DataPath {
fn new(client: HttpClient, path: &str) -> Self { DataPath { client: client, path: data::parse_data_uri(path).to_string() } }
fn path(&self) -> &str { &self.path }
fn client(&self) -> &HttpClient { &self.client }
}
impl DataPath {
/// Determine if a particular data URI is for a file or directory
///
/// ```no_run
/// # use algorithmia::Algorithmia;
/// # use algorithmia::data::{DataFile, DataDir, DataType, HasDataPath};
/// # let client = Algorithmia::client("111112222233333444445555566");
/// let my_obj = client.data("data://.my/some/path");
/// match my_obj.get_type().ok().unwrap() {
/// DataType::File => println!("{} is a file", my_obj.to_data_uri()),
/// DataType::Dir => println!("{} is a directory", my_obj.to_data_uri()),
/// }
/// ```
pub fn get_type(&self) -> Result<DataType, Error> {
let req = self.client.head(self.to_url());
let res = try!(req.send());
match res.status {
StatusCode::Ok => match res.headers.get::<XDataType>() {
Some(dt) if &*dt.to_string() == "directory" => Ok(DataType::Dir),
Some(dt) if &*dt.to_string() == "file" => Ok(DataType::File),
Some(dt) => Err(Error::DataTypeError(format!("Unknown DataType: {}", dt.to_string()))),
None => Err(Error::DataTypeError("Unspecified DataType".to_string())),
},
status => {
let msg = match res.headers.get::<XErrorMessage>() {
Some(err_header) => format!("{}: {}", status, err_header),
None => format!("{}", status),
};
Err(ApiError{message: msg, stacktrace: None}.into())
},
}
}
pub fn into_type(&self) -> Result<DataObject, Error> {
match try!(self.get_type()) {
DataType::Dir => Ok(DataObject::Dir(self.into())),
DataType::File => Ok(DataObject::File(self.into())),
}
}
}
impl <'a> From<&'a DataPath> for DataDir {
fn from(d: &'a DataPath) -> Self {
DataDir::new(d.client().clone(), d.path())
}
}
impl <'a> From<&'a DataPath> for DataFile {
fn from(d: &'a DataPath) -> Self {
DataFile::new(d.client().clone(), d.path())
}
}