gproxy_protocol/adapt/generate/stream/
reader.rs1use crate::{
4 HttpBody,
5 codec::{self, CodecError, CodecErrorKind, CodecErrorStage, CodecLimits},
6 connection::ByteStream,
7 wire::DeclaredFields,
8};
9use bytes::{Buf, Bytes};
10use futures_util::StreamExt;
11use serde::de::DeserializeOwned;
12use std::collections::VecDeque;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum SourceFraming {
16 Sse,
17 JsonArray,
18 Ndjson,
19}
20
21#[derive(Debug)]
22pub enum NativeFrame<T> {
23 Event { name: Option<String>, value: T },
24 Done,
25}
26
27enum Decoder {
28 Sse(codec::SseDecoder),
29 Array(codec::JsonArrayDecoder),
30 Ndjson(codec::NdjsonDecoder),
31}
32
33enum Frame {
34 Sse(codec::SseFrame),
35 Json(serde_json::Value),
36}
37
38pub struct NativeReader {
44 stream: Option<ByteStream>,
45 pending: Bytes,
46 decoder: Decoder,
47 queued: VecDeque<Frame>,
48 limits: CodecLimits,
49 received: u64,
50
51 eof: bool,
52 failed: bool,
53}
54
55impl NativeReader {
56 pub fn new(body: HttpBody, framing: SourceFraming, limits: CodecLimits) -> Self {
57 let (stream, pending) = match body {
58 HttpBody::Bytes(bytes) => (None, bytes),
59 HttpBody::Stream(stream) => (Some(stream), Bytes::new()),
60 };
61 Self {
62 received: pending.len() as u64,
63 stream,
64 pending,
65 decoder: match framing {
66 SourceFraming::Sse => Decoder::Sse(codec::SseDecoder::new(limits)),
67 SourceFraming::JsonArray => Decoder::Array(codec::JsonArrayDecoder::new(limits)),
68 SourceFraming::Ndjson => Decoder::Ndjson(codec::NdjsonDecoder::new(limits)),
69 },
70 queued: VecDeque::new(),
71 limits,
72
73 eof: false,
74 failed: false,
75 }
76 }
77 pub async fn next<T: DeserializeOwned + DeclaredFields>(
78 &mut self,
79 ) -> Result<Option<NativeFrame<T>>, CodecError> {
80 if self.failed {
81 return Err(error(
82 CodecErrorKind::Invalid,
83 "native reader terminated after failure",
84 ));
85 }
86 let result = self.next_inner().await;
87 if result.is_err() {
88 self.failed = true;
89 self.stream = None;
90 self.pending = Bytes::new();
91 self.queued.clear();
92 }
93 result
94 }
95 async fn next_inner<T: DeserializeOwned + DeclaredFields>(
96 &mut self,
97 ) -> Result<Option<NativeFrame<T>>, CodecError> {
98 if self.received > self.limits.max_body_bytes {
99 return Err(error(
100 CodecErrorKind::Limit,
101 "native body byte limit exceeded",
102 ));
103 }
104 let mut work = 0usize;
105 loop {
106 if let Some(frame) = self.queued.pop_front() {
107 return match frame {
108 Frame::Sse(codec::SseFrame::Done) => Ok(Some(NativeFrame::Done)),
109 Frame::Sse(codec::SseFrame::Event(event)) => {
110 let value: T = codec::decode_json(event.data.as_bytes(), self.limits)?;
111 Ok(Some(NativeFrame::Event {
112 name: event.event,
113 value: value.into_declared(),
114 }))
115 }
116 Frame::Json(value) => {
117 let value: T = serde_json::from_value(value).map_err(|e| {
118 CodecError::with_source(
119 CodecErrorKind::Json,
120 CodecErrorStage::Stream,
121 "invalid native event",
122 e,
123 )
124 })?;
125 Ok(Some(NativeFrame::Event {
126 name: None,
127 value: value.into_declared(),
128 }))
129 }
130 };
131 }
132 if work >= 1024 {
133 yield_once().await;
134 work = 0;
135 }
136 if !self.pending.is_empty() {
137 let count = match &self.decoder {
142 Decoder::Array(_) => 1,
143 _ => self
144 .pending
145 .iter()
146 .position(|b| *b == b'\n' || *b == b'\r')
147 .map_or(self.pending.len(), |n| n + 1),
148 };
149 match &mut self.decoder {
150 Decoder::Sse(d) => self
151 .queued
152 .extend(d.push(&self.pending[..count])?.into_iter().map(Frame::Sse)),
153 Decoder::Array(d) => self
154 .queued
155 .extend(d.push(&self.pending[..count])?.into_iter().map(Frame::Json)),
156 Decoder::Ndjson(d) => self
157 .queued
158 .extend(d.push(&self.pending[..count])?.into_iter().map(Frame::Json)),
159 }
160 self.pending.advance(count);
161 work += 1;
162 continue;
163 }
164 if self.eof {
165 return Ok(None);
166 }
167 if let Some(stream) = &mut self.stream {
168 if let Some(chunk) = stream.next().await {
169 let chunk = chunk.map_err(|e| {
170 CodecError::with_source(
171 CodecErrorKind::Transport,
172 CodecErrorStage::Stream,
173 "native stream transport failed",
174 e,
175 )
176 })?;
177 self.received = self
178 .received
179 .checked_add(chunk.len() as u64)
180 .ok_or_else(|| error(CodecErrorKind::Limit, "native body size overflow"))?;
181 if self.received > self.limits.max_body_bytes {
182 return Err(error(
183 CodecErrorKind::Limit,
184 "native body byte limit exceeded",
185 ));
186 }
187 self.pending = chunk;
188 work += 1;
189 continue;
190 }
191 self.stream = None;
192 }
193 self.eof = true;
194 match &mut self.decoder {
195 Decoder::Sse(d) => self.queued.extend(d.finish()?.into_iter().map(Frame::Sse)),
196 Decoder::Array(d) => d.finish()?,
197 Decoder::Ndjson(d) => self.queued.extend(d.finish()?.into_iter().map(Frame::Json)),
198 }
199 }
200 }
201}
202
203fn error(kind: CodecErrorKind, message: &'static str) -> CodecError {
204 CodecError::new(kind, CodecErrorStage::Stream, message)
205}
206
207async fn yield_once() {
208 let mut yielded = false;
209 std::future::poll_fn(move |cx| {
210 if yielded {
211 std::task::Poll::Ready(())
212 } else {
213 yielded = true;
214 cx.waker().wake_by_ref();
215 std::task::Poll::Pending
216 }
217 })
218 .await
219}