ort_openrouter_cli/net/
chunked.rs1extern crate alloc;
8use alloc::ffi::CString;
9use alloc::string::{String, ToString};
10use alloc::vec::Vec;
11
12use crate::{ErrorKind, OrtResult, Read, common::buf_read, ort_error, syscall};
13
14pub fn read<R: Read, const MAX_CHUNK_SIZE: usize>(
19 r: buf_read::OrtBufReader<R>,
20) -> ChunkedIterator<R, MAX_CHUNK_SIZE> {
21 ChunkedIterator::new(r)
22}
23
24pub struct ChunkedIterator<R: Read, const MAX_CHUNK_SIZE: usize> {
25 r: buf_read::OrtBufReader<R>,
26 size_buf: String,
27 data_buf: Vec<u8>,
28}
29
30impl<R: Read, const MAX_CHUNK_SIZE: usize> ChunkedIterator<R, MAX_CHUNK_SIZE> {
36 fn new(r: buf_read::OrtBufReader<R>) -> ChunkedIterator<R, MAX_CHUNK_SIZE> {
37 ChunkedIterator {
38 r,
39 size_buf: String::with_capacity(16),
40 data_buf: Vec::with_capacity(MAX_CHUNK_SIZE),
41 }
42 }
43
44 pub fn next_chunk(&mut self) -> Option<OrtResult<&str>> {
45 let mut bytes_read = 0;
46 loop {
49 self.size_buf.clear();
52 match self.r.read_line(&mut self.size_buf) {
53 Ok(0) => {
54 return Some(Err(ort_error(ErrorKind::ChunkedEofInSize, "")));
55 }
56 Ok(_) => {}
57 Err(err) => {
58 err.debug_print();
59 return Some(Err(ort_error(ErrorKind::ChunkedSizeReadError, "")));
60 }
61 }
62 let size_str = self.size_buf.trim();
63 if size_str.is_empty() {
64 continue;
66 }
67 let size = match usize::from_str_radix(size_str, 16) {
68 Ok(n) => n,
69 Err(_err) => {
70 let c_s = CString::new("ERROR invalid chunked size: ".to_string() + size_str)
71 .unwrap();
72 syscall::write(2, c_s.as_ptr().cast(), c_s.count_bytes());
73 return Some(Err(ort_error(ErrorKind::ChunkedInvalidSize, "")));
74 }
75 };
76 if size == 0 {
77 return None;
79 }
80
81 if bytes_read == 0 {
83 self.data_buf.clear();
84 }
85 self.data_buf.reserve_exact(size);
87 unsafe { self.data_buf.set_len(size + bytes_read) };
88
89 if let Err(_err) = self.r.read_exact(&mut self.data_buf[bytes_read..]) {
90 return Some(Err(ort_error(ErrorKind::ChunkedDataReadError, "")));
92 };
93 bytes_read += size;
94
95 let last_byte = self.data_buf[self.data_buf.len() - 1];
98 if (last_byte & 0b1000_0000) != 0 {
99 continue;
102 }
103 break;
104 }
105 Some(Ok(unsafe { str::from_utf8_unchecked(&self.data_buf) }))
106 }
107}