1#![forbid(unsafe_code)]
2
3use crate::{ProtocolError, Result};
4
5pub const TNS_MAX_SHORT_LENGTH: usize = 252;
6pub const TNS_LONG_LENGTH_INDICATOR: u8 = 0xfe;
7pub const TNS_NULL_LENGTH_INDICATOR: u8 = 0xff;
8
9const MIB: usize = 1024 * 1024;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub struct ProtocolLimits {
19 pub max_packet_bytes: usize,
21 pub max_frame_bytes: usize,
23 pub max_response_bytes: usize,
25 pub max_columns: usize,
27 pub max_binds: usize,
29 pub max_batch_rows: usize,
31 pub max_object_depth: usize,
33 pub max_object_elements: usize,
35 pub max_vector_dimensions: usize,
37 pub max_lob_chunks: usize,
39 pub max_length_prefixed_elements: usize,
41}
42
43impl Default for ProtocolLimits {
44 fn default() -> Self {
45 Self::DEFAULT
46 }
47}
48
49impl ProtocolLimits {
50 pub const DEFAULT: Self = Self {
51 max_packet_bytes: 16 * MIB,
52 max_frame_bytes: 16 * MIB,
53 max_response_bytes: 256 * MIB,
54 max_columns: 4096,
55 max_binds: 65_535,
56 max_batch_rows: 1_000_000,
57 max_object_depth: 256,
58 max_object_elements: 1_000_000,
59 max_vector_dimensions: 1_000_000,
60 max_lob_chunks: 1_000_000,
61 max_length_prefixed_elements: 1_000_000,
62 };
63
64 pub fn validate(self) -> Result<Self> {
66 for (name, value) in self.named_limits() {
67 if value == 0 {
68 return Err(ProtocolError::ResourceLimit {
69 limit: name,
70 observed: 0,
71 maximum: 1,
72 });
73 }
74 }
75 if self.max_packet_bytes > self.max_frame_bytes {
76 return Err(ProtocolError::ResourceLimit {
77 limit: "packet_bytes",
78 observed: self.max_packet_bytes,
79 maximum: self.max_frame_bytes,
80 });
81 }
82 if self.max_frame_bytes > self.max_response_bytes {
83 return Err(ProtocolError::ResourceLimit {
84 limit: "frame_bytes",
85 observed: self.max_frame_bytes,
86 maximum: self.max_response_bytes,
87 });
88 }
89 Ok(self)
90 }
91
92 pub fn check_packet_bytes(&self, observed: usize) -> Result<()> {
93 self.check("packet_bytes", observed, self.max_packet_bytes)
94 }
95
96 pub fn check_frame_bytes(&self, observed: usize) -> Result<()> {
97 self.check("frame_bytes", observed, self.max_frame_bytes)
98 }
99
100 pub fn check_response_bytes(&self, observed: usize) -> Result<()> {
101 self.check("response_bytes", observed, self.max_response_bytes)
102 }
103
104 pub fn check_columns(&self, observed: usize) -> Result<()> {
105 self.check("columns", observed, self.max_columns)
106 }
107
108 pub fn check_binds(&self, observed: usize) -> Result<()> {
109 self.check("binds", observed, self.max_binds)
110 }
111
112 pub fn check_batch_rows(&self, observed: usize) -> Result<()> {
113 self.check("batch_rows", observed, self.max_batch_rows)
114 }
115
116 pub fn check_object_depth(&self, observed: usize) -> Result<()> {
117 self.check("object_depth", observed, self.max_object_depth)
118 }
119
120 pub fn check_object_elements(&self, observed: usize) -> Result<()> {
121 self.check("object_elements", observed, self.max_object_elements)
122 }
123
124 pub fn check_vector_dimensions(&self, observed: usize) -> Result<()> {
125 self.check("vector_dimensions", observed, self.max_vector_dimensions)
126 }
127
128 pub fn check_lob_chunks(&self, observed: usize) -> Result<()> {
129 self.check("lob_chunks", observed, self.max_lob_chunks)
130 }
131
132 pub fn check_length_prefixed_elements(&self, observed: usize) -> Result<()> {
133 self.check(
134 "length_prefixed_elements",
135 observed,
136 self.max_length_prefixed_elements,
137 )
138 }
139
140 fn check(&self, limit: &'static str, observed: usize, maximum: usize) -> Result<()> {
141 if observed <= maximum {
142 Ok(())
143 } else {
144 Err(ProtocolError::ResourceLimit {
145 limit,
146 observed,
147 maximum,
148 })
149 }
150 }
151
152 fn named_limits(&self) -> [(&'static str, usize); 11] {
153 [
154 ("packet_bytes", self.max_packet_bytes),
155 ("frame_bytes", self.max_frame_bytes),
156 ("response_bytes", self.max_response_bytes),
157 ("columns", self.max_columns),
158 ("binds", self.max_binds),
159 ("batch_rows", self.max_batch_rows),
160 ("object_depth", self.max_object_depth),
161 ("object_elements", self.max_object_elements),
162 ("vector_dimensions", self.max_vector_dimensions),
163 ("lob_chunks", self.max_lob_chunks),
164 (
165 "length_prefixed_elements",
166 self.max_length_prefixed_elements,
167 ),
168 ]
169 }
170}
171
172#[derive(Clone, Copy, Debug, Eq, PartialEq)]
173pub enum PacketLengthWidth {
174 Legacy16,
175 Large32,
176}
177
178#[derive(Clone, Debug, Default, Eq, PartialEq)]
179pub struct TtcWriter {
180 bytes: Vec<u8>,
181 seq_num: u8,
182}
183
184impl TtcWriter {
185 pub fn new() -> Self {
186 Self::default()
187 }
188
189 pub fn with_capacity(capacity: usize) -> Self {
197 Self {
198 bytes: Vec::with_capacity(capacity),
199 seq_num: 0,
200 }
201 }
202
203 pub fn into_bytes(self) -> Vec<u8> {
204 self.bytes
205 }
206
207 pub fn write_u8(&mut self, value: u8) {
208 self.bytes.push(value);
209 }
210
211 pub fn write_u16be(&mut self, value: u16) {
212 self.bytes.extend_from_slice(&value.to_be_bytes());
213 }
214
215 pub fn write_u16le(&mut self, value: u16) {
216 self.bytes.extend_from_slice(&value.to_le_bytes());
217 }
218
219 pub fn write_u32be(&mut self, value: u32) {
220 self.bytes.extend_from_slice(&value.to_be_bytes());
221 }
222
223 pub fn write_u64be(&mut self, value: u64) {
224 self.bytes.extend_from_slice(&value.to_be_bytes());
225 }
226
227 pub fn write_ub2(&mut self, value: u16) {
228 if value == 0 {
229 self.write_u8(0);
230 } else if value <= u16::from(u8::MAX) {
231 self.write_u8(1);
232 self.write_u8(value as u8);
233 } else {
234 self.write_u8(2);
235 self.write_u16be(value);
236 }
237 }
238
239 pub fn write_ub4(&mut self, value: u32) {
240 if value == 0 {
241 self.write_u8(0);
242 } else if value <= u32::from(u8::MAX) {
243 self.write_u8(1);
244 self.write_u8(value as u8);
245 } else if value <= u32::from(u16::MAX) {
246 self.write_u8(2);
247 self.write_u16be(value as u16);
248 } else {
249 self.write_u8(4);
250 self.write_u32be(value);
251 }
252 }
253
254 pub fn write_ub8(&mut self, value: u64) {
255 if value == 0 {
256 self.write_u8(0);
257 } else if value <= u64::from(u8::MAX) {
258 self.write_u8(1);
259 self.write_u8(value as u8);
260 } else if value <= u64::from(u16::MAX) {
261 self.write_u8(2);
262 self.write_u16be(value as u16);
263 } else if value <= u64::from(u32::MAX) {
264 self.write_u8(4);
265 self.write_u32be(value as u32);
266 } else {
267 self.write_u8(8);
268 self.write_u64be(value);
269 }
270 }
271
272 pub fn write_seq_num(&mut self) {
273 self.seq_num = self.seq_num.wrapping_add(1);
274 if self.seq_num == 0 {
275 self.seq_num = 1;
276 }
277 self.write_u8(self.seq_num);
278 }
279
280 pub fn write_raw(&mut self, value: &[u8]) {
281 self.bytes.extend_from_slice(value);
282 }
283
284 pub fn write_bytes_with_length(&mut self, value: &[u8]) -> Result<()> {
285 if value.len() <= TNS_MAX_SHORT_LENGTH {
286 self.write_u8(value.len() as u8);
287 self.write_raw(value);
288 return Ok(());
289 }
290 self.write_u8(TNS_LONG_LENGTH_INDICATOR);
291 for chunk in value.chunks(32_767) {
292 self.write_ub4(u32::try_from(chunk.len()).map_err(|_| {
293 ProtocolError::InvalidPacketLength {
294 length: chunk.len(),
295 minimum: 0,
296 }
297 })?);
298 self.write_raw(chunk);
299 }
300 self.write_ub4(0);
301 Ok(())
302 }
303
304 pub fn write_bytes_with_two_lengths(&mut self, value: Option<&[u8]>) -> Result<()> {
305 match value {
306 Some(bytes) => {
307 self.write_ub4(u32::try_from(bytes.len()).map_err(|_| {
308 ProtocolError::InvalidPacketLength {
309 length: bytes.len(),
310 minimum: 0,
311 }
312 })?);
313 if !bytes.is_empty() {
314 self.write_bytes_with_length(bytes)?;
315 }
316 }
317 None => self.write_ub4(0),
318 }
319 Ok(())
320 }
321
322 pub fn write_str_two_lengths(&mut self, value: &str) -> Result<()> {
323 self.write_bytes_with_two_lengths(Some(value.as_bytes()))
324 }
325
326 pub fn write_sb4(&mut self, value: i32) {
331 let (sign, magnitude) = if value < 0 {
332 (0x80u8, value.unsigned_abs())
333 } else {
334 (0u8, value as u32)
335 };
336 if magnitude == 0 {
337 self.write_u8(0);
338 } else if magnitude <= u32::from(u8::MAX) {
339 self.write_u8(1 | sign);
340 self.write_u8(magnitude as u8);
341 } else if magnitude <= u32::from(u16::MAX) {
342 self.write_u8(2 | sign);
343 self.write_u16be(magnitude as u16);
344 } else {
345 self.write_u8(4 | sign);
346 self.write_u32be(magnitude);
347 }
348 }
349
350 pub fn write_keyword_value_pair(
354 &mut self,
355 text_value: Option<&[u8]>,
356 binary_value: Option<&[u8]>,
357 keyword: u16,
358 ) -> Result<()> {
359 self.write_bytes_with_two_lengths(text_value)?;
360 self.write_bytes_with_two_lengths(binary_value)?;
361 self.write_ub2(keyword);
362 Ok(())
363 }
364
365 pub fn write_function_code(&mut self, function_code: u8) {
366 self.write_u8(crate::thin::TNS_MSG_TYPE_FUNCTION);
367 self.write_u8(function_code);
368 self.write_seq_num();
369 }
370
371 pub fn write_function_code_with_seq(&mut self, function_code: u8, seq_num: u8) {
372 self.write_u8(crate::thin::TNS_MSG_TYPE_FUNCTION);
373 self.write_u8(function_code);
374 self.write_u8(seq_num);
375 }
376}
377
378pub trait BoundedReader {
405 fn remaining(&self) -> usize;
408
409 fn protocol_limits(&self) -> ProtocolLimits {
412 ProtocolLimits::DEFAULT
413 }
414
415 fn alloc_count_checked(&self, count: usize, min_bytes_per_elem: usize) -> Result<usize> {
425 self.protocol_limits()
426 .check_length_prefixed_elements(count)?;
427 let per_elem = min_bytes_per_elem.max(1);
428 match count.checked_mul(per_elem) {
429 Some(needed) if needed <= self.remaining() => Ok(count),
430 _ => Err(ProtocolError::TtcDecode(
431 "declared element count exceeds remaining buffer",
432 )),
433 }
434 }
435
436 fn with_capacity_bounded<T>(&self, count: usize, min_bytes_per_elem: usize) -> Vec<T> {
444 let per_elem = min_bytes_per_elem.max(1);
445 Vec::with_capacity(count.min(self.remaining() / per_elem))
446 }
447
448 fn with_capacity_limited<T, F>(
452 &self,
453 count: usize,
454 min_bytes_per_elem: usize,
455 check: F,
456 ) -> Result<Vec<T>>
457 where
458 F: FnOnce(&ProtocolLimits, usize) -> Result<()>,
459 {
460 check(&self.protocol_limits(), count)?;
461 Ok(self.with_capacity_bounded(count, min_bytes_per_elem))
462 }
463}
464
465#[derive(Clone, Debug)]
466pub struct TtcReader<'a> {
467 bytes: &'a [u8],
468 pos: usize,
469 limits: ProtocolLimits,
470}
471
472impl BoundedReader for TtcReader<'_> {
473 fn remaining(&self) -> usize {
474 TtcReader::remaining(self)
475 }
476
477 fn protocol_limits(&self) -> ProtocolLimits {
478 self.limits
479 }
480}
481
482#[derive(Clone, Debug, PartialEq, Eq)]
486pub enum BorrowedBytes<'a> {
487 Null,
489 Slice(&'a [u8]),
491 Chunked(Vec<u8>),
494}
495
496impl<'a> TtcReader<'a> {
497 pub fn new(bytes: &'a [u8]) -> Self {
498 Self {
499 bytes,
500 pos: 0,
501 limits: ProtocolLimits::DEFAULT,
502 }
503 }
504
505 pub fn with_limits(bytes: &'a [u8], limits: ProtocolLimits) -> Result<Self> {
506 let limits = limits.validate()?;
507 limits.check_frame_bytes(bytes.len())?;
508 limits.check_response_bytes(bytes.len())?;
509 Ok(Self {
510 bytes,
511 pos: 0,
512 limits,
513 })
514 }
515
516 pub fn limits(&self) -> ProtocolLimits {
517 self.limits
518 }
519
520 pub fn remaining(&self) -> usize {
521 self.bytes.len().saturating_sub(self.pos)
522 }
523
524 pub fn position(&self) -> usize {
525 self.pos
526 }
527
528 pub fn remaining_slice(&self) -> &[u8] {
529 &self.bytes[self.pos.min(self.bytes.len())..]
530 }
531
532 pub fn peek_u8(&self) -> Result<u8> {
533 self.bytes
534 .get(self.pos)
535 .copied()
536 .ok_or(ProtocolError::TtcDecode("missing u8"))
537 }
538
539 pub fn read_u8(&mut self) -> Result<u8> {
540 let value = *self
541 .bytes
542 .get(self.pos)
543 .ok_or(ProtocolError::TtcDecode("missing u8"))?;
544 self.pos += 1;
545 Ok(value)
546 }
547
548 pub fn read_i8(&mut self) -> Result<i8> {
549 Ok(self.read_u8()? as i8)
550 }
551
552 pub fn read_u16be(&mut self) -> Result<u16> {
553 let bytes = self.read_raw(2)?;
554 Ok(u16::from_be_bytes(
555 bytes
556 .try_into()
557 .map_err(|_| ProtocolError::TtcDecode("invalid u16"))?,
558 ))
559 }
560
561 pub fn read_u16le(&mut self) -> Result<u16> {
562 let bytes = self.read_raw(2)?;
563 Ok(u16::from_le_bytes(
564 bytes
565 .try_into()
566 .map_err(|_| ProtocolError::TtcDecode("invalid u16"))?,
567 ))
568 }
569
570 pub fn read_u32be(&mut self) -> Result<u32> {
571 let bytes = self.read_raw(4)?;
572 Ok(u32::from_be_bytes(
573 bytes
574 .try_into()
575 .map_err(|_| ProtocolError::TtcDecode("invalid u32"))?,
576 ))
577 }
578
579 pub fn read_raw(&mut self, len: usize) -> Result<&'a [u8]> {
580 self.limits.check_response_bytes(len)?;
581 let end = self
582 .pos
583 .checked_add(len)
584 .ok_or(ProtocolError::TtcDecode("read offset overflow"))?;
585 let bytes = self
586 .bytes
587 .get(self.pos..end)
588 .ok_or(ProtocolError::TtcDecode("truncated TTC payload"))?;
589 self.pos = end;
590 Ok(bytes)
591 }
592
593 pub fn skip(&mut self, len: usize) -> Result<()> {
594 self.read_raw(len).map(|_| ())
595 }
596
597 pub fn read_ub2(&mut self) -> Result<u16> {
598 let len = self.read_u8()?;
599 match len {
600 0 => Ok(0),
601 1 => Ok(u16::from(self.read_u8()?)),
602 2 => self.read_u16be(),
603 _ => Err(ProtocolError::TtcDecode("invalid ub2 length")),
604 }
605 }
606
607 pub fn read_ub4(&mut self) -> Result<u32> {
608 let len = self.read_u8()?;
609 if len == 0 {
610 return Ok(0);
611 }
612 if len > 4 {
613 return Err(ProtocolError::TtcDecode("invalid ub4 length"));
614 }
615 let mut value = 0u32;
616 for byte in self.read_raw(usize::from(len))? {
617 value = (value << 8) | u32::from(*byte);
618 }
619 Ok(value)
620 }
621
622 pub fn read_sb4(&mut self) -> Result<i32> {
623 let len = self.read_u8()?;
624 let is_negative = len & 0x80 != 0;
625 let len = len & 0x7f;
626 if len == 0 {
627 return Ok(0);
628 }
629 if len > 4 {
630 return Err(ProtocolError::TtcDecode("invalid sb4 length"));
631 }
632 let mut value = 0u32;
639 for byte in self.read_raw(usize::from(len))? {
640 value = (value << 8) | u32::from(*byte);
641 }
642 let value = value as i32;
643 Ok(if is_negative {
644 value.wrapping_neg()
645 } else {
646 value
647 })
648 }
649
650 pub fn read_sb8(&mut self) -> Result<i64> {
651 let len = self.read_u8()?;
652 let is_negative = len & 0x80 != 0;
653 let len = len & 0x7f;
654 if len == 0 {
655 return Ok(0);
656 }
657 if len > 8 {
658 return Err(ProtocolError::TtcDecode("invalid sb8 length"));
659 }
660 let mut value = 0u64;
663 for byte in self.read_raw(usize::from(len))? {
664 value = (value << 8) | u64::from(*byte);
665 }
666 let value = value as i64;
667 Ok(if is_negative {
668 value.wrapping_neg()
669 } else {
670 value
671 })
672 }
673
674 pub fn read_ub8(&mut self) -> Result<u64> {
675 let len = self.read_u8()?;
676 if len == 0 {
677 return Ok(0);
678 }
679 if len > 8 {
680 return Err(ProtocolError::TtcDecode("invalid ub8 length"));
681 }
682 let mut value = 0u64;
683 for byte in self.read_raw(usize::from(len))? {
684 value = (value << 8) | u64::from(*byte);
685 }
686 Ok(value)
687 }
688
689 pub fn read_bytes_borrowed(&mut self) -> Result<BorrowedBytes<'a>> {
700 let len = self.read_u8()?;
701 if len == TNS_LONG_LENGTH_INDICATOR {
702 let mut out = Vec::new();
703 let mut chunks = 0usize;
704 let mut total = 0usize;
705 loop {
706 let chunk_len = self.read_ub4()?;
707 if chunk_len == 0 {
708 break;
709 }
710 chunks = chunks.checked_add(1).ok_or(ProtocolError::ResourceLimit {
711 limit: "lob_chunks",
712 observed: usize::MAX,
713 maximum: self.limits.max_lob_chunks,
714 })?;
715 self.limits.check_lob_chunks(chunks)?;
716 let chunk_len =
717 usize::try_from(chunk_len).map_err(|_| ProtocolError::InvalidPacketLength {
718 length: usize::MAX,
719 minimum: 0,
720 })?;
721 total = total
722 .checked_add(chunk_len)
723 .ok_or(ProtocolError::ResourceLimit {
724 limit: "response_bytes",
725 observed: usize::MAX,
726 maximum: self.limits.max_response_bytes,
727 })?;
728 self.limits.check_response_bytes(total)?;
729 let chunk = self.read_raw(chunk_len)?;
730 out.extend_from_slice(chunk);
731 }
732 Ok(BorrowedBytes::Chunked(out))
733 } else if len == 0 || len == TNS_NULL_LENGTH_INDICATOR {
734 Ok(BorrowedBytes::Null)
735 } else {
736 self.limits.check_response_bytes(usize::from(len))?;
737 Ok(BorrowedBytes::Slice(self.read_raw(usize::from(len))?))
738 }
739 }
740
741 pub fn skip_bytes_field(&mut self) -> Result<()> {
746 let len = self.read_u8()?;
747 if len == TNS_LONG_LENGTH_INDICATOR {
748 let mut chunks = 0usize;
749 let mut total = 0usize;
750 loop {
751 let chunk_len = self.read_ub4()?;
752 if chunk_len == 0 {
753 break;
754 }
755 chunks = chunks.checked_add(1).ok_or(ProtocolError::ResourceLimit {
756 limit: "lob_chunks",
757 observed: usize::MAX,
758 maximum: self.limits.max_lob_chunks,
759 })?;
760 self.limits.check_lob_chunks(chunks)?;
761 let chunk_len =
762 usize::try_from(chunk_len).map_err(|_| ProtocolError::InvalidPacketLength {
763 length: usize::MAX,
764 minimum: 0,
765 })?;
766 total = total
767 .checked_add(chunk_len)
768 .ok_or(ProtocolError::ResourceLimit {
769 limit: "response_bytes",
770 observed: usize::MAX,
771 maximum: self.limits.max_response_bytes,
772 })?;
773 self.limits.check_response_bytes(total)?;
774 self.skip(chunk_len)?;
775 }
776 Ok(())
777 } else if len == 0 || len == TNS_NULL_LENGTH_INDICATOR {
778 Ok(())
779 } else {
780 self.limits.check_response_bytes(usize::from(len))?;
781 self.skip(usize::from(len))
782 }
783 }
784
785 pub fn read_bytes(&mut self) -> Result<Option<Vec<u8>>> {
786 let len = self.read_u8()?;
787 if len == TNS_LONG_LENGTH_INDICATOR {
788 let mut out = Vec::new();
789 let mut chunks = 0usize;
790 let mut total = 0usize;
791 loop {
792 let chunk_len = self.read_ub4()?;
793 if chunk_len == 0 {
794 break;
795 }
796 chunks = chunks.checked_add(1).ok_or(ProtocolError::ResourceLimit {
797 limit: "lob_chunks",
798 observed: usize::MAX,
799 maximum: self.limits.max_lob_chunks,
800 })?;
801 self.limits.check_lob_chunks(chunks)?;
802 let chunk_len =
803 usize::try_from(chunk_len).map_err(|_| ProtocolError::InvalidPacketLength {
804 length: usize::MAX,
805 minimum: 0,
806 })?;
807 total = total
808 .checked_add(chunk_len)
809 .ok_or(ProtocolError::ResourceLimit {
810 limit: "response_bytes",
811 observed: usize::MAX,
812 maximum: self.limits.max_response_bytes,
813 })?;
814 self.limits.check_response_bytes(total)?;
815 let chunk = self.read_raw(chunk_len)?;
816 out.extend_from_slice(chunk);
817 }
818 Ok(Some(out))
819 } else if len == 0 || len == TNS_NULL_LENGTH_INDICATOR {
820 Ok(None)
821 } else {
822 self.limits.check_response_bytes(usize::from(len))?;
823 Ok(Some(self.read_raw(usize::from(len))?.to_vec()))
824 }
825 }
826
827 pub fn read_bytes_with_length(&mut self) -> Result<Option<Vec<u8>>> {
828 let len =
829 usize::try_from(self.read_ub4()?).map_err(|_| ProtocolError::InvalidPacketLength {
830 length: usize::MAX,
831 minimum: 0,
832 })?;
833 self.limits.check_response_bytes(len)?;
834 if len == 0 {
835 return Ok(None);
836 }
837 let value_start = self.pos;
838 match self.read_bytes() {
839 Ok(Some(bytes)) if bytes.len() == len => Ok(Some(bytes)),
840 Ok(_) | Err(_) => {
841 self.pos = value_start;
842 Ok(Some(self.read_raw(len)?.to_vec()))
843 }
844 }
845 }
846
847 pub fn read_string_with_length(&mut self) -> Result<Option<String>> {
848 let Some(bytes) = self.read_bytes_with_length()? else {
849 return Ok(None);
850 };
851 String::from_utf8(bytes)
852 .map(Some)
853 .map_err(|_| ProtocolError::TtcDecode("server sent non-UTF8 string"))
854 }
855
856 pub fn read_string(&mut self) -> Result<Option<String>> {
857 let Some(bytes) = self.read_bytes()? else {
858 return Ok(None);
859 };
860 String::from_utf8(bytes)
861 .map(Some)
862 .map_err(|_| ProtocolError::TtcDecode("server sent non-UTF8 string"))
863 }
864}
865
866pub fn encode_packet(
867 packet_type: u8,
868 packet_flags: u8,
869 data_flags: Option<u16>,
870 payload: &[u8],
871 width: PacketLengthWidth,
872) -> Result<Vec<u8>> {
873 let data_flags_len = usize::from(data_flags.is_some()) * 2;
874 let length = crate::packet::TNS_HEADER_LEN + data_flags_len + payload.len();
875 let mut out = Vec::with_capacity(length);
876 match width {
877 PacketLengthWidth::Legacy16 => {
878 let wire_length =
879 u16::try_from(length).map_err(|_| ProtocolError::PacketTooLarge { length })?;
880 out.extend_from_slice(&wire_length.to_be_bytes());
881 out.extend_from_slice(&0u16.to_be_bytes());
882 }
883 PacketLengthWidth::Large32 => {
884 let wire_length =
885 u32::try_from(length).map_err(|_| ProtocolError::PacketTooLarge { length })?;
886 out.extend_from_slice(&wire_length.to_be_bytes());
887 }
888 }
889 out.push(packet_type);
890 out.push(packet_flags);
891 out.extend_from_slice(&0u16.to_be_bytes());
892 if let Some(flags) = data_flags {
893 out.extend_from_slice(&flags.to_be_bytes());
894 }
895 out.extend_from_slice(payload);
896 Ok(out)
897}
898
899#[cfg(test)]
900mod tests {
901 use super::*;
902
903 fn assert_resource_limit(
904 result: Result<()>,
905 expected_limit: &'static str,
906 expected_observed: usize,
907 expected_maximum: usize,
908 ) {
909 assert!(
910 matches!(
911 result,
912 Err(ProtocolError::ResourceLimit {
913 limit,
914 observed,
915 maximum,
916 }) if limit == expected_limit
917 && observed == expected_observed
918 && maximum == expected_maximum
919 ),
920 "expected ResourceLimit {{ limit: {expected_limit}, observed: {expected_observed}, maximum: {expected_maximum} }}"
921 );
922 }
923
924 #[test]
925 fn protocol_limits_default_names_every_resource_family() {
926 let limits = ProtocolLimits::default()
927 .validate()
928 .expect("valid defaults");
929 assert_eq!(limits, ProtocolLimits::DEFAULT);
930 let names: Vec<&'static str> = limits
931 .named_limits()
932 .into_iter()
933 .map(|(name, value)| {
934 assert!(value > 0, "{name} must be non-zero");
935 name
936 })
937 .collect();
938 assert_eq!(
939 names,
940 vec![
941 "packet_bytes",
942 "frame_bytes",
943 "response_bytes",
944 "columns",
945 "binds",
946 "batch_rows",
947 "object_depth",
948 "object_elements",
949 "vector_dimensions",
950 "lob_chunks",
951 "length_prefixed_elements",
952 ]
953 );
954 }
955
956 #[test]
957 fn protocol_limits_check_helpers_return_typed_resource_limit_errors() {
958 let limits = ProtocolLimits {
959 max_packet_bytes: 8,
960 max_frame_bytes: 16,
961 max_response_bytes: 32,
962 max_columns: 2,
963 max_binds: 3,
964 max_batch_rows: 4,
965 max_object_depth: 5,
966 max_object_elements: 6,
967 max_vector_dimensions: 7,
968 max_lob_chunks: 8,
969 max_length_prefixed_elements: 9,
970 }
971 .validate()
972 .expect("valid test limits");
973
974 limits.check_packet_bytes(8).expect("boundary accepted");
975 limits.check_frame_bytes(16).expect("boundary accepted");
976 limits.check_response_bytes(32).expect("boundary accepted");
977 limits.check_columns(2).expect("boundary accepted");
978 limits.check_binds(3).expect("boundary accepted");
979 limits.check_batch_rows(4).expect("boundary accepted");
980 limits.check_object_depth(5).expect("boundary accepted");
981 limits.check_object_elements(6).expect("boundary accepted");
982 limits
983 .check_vector_dimensions(7)
984 .expect("boundary accepted");
985 limits.check_lob_chunks(8).expect("boundary accepted");
986 limits
987 .check_length_prefixed_elements(9)
988 .expect("boundary accepted");
989
990 assert_resource_limit(limits.check_packet_bytes(9), "packet_bytes", 9, 8);
991 assert_resource_limit(limits.check_frame_bytes(17), "frame_bytes", 17, 16);
992 assert_resource_limit(limits.check_response_bytes(33), "response_bytes", 33, 32);
993 assert_resource_limit(limits.check_columns(3), "columns", 3, 2);
994 assert_resource_limit(limits.check_binds(4), "binds", 4, 3);
995 assert_resource_limit(limits.check_batch_rows(5), "batch_rows", 5, 4);
996 assert_resource_limit(limits.check_object_depth(6), "object_depth", 6, 5);
997 assert_resource_limit(limits.check_object_elements(7), "object_elements", 7, 6);
998 assert_resource_limit(limits.check_vector_dimensions(8), "vector_dimensions", 8, 7);
999 assert_resource_limit(limits.check_lob_chunks(9), "lob_chunks", 9, 8);
1000 assert_resource_limit(
1001 limits.check_length_prefixed_elements(10),
1002 "length_prefixed_elements",
1003 10,
1004 9,
1005 );
1006 }
1007
1008 #[test]
1009 fn protocol_limits_validate_rejects_zero_and_inverted_byte_hierarchy() {
1010 let zero_columns = ProtocolLimits {
1011 max_columns: 0,
1012 ..ProtocolLimits::DEFAULT
1013 };
1014 assert!(matches!(
1015 zero_columns.validate(),
1016 Err(ProtocolError::ResourceLimit {
1017 limit: "columns",
1018 observed: 0,
1019 maximum: 1,
1020 })
1021 ));
1022
1023 let packet_larger_than_frame = ProtocolLimits {
1024 max_packet_bytes: 17,
1025 max_frame_bytes: 16,
1026 ..ProtocolLimits::DEFAULT
1027 };
1028 assert!(matches!(
1029 packet_larger_than_frame.validate(),
1030 Err(ProtocolError::ResourceLimit {
1031 limit: "packet_bytes",
1032 observed: 17,
1033 maximum: 16,
1034 })
1035 ));
1036
1037 let frame_larger_than_response = ProtocolLimits {
1038 max_packet_bytes: 16,
1039 max_frame_bytes: 33,
1040 max_response_bytes: 32,
1041 ..ProtocolLimits::DEFAULT
1042 };
1043 assert!(matches!(
1044 frame_larger_than_response.validate(),
1045 Err(ProtocolError::ResourceLimit {
1046 limit: "frame_bytes",
1047 observed: 33,
1048 maximum: 32,
1049 })
1050 ));
1051 }
1052
1053 #[test]
1054 fn ttc_reader_with_limits_rejects_oversized_raw_reads() {
1055 let limits = ProtocolLimits {
1056 max_packet_bytes: 4,
1057 max_frame_bytes: 4,
1058 max_response_bytes: 4,
1059 ..ProtocolLimits::DEFAULT
1060 };
1061 let mut reader = TtcReader::with_limits(&[1, 2, 3, 4], limits).expect("valid limits");
1062 assert!(matches!(
1063 reader.read_raw(5),
1064 Err(ProtocolError::ResourceLimit {
1065 limit: "response_bytes",
1066 observed: 5,
1067 maximum: 4,
1068 })
1069 ));
1070 }
1071
1072 #[test]
1073 fn ttc_reader_with_limits_rejects_too_many_lob_chunks() {
1074 let limits = ProtocolLimits {
1075 max_lob_chunks: 1,
1076 ..ProtocolLimits::DEFAULT
1077 };
1078 let bytes = [TNS_LONG_LENGTH_INDICATOR, 1, 1, b'a', 1, 1, b'b', 0];
1079 let mut reader = TtcReader::with_limits(&bytes, limits).expect("valid limits");
1080 assert!(matches!(
1081 reader.read_bytes(),
1082 Err(ProtocolError::ResourceLimit {
1083 limit: "lob_chunks",
1084 observed: 2,
1085 maximum: 1,
1086 })
1087 ));
1088 }
1089
1090 #[test]
1097 fn alloc_count_checked_errs_when_count_exceeds_remaining() {
1098 let bytes = [0u8; 4];
1102 let reader = TtcReader::new(&bytes);
1103 assert!(reader.alloc_count_checked(u32::MAX as usize, 8).is_err());
1104 assert!(reader.alloc_count_checked(usize::MAX, 8).is_err());
1106 }
1107
1108 #[test]
1109 fn alloc_count_checked_ok_when_count_fits() {
1110 let bytes = [0u8; 16];
1112 let reader = TtcReader::new(&bytes);
1113 assert_eq!(
1114 reader.alloc_count_checked(2, 8).expect("fits"),
1115 2,
1116 "a count whose bytes fit must pass through unchanged"
1117 );
1118 assert_eq!(reader.alloc_count_checked(0, 0).expect("zero"), 0);
1121 }
1122
1123 #[test]
1124 fn with_capacity_bounded_caps_preallocation_but_still_grows() {
1125 let bytes = [0u8; 8];
1127 let reader = TtcReader::new(&bytes);
1128 let v: Vec<u32> = reader.with_capacity_bounded(u32::MAX as usize, 4);
1129 assert_eq!(
1131 v.capacity(),
1132 2,
1133 "pre-allocation must be capped by remaining"
1134 );
1135 let mut v = v;
1138 for i in 0..100u32 {
1139 v.push(i);
1140 }
1141 assert_eq!(v.len(), 100);
1142 }
1143
1144 #[test]
1145 fn with_capacity_bounded_uses_full_count_when_buffer_is_large() {
1146 let bytes = [0u8; 400];
1149 let reader = TtcReader::new(&bytes);
1150 let v: Vec<u32> = reader.with_capacity_bounded(10, 4);
1151 assert_eq!(v.capacity(), 10);
1152 }
1153
1154 #[test]
1159 fn sb4_sb8_negate_overflow_does_not_panic() {
1160 let bytes = [0x84u8, 0x80, 0x00, 0x00, 0x00];
1162 let mut reader = TtcReader::new(&bytes);
1163 assert_eq!(reader.read_sb4().expect("sb4 must not panic"), i32::MIN);
1164
1165 let bytes8 = [0x88u8, 0x80, 0, 0, 0, 0, 0, 0, 0];
1167 let mut reader8 = TtcReader::new(&bytes8);
1168 assert_eq!(reader8.read_sb8().expect("sb8 must not panic"), i64::MIN);
1169 }
1170
1171 #[test]
1174 fn sb4_decodes_representative_values() {
1175 let cases: [(&[u8], i32); 4] = [
1177 (&[0x00], 0),
1178 (&[0x01, 0x2a], 42),
1179 (&[0x81, 0x2a], -42),
1180 (&[0x02, 0x01, 0x00], 256),
1181 ];
1182 for (bytes, expected) in cases {
1183 let mut reader = TtcReader::new(bytes);
1184 assert_eq!(
1185 reader.read_sb4().expect("sb4 decode"),
1186 expected,
1187 "{bytes:?}"
1188 );
1189 }
1190 }
1191
1192 #[test]
1193 fn ub4_round_trips_representative_values() {
1194 for value in [0, 1, 255, 256, 65_535, 65_536, u32::MAX] {
1195 let mut writer = TtcWriter::new();
1196 writer.write_ub4(value);
1197 let bytes = writer.into_bytes();
1198 let mut reader = TtcReader::new(&bytes);
1199 assert_eq!(reader.read_ub4().expect("ub4 should decode"), value);
1200 assert_eq!(reader.remaining(), 0);
1201 }
1202 }
1203
1204 #[test]
1211 fn read_bytes_borrowed_borrows_short_values_and_owns_chunked() {
1212 let short = [0x03u8, b'a', b'b', b'c'];
1214 let mut reader = TtcReader::new(&short);
1215 let borrowed = reader.read_bytes_borrowed().expect("short decode");
1216 assert!(matches!(borrowed, BorrowedBytes::Slice(slice) if slice == b"abc"));
1217 assert_eq!(reader.remaining(), 0);
1218
1219 let null = [TNS_NULL_LENGTH_INDICATOR];
1221 let mut reader = TtcReader::new(&null);
1222 assert!(matches!(
1223 reader.read_bytes_borrowed().expect("null decode"),
1224 BorrowedBytes::Null
1225 ));
1226
1227 let zero = [0x00u8];
1229 let mut reader = TtcReader::new(&zero);
1230 assert!(matches!(
1231 reader.read_bytes_borrowed().expect("zero decode"),
1232 BorrowedBytes::Null
1233 ));
1234
1235 let mut writer = TtcWriter::new();
1237 writer
1238 .write_bytes_with_length(&vec![0x5au8; 600]) .expect("chunked encode");
1240 let long = writer.into_bytes();
1241 let mut reader = TtcReader::new(&long);
1242 let expected = vec![0x5au8; 600];
1243 let borrowed = reader.read_bytes_borrowed().expect("chunked decode");
1244 assert!(matches!(&borrowed, BorrowedBytes::Chunked(bytes) if bytes == &expected));
1245 assert_eq!(reader.remaining(), 0);
1246 }
1247
1248 #[test]
1249 fn bytes_with_length_accepts_nested_ttc_bytes() {
1250 let mut writer = TtcWriter::new();
1251 writer
1252 .write_bytes_with_two_lengths(Some(b"abc"))
1253 .expect("bytes should encode");
1254 let bytes = writer.into_bytes();
1255 let mut reader = TtcReader::new(&bytes);
1256 assert_eq!(
1257 reader
1258 .read_bytes_with_length()
1259 .expect("bytes should decode"),
1260 Some(b"abc".to_vec())
1261 );
1262 assert_eq!(reader.remaining(), 0);
1263 }
1264
1265 #[test]
1266 fn bytes_with_length_accepts_direct_payload_bytes() {
1267 let bytes = [1, 3, b'a', b'b', b'c'];
1268 let mut reader = TtcReader::new(&bytes);
1269 assert_eq!(
1270 reader
1271 .read_bytes_with_length()
1272 .expect("bytes should decode"),
1273 Some(b"abc".to_vec())
1274 );
1275 assert_eq!(reader.remaining(), 0);
1276 }
1277
1278 #[test]
1279 fn data_packet_uses_four_byte_length_when_negotiated() {
1280 let packet = encode_packet(
1281 6,
1282 0,
1283 Some(0),
1284 &[0x03, 0x93, 0x01],
1285 PacketLengthWidth::Large32,
1286 )
1287 .expect("packet should encode");
1288 assert_eq!(&packet[..10], &[0, 0, 0, 13, 6, 0, 0, 0, 0, 0]);
1289 }
1290}