Skip to content

Commit 5f30553

Browse files
authored
Merge pull request #13 from CleverCloud/stoppable_converter
Allow converter to stop in the middle of blocks
2 parents 9952f67 + a8e3cc3 commit 5f30553

File tree

4 files changed

+61
-10
lines changed

4 files changed

+61
-10
lines changed

src/protocol/h1/converter.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl Version {
1616
}
1717

1818
impl<T: AsBuffer> BlockConverter<T> for H1BlockConverter {
19-
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) {
19+
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) -> bool {
2020
match block {
2121
Block::StatusLine => match kawa.detached.status_line.pop() {
2222
StatusLine::Request {
@@ -52,7 +52,7 @@ impl<T: AsBuffer> BlockConverter<T> for H1BlockConverter {
5252
},
5353
Block::Cookies => {
5454
if kawa.detached.jar.is_empty() {
55-
return;
55+
return true;
5656
}
5757
kawa.push_out(Store::Static(b"Cookie: "));
5858
let mut first = true;
@@ -104,5 +104,6 @@ impl<T: AsBuffer> BlockConverter<T> for H1BlockConverter {
104104
}
105105
}
106106
}
107+
true
107108
}
108109
}

src/protocol/h2/converter.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
pub struct H2BlockConverter;
99

1010
impl<T: AsBuffer> BlockConverter<T> for H2BlockConverter {
11-
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) {
11+
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) -> bool {
1212
match block {
1313
Block::StatusLine => match kawa.detached.status_line.pop() {
1414
StatusLine::Request {
@@ -36,7 +36,7 @@ impl<T: AsBuffer> BlockConverter<T> for H2BlockConverter {
3636
},
3737
Block::Cookies => {
3838
if kawa.detached.jar.is_empty() {
39-
return;
39+
return true;
4040
}
4141
kawa.push_out(Store::Static(b"------------ HEADER"));
4242
for cookie in kawa
@@ -72,7 +72,7 @@ impl<T: AsBuffer> BlockConverter<T> for H2BlockConverter {
7272
|| compare_no_case(key, b"transfer-encoding")
7373
|| compare_no_case(key, b"upgrade")
7474
{
75-
return;
75+
return true;
7676
}
7777
}
7878
kawa.push_out(Store::Static(b"------------ HEADER\n"));
@@ -106,5 +106,6 @@ impl<T: AsBuffer> BlockConverter<T> for H2BlockConverter {
106106
}
107107
}
108108
}
109+
true
109110
}
110111
}

src/storage/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ pub use vecdeque::VecDeque;
1313

1414
pub trait BlockConverter<T: AsBuffer> {
1515
fn initialize(&mut self, _kawa: &mut Kawa<T>) {}
16-
fn call(&mut self, block: Block, kawa: &mut Kawa<T>);
16+
fn call(&mut self, block: Block, kawa: &mut Kawa<T>) -> bool;
1717
fn finalize(&mut self, _kawa: &mut Kawa<T>) {}
1818
}

src/storage/repr.rs

+53-4
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ impl<T: AsBuffer> Kawa<T> {
7878
pub fn prepare<C: BlockConverter<T>>(&mut self, converter: &mut C) {
7979
converter.initialize(self);
8080
while let Some(block) = self.blocks.pop_front() {
81-
converter.call(block, self);
81+
if !converter.call(block, self) {
82+
break;
83+
}
8284
}
8385
converter.finalize(self);
8486
}
@@ -109,8 +111,8 @@ impl<T: AsBuffer> Kawa<T> {
109111
/// note: this function assumes blocks is empty! To respect this invariant you should always
110112
/// call prepare before consume
111113
pub fn consume(&mut self, mut amount: usize) {
112-
assert!(self.blocks.is_empty());
113-
assert!(self.detached.jar.is_empty());
114+
// assert!(self.blocks.is_empty());
115+
// assert!(self.detached.jar.is_empty());
114116
if amount > 0 {
115117
self.consumed = true;
116118
}
@@ -142,7 +144,12 @@ impl<T: AsBuffer> Kawa<T> {
142144
return slice.start as usize;
143145
}
144146
}
145-
self.storage.head
147+
if self.blocks.is_empty() {
148+
// conservative estimate
149+
self.storage.head
150+
} else {
151+
self.storage.start
152+
}
146153
}
147154

148155
pub fn push_block(&mut self, block: Block) {
@@ -487,6 +494,17 @@ impl Store {
487494
}
488495
}
489496

497+
pub fn len(&self) -> usize {
498+
match self {
499+
Store::Empty => 0,
500+
Store::Slice(s) | Store::Detached(s) => s.len(),
501+
Store::Static(s) => s.len(),
502+
Store::Alloc(s, i) => s.len() - *i as usize,
503+
#[cfg(feature = "rc-alloc")]
504+
Store::Shared(s, i) => s.len() - *i as usize,
505+
}
506+
}
507+
490508
pub fn is_empty(&self) -> bool {
491509
matches!(self, Store::Empty)
492510
}
@@ -539,6 +557,37 @@ impl Store {
539557
}
540558
}
541559

560+
pub fn split(self, at: usize) -> (Store, Store) {
561+
let at32 = at as u32;
562+
match self {
563+
Store::Empty => (Store::Empty, Store::Empty),
564+
Store::Slice(Slice { start, len }) => (
565+
Store::Slice(Slice { start, len: at32 }),
566+
Store::Slice(Slice {
567+
start: start + at32,
568+
len: len - at32,
569+
}),
570+
),
571+
Store::Detached(Slice { start, len }) => (
572+
Store::Detached(Slice { start, len: at32 }),
573+
Store::Detached(Slice {
574+
start: start + at32,
575+
len: len - at32,
576+
}),
577+
),
578+
Store::Static(s) => (Store::Static(&s[..at]), Store::Static(&s[at..])),
579+
Store::Alloc(s, i) => (
580+
Store::from_slice(&s[i as usize..i as usize + at]),
581+
Store::Alloc(s, i + at32),
582+
),
583+
#[cfg(feature = "rc-alloc")]
584+
Store::Shared(s, i) => (
585+
Store::from_slice(&s[i as usize..i as usize + at]),
586+
Store::Shared(s, i + at32),
587+
),
588+
}
589+
}
590+
542591
fn consume(self, amount: usize) -> (usize, Option<Store>) {
543592
match self {
544593
Store::Empty => (amount, None),

0 commit comments

Comments
 (0)