Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9d401f5

Browse files
committed
feat(doit): optimizations and simplification; seek
* MultiPartReader is using match to handle state, reducing unnecessary calls to 0 in that regard. * Fixed seek() calls on readers, assuring they are reset to start each time the loop is done. * both media-parameters now use `ReadSeek` streams. * Use `seek()` to figure out size, simplifying the interface. Closes #17
1 parent 6b23013 commit 9d401f5

4 files changed

Lines changed: 47 additions & 41 deletions

File tree

src/mako/lib/mbuild.mako

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -375,17 +375,18 @@ match result {
375375
rtype = 'cmn::Result<(hyper::client::Response, %s)>' % (response_schema.id)
376376
reserved_params = ['alt']
377377
378-
378+
mtype_param = 'RS'
379+
mtype_where = 'ReadSeek'
379380
380381
possible_urls = [m.path]
381382
simple_media_param = None
382383
if media_params:
383384
stripped = lambda s: s.strip().strip(',')
384385
qualifier = ''
386+
type_params = mtype_param
387+
where = mtype_param + ': ' + mtype_where
385388
for p in media_params:
386-
type_params += p.type.param + ', '
387-
where += p.type.param + ': ' + p.type.where + ', '
388-
add_args += 'mut ' + p.type.arg_name + ': ' + ('Option<(%s, u64, mime::Mime)>' % p.type.param) + ', '
389+
add_args += 'mut ' + p.type.arg_name + ': ' + ('Option<(%s, mime::Mime)>' % mtype_param) + ', '
389390
possible_urls.append(p.path)
390391
if p.protocol == 'simple':
391392
simple_media_param = p
@@ -422,6 +423,7 @@ match result {
422423
all_required_param_name = set(p.name for p in params if is_required_property(p))
423424
MULTI_SLASH = 'multi-slash-prefix'
424425
URL_ENCODE = 'url-encode'
426+
READER_SEEK = "let size = reader.seek(io::SeekFrom::End(0)).unwrap();\nreader.seek(io::SeekFrom::Start(0)).unwrap();"
425427
426428
special_cases = set()
427429
for possible_url in possible_urls:
@@ -595,8 +597,10 @@ else {
595597
}
596598
597599
% if request_value:
598-
let json_encoded_request = json::encode(&self.${property(REQUEST_VALUE_PROPERTY_NAME)}).unwrap();
599600
let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default());
601+
let mut request_value_reader = io::Cursor::new(json::encode(&self.${property(REQUEST_VALUE_PROPERTY_NAME)}).unwrap().into_bytes());
602+
let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap();
603+
request_value_reader.seek(io::SeekFrom::Start(0)).unwrap();
600604
% endif
601605
602606
let mut client = &mut *self.hub.client.borrow_mut();
@@ -611,15 +615,16 @@ else {
611615
}
612616
let auth_header = hyper::header::Authorization(token.unwrap().access_token);
613617
% endif
618+
% if request_value:
619+
request_value_reader.seek(io::SeekFrom::Start(0)).unwrap();
620+
% endif
614621
% if request_value and simple_media_param:
615-
let mut request_value_reader = io::Cursor::new(json_encoded_request.clone().into_bytes());
616622
let mut mp_reader: cmn::MultiPartReader = Default::default();
617623
let (mut body_reader, content_type) = match ${simple_media_param.type.arg_name}.as_mut() {
618-
Some(&mut (ref mut reader, size, ref mime)) => {
624+
Some(&mut (ref mut reader, ref mime)) => {
619625
mp_reader.reserve_exact(2);
620-
let rsize = request_value_reader.seek(io::SeekFrom::End(0)).unwrap();
621-
request_value_reader.seek(io::SeekFrom::Start(0)).unwrap();
622-
mp_reader.add_part(&mut request_value_reader, rsize, json_mime_type.clone())
626+
${READER_SEEK | indent_all_but_first_by(5)}
627+
mp_reader.add_part(&mut request_value_reader, request_size, json_mime_type.clone())
623628
.add_part(reader, size, mime.clone());
624629
let mime_type = mp_reader.mime_type();
625630
(&mut mp_reader as &mut io::Read, ContentType(mime_type))
@@ -638,8 +643,8 @@ else {
638643
% if not simple_media_param:
639644
640645
.header(ContentType(json_mime_type.clone()))
641-
.header(ContentLength(json_encoded_request.len() as u64))
642-
.body(json_encoded_request.as_slice())\
646+
.header(ContentLength(request_size as u64))
647+
.body(request_value_reader.into_body())\
643648
% else:
644649
645650
.header(content_type)
@@ -648,7 +653,8 @@ else {
648653
% endif
649654
;
650655
% if simple_media_param and not request_value:
651-
if let Some(&mut (ref mut reader, size, ref mime)) = ${simple_media_param.type.arg_name}.as_mut() {
656+
if let Some(&mut (ref mut reader, ref mime)) = ${simple_media_param.type.arg_name}.as_mut() {
657+
${READER_SEEK | indent_all_but_first_by(4)}
652658
req = req.header(ContentType(mime.clone()))
653659
.header(ContentLength(size))
654660
.body(reader.into_body());
@@ -697,23 +703,20 @@ else {
697703
}
698704
699705
% for p in media_params:
700-
<%
701-
none_type = 'None::<(' + p.type.default + ', u64, mime::Mime)>'
702-
%>\
703706
${p.description | rust_doc_comment, indent_all_but_first_by(1)}
704707
///
705708
% for item_name, item in p.info.iteritems():
706709
/// * *${split_camelcase_s(item_name)}*: ${isinstance(item, (list, tuple)) and put_and(enclose_in("'", item)) or str(item)}
707710
% endfor
708-
pub fn ${api.terms.upload_action}${p.type.suffix}<${p.type.param}>(self, ${p.type.arg_name}: ${p.type.param}, size: u64, mime_type: mime::Mime) -> ${rtype}
709-
where ${p.type.param}: ${p.type.where} {
711+
pub fn ${api.terms.upload_action}${p.type.suffix}<${mtype_param}>(self, ${p.type.arg_name}: ${mtype_param}, mime_type: mime::Mime) -> ${rtype}
712+
where ${mtype_param}: ${mtype_where} {
710713
self.${api.terms.action}(\
711714
% for _ in range(0, loop.index):
712-
${none_type}, \
715+
None, \
713716
% endfor
714-
Some((${p.type.arg_name}, size, mime_type)), \
717+
Some((${p.type.arg_name}, mime_type)), \
715718
% for _ in range(loop.index+1, len(media_params)):
716-
${none_type}, \
719+
None, \
717720
% endfor
718721
)
719722
}

src/mako/lib/util.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,22 @@
7171
PROTOCOL_TYPE_INFO = {
7272
'simple' : {
7373
'arg_name': 'stream',
74-
'param': 'R',
7574
'description': """Upload media all at once.
7675
If the upload fails for whichever reason, all progress is lost.""",
7776
'default': 'fs::File',
78-
'where': 'ReadSeek',
7977
'suffix': '',
80-
'example_value': 'fs::File::open("file.ext").unwrap(), 148, "application/octet-stream".parse().unwrap()'
78+
'example_value': 'fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()'
8179
},
8280
'resumable' : {
8381
'arg_name': 'resumeable_stream',
84-
'param': 'RS',
8582
'description': """Upload media in a resumeable fashion.
8683
Even if the upload fails or is interrupted, it can be resumed for a
8784
certain amount of time as the server maintains state temporarily.
8885
8986
TODO: Write more about how delegation works in this particular case.""",
9087
'default': 'fs::File',
91-
'where': 'ReadSeek',
9288
'suffix': '_resumable',
93-
'example_value': 'fs::File::open("file.ext").unwrap(), 282, "application/octet-stream".parse().unwrap()'
89+
'example_value': 'fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()'
9490
}
9591
}
9692

src/rust/cmn.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,22 +183,28 @@ impl<'a> MultiPartReader<'a> {
183183

184184
impl<'a> Read for MultiPartReader<'a> {
185185
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
186-
if self.last_part_boundary.is_some() {
187-
let br = self.last_part_boundary.as_mut().unwrap().read(buf).unwrap_or(0);
188-
if br < buf.len() {
189-
self.last_part_boundary = None;
186+
match (self.raw_parts.len(),
187+
self.current_part.is_none(),
188+
self.last_part_boundary.is_none()) {
189+
(_, _, false) => {
190+
let br = self.last_part_boundary.as_mut().unwrap().read(buf).unwrap_or(0);
191+
if br < buf.len() {
192+
self.last_part_boundary = None;
193+
}
194+
return Ok(br)
195+
},
196+
(0, true, true) => return Ok(0),
197+
(n, true, _) if n > 0 => {
198+
let (headers, reader) = self.raw_parts.remove(0);
199+
let mut c = Cursor::new(Vec::<u8>::new());
200+
write!(&mut c, "{}--{}{}{}{}", LINE_ENDING, BOUNDARY, LINE_ENDING,
201+
headers, LINE_ENDING).unwrap();
202+
c.seek(SeekFrom::Start(0)).unwrap();
203+
self.current_part = Some((c, reader));
190204
}
191-
return Ok(br)
192-
} else if self.is_depleted() {
193-
return Ok(0)
194-
} else if self.raw_parts.len() > 0 && self.current_part.is_none() {
195-
let (headers, reader) = self.raw_parts.remove(0);
196-
let mut c = Cursor::new(Vec::<u8>::new());
197-
write!(&mut c, "{}--{}{}{}{}", LINE_ENDING, BOUNDARY, LINE_ENDING,
198-
headers, LINE_ENDING).unwrap();
199-
c.seek(SeekFrom::Start(0)).unwrap();
200-
self.current_part = Some((c, reader));
205+
_ => {},
201206
}
207+
202208
// read headers as long as possible
203209
let (hb, rr) = {
204210
let &mut (ref mut c, ref mut reader) = self.current_part.as_mut().unwrap();

src/rust/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod tests {
1717
use self::hyper_mock::*;
1818
use std::io::Read;
1919
use std::default::Default;
20+
use std::old_path::BytesContainer;
2021

2122
const EXPECTED: &'static str =
2223
"\r\n--MDuXWGyeE33QFXGchb2VFWc4Z7945d\r\n\

0 commit comments

Comments
 (0)