1use std::collections::BTreeMap;
39
40use crate::thin::{
41 decode_binary_double, decode_binary_float, decode_datetime_value, decode_interval_ds,
42 decode_number_value, encode_binary_double, encode_binary_float, encode_interval_ds,
43 encode_number_text, encode_oracle_date, encode_oracle_timestamp, QueryValue,
44};
45use crate::wire::BoundedReader;
46use crate::{ProtocolError, Result};
47
48const TNS_JSON_MAGIC_BYTE_1: u8 = 0xff;
50const TNS_JSON_MAGIC_BYTE_2: u8 = 0x4a; const TNS_JSON_MAGIC_BYTE_3: u8 = 0x5a; const TNS_JSON_VERSION_MAX_FNAME_255: u8 = 1;
53const TNS_JSON_VERSION_MAX_FNAME_65535: u8 = 3;
54
55const TNS_JSON_FLAG_HASH_ID_UINT8: u16 = 0x0100;
57const TNS_JSON_FLAG_NUM_FNAMES_UINT16: u16 = 0x0400;
58const TNS_JSON_FLAG_FNAMES_SEG_UINT32: u16 = 0x0800;
59const TNS_JSON_FLAG_TINY_NODES_STAT: u16 = 0x2000;
60const TNS_JSON_FLAG_TREE_SEG_UINT32: u16 = 0x1000;
61const TNS_JSON_FLAG_REL_OFFSET_MODE: u16 = 0x01;
62const TNS_JSON_FLAG_INLINE_LEAF: u16 = 0x02;
63const TNS_JSON_FLAG_NUM_FNAMES_UINT32: u16 = 0x08;
64const TNS_JSON_FLAG_IS_SCALAR: u16 = 0x10;
65
66const TNS_JSON_FLAG_SEC_FNAMES_SEG_UINT16: u16 = 0x0100;
68
69const TNS_JSON_TYPE_NULL: u8 = 0x30;
71const TNS_JSON_TYPE_TRUE: u8 = 0x31;
72const TNS_JSON_TYPE_FALSE: u8 = 0x32;
73const TNS_JSON_TYPE_STRING_LENGTH_UINT8: u8 = 0x33;
74const TNS_JSON_TYPE_NUMBER_LENGTH_UINT8: u8 = 0x34;
75const TNS_JSON_TYPE_BINARY_DOUBLE: u8 = 0x36;
76const TNS_JSON_TYPE_STRING_LENGTH_UINT16: u8 = 0x37;
77const TNS_JSON_TYPE_STRING_LENGTH_UINT32: u8 = 0x38;
78const TNS_JSON_TYPE_TIMESTAMP: u8 = 0x39;
79const TNS_JSON_TYPE_BINARY_LENGTH_UINT16: u8 = 0x3a;
80const TNS_JSON_TYPE_BINARY_LENGTH_UINT32: u8 = 0x3b;
81const TNS_JSON_TYPE_DATE: u8 = 0x3c;
82const TNS_JSON_TYPE_INTERVAL_YM: u8 = 0x3d;
83const TNS_JSON_TYPE_INTERVAL_DS: u8 = 0x3e;
84const TNS_JSON_TYPE_TIMESTAMP_TZ: u8 = 0x7c;
85const TNS_JSON_TYPE_TIMESTAMP7: u8 = 0x7d;
86const TNS_JSON_TYPE_ID: u8 = 0x7e;
87const TNS_JSON_TYPE_BINARY_FLOAT: u8 = 0x7f;
88const TNS_JSON_TYPE_OBJECT: u8 = 0x84;
89const TNS_JSON_TYPE_ARRAY: u8 = 0xc0;
90const TNS_JSON_TYPE_EXTENDED: u8 = 0x7b;
91const TNS_JSON_TYPE_VECTOR: u8 = 0x01;
92
93const ORA_TYPE_SIZE_DATE: usize = 7;
95const ORA_TYPE_SIZE_TIMESTAMP: usize = 11;
96const ORA_TYPE_SIZE_TIMESTAMP_TZ: usize = 13;
97const ORA_TYPE_SIZE_INTERVAL_DS: usize = 11;
98
99const MAX_FNAME_SIZE_SHORT: usize = 255;
102const MAX_FNAME_SIZE_LONG: usize = 65535;
103
104#[derive(Clone, Debug, PartialEq)]
114pub enum OsonValue {
115 Null,
116 Bool(bool),
117 Number(String),
120 BinaryFloat(f32),
121 BinaryDouble(f64),
122 String(String),
124 Raw(Vec<u8>),
126 DateTime {
129 year: i32,
130 month: u8,
131 day: u8,
132 hour: u8,
133 minute: u8,
134 second: u8,
135 nanosecond: u32,
136 },
137 IntervalDS {
139 days: i32,
140 hours: i32,
141 minutes: i32,
142 seconds: i32,
143 fseconds: i32,
144 },
145 Vector(crate::vector::Vector),
147 Array(Vec<OsonValue>),
148 Object(Vec<(String, OsonValue)>),
150}
151
152struct OsonReader<'a> {
160 data: &'a [u8],
161 pos: usize,
162}
163
164impl<'a> OsonReader<'a> {
165 fn new(data: &'a [u8]) -> Self {
166 Self { data, pos: 0 }
167 }
168
169 fn invalid(reason: &'static str) -> ProtocolError {
170 ProtocolError::OsonInvalid(reason)
171 }
172
173 fn read_raw(&mut self, len: usize) -> Result<&'a [u8]> {
174 let end = self
175 .pos
176 .checked_add(len)
177 .ok_or(ProtocolError::OsonInvalid("length overflow"))?;
178 let slice = self
179 .data
180 .get(self.pos..end)
181 .ok_or(ProtocolError::OsonInvalid("read past end of OSON image"))?;
182 self.pos = end;
183 Ok(slice)
184 }
185
186 fn read_u8(&mut self) -> Result<u8> {
187 Ok(self.read_raw(1)?[0])
188 }
189
190 fn read_u16be(&mut self) -> Result<u16> {
191 let raw = self.read_raw(2)?;
192 Ok(u16::from_be_bytes([raw[0], raw[1]]))
193 }
194
195 fn read_u32be(&mut self) -> Result<u32> {
196 let raw = self.read_raw(4)?;
197 Ok(u32::from_be_bytes([raw[0], raw[1], raw[2], raw[3]]))
198 }
199
200 fn skip(&mut self, len: usize) -> Result<()> {
201 self.read_raw(len)?;
202 Ok(())
203 }
204
205 fn seek_to(&mut self, pos: usize) -> Result<()> {
209 if pos > self.data.len() {
210 return Err(Self::invalid("seek past end of OSON image"));
211 }
212 self.pos = pos;
213 Ok(())
214 }
215}
216
217impl crate::wire::BoundedReader for OsonReader<'_> {
218 fn remaining(&self) -> usize {
219 self.data.len()
225 }
226}
227
228const MAX_OSON_DEPTH: usize = 1_000;
235
236struct OsonDecoder<'a> {
238 reader: OsonReader<'a>,
239 field_names: Vec<String>,
240 field_id_length: usize,
241 tree_seg_pos: usize,
242 relative_offsets: bool,
243 depth: usize,
245}
246
247impl<'a> OsonDecoder<'a> {
248 fn read_field_names(
252 &mut self,
253 num_fields: usize,
254 hash_id_size: usize,
255 offsets_size: usize,
256 name_len_size: usize,
257 seg_size: usize,
258 ) -> Result<Vec<String>> {
259 self.reader.skip(num_fields * hash_id_size)?;
261
262 let offsets_pos = self.reader.pos;
265 self.reader.skip(num_fields * offsets_size)?;
266 let seg = self.reader.read_raw(seg_size)?;
267 let final_pos = self.reader.pos;
268
269 self.reader.seek_to(offsets_pos)?;
270 let mut names: Vec<String> = self.reader.with_capacity_bounded(num_fields, 1);
274 for _ in 0..num_fields {
275 let offset = if offsets_size == 2 {
276 usize::from(self.reader.read_u16be()?)
277 } else {
278 self.reader.read_u32be()? as usize
279 };
280 let (name_len, name_start) = if name_len_size == 2 {
281 let hi = *seg
282 .get(offset)
283 .ok_or(ProtocolError::OsonInvalid("field name offset out of range"))?;
284 let lo = *seg
285 .get(offset + 1)
286 .ok_or(ProtocolError::OsonInvalid("field name offset out of range"))?;
287 (usize::from(u16::from_be_bytes([hi, lo])), offset + 2)
288 } else {
289 let len = *seg
290 .get(offset)
291 .ok_or(ProtocolError::OsonInvalid("field name offset out of range"))?;
292 (usize::from(len), offset + 1)
293 };
294 let end = name_start
295 .checked_add(name_len)
296 .ok_or(ProtocolError::OsonInvalid("field name length overflow"))?;
297 let bytes = seg
298 .get(name_start..end)
299 .ok_or(ProtocolError::OsonInvalid("field name past end of segment"))?;
300 names.push(
301 std::str::from_utf8(bytes)
302 .map_err(|_| ProtocolError::OsonInvalid("field name is not valid UTF-8"))?
303 .to_string(),
304 );
305 }
306 self.reader.seek_to(final_pos)?;
307 Ok(names)
308 }
309
310 fn get_num_children(&mut self, node_type: u8) -> Result<(u32, bool)> {
314 let children_bits = node_type & 0x18;
315 if children_bits == 0x18 {
316 return Ok((0, true));
317 }
318 let num = match children_bits {
319 0x00 => u32::from(self.reader.read_u8()?),
320 0x08 => u32::from(self.reader.read_u16be()?),
321 0x10 => self.reader.read_u32be()?,
322 _ => return Err(ProtocolError::OsonInvalid("invalid container width")),
323 };
324 Ok((num, false))
325 }
326
327 fn get_offset(&mut self, node_type: u8) -> Result<u32> {
329 if node_type & 0x20 != 0 {
330 self.reader.read_u32be()
331 } else {
332 Ok(u32::from(self.reader.read_u16be()?))
333 }
334 }
335
336 fn decode_container_node(&mut self, node_type: u8) -> Result<OsonValue> {
337 let is_object = (node_type & 0x40) == 0;
338 let container_offset = (self.reader.pos - self.tree_seg_pos - 1) as u32;
341
342 let (mut num_children, is_shared) = self.get_num_children(node_type)?;
343 let mut field_ids_pos = 0usize;
344 let mut offsets_pos;
345
346 if is_shared {
347 let offset = self.get_offset(node_type)?;
350 offsets_pos = self.reader.pos;
351 self.reader.seek_to(self.tree_seg_pos + offset as usize)?;
352 let shared_type = self.reader.read_u8()?;
353 let (shared_num, _) = self.get_num_children(shared_type)?;
354 num_children = shared_num;
355 field_ids_pos = self.reader.pos;
356 } else if is_object {
357 field_ids_pos = self.reader.pos;
358 offsets_pos = self.reader.pos + self.field_id_length * num_children as usize;
359 } else {
360 offsets_pos = self.reader.pos;
361 }
362
363 let (mut object, mut array): (Vec<(String, OsonValue)>, Vec<OsonValue>) = if is_object {
370 (
371 self.reader.with_capacity_bounded(num_children as usize, 1),
372 Vec::new(),
373 )
374 } else {
375 (
376 Vec::new(),
377 self.reader.with_capacity_bounded(num_children as usize, 1),
378 )
379 };
380
381 for _ in 0..num_children {
382 let mut name = String::new();
383 if is_object {
384 self.reader.seek_to(field_ids_pos)?;
385 let field_id = match self.field_id_length {
386 1 => u32::from(self.reader.read_u8()?),
387 2 => u32::from(self.reader.read_u16be()?),
388 4 => self.reader.read_u32be()?,
389 _ => return Err(ProtocolError::OsonInvalid("invalid field id length")),
390 };
391 let index = (field_id as usize)
392 .checked_sub(1)
393 .ok_or(ProtocolError::OsonInvalid("field id out of range"))?;
394 name = self
395 .field_names
396 .get(index)
397 .ok_or(ProtocolError::OsonInvalid("field id out of range"))?
398 .clone();
399 field_ids_pos = self.reader.pos;
400 }
401 self.reader.seek_to(offsets_pos)?;
402 let mut offset = self.get_offset(node_type)?;
403 if self.relative_offsets {
404 offset = offset
405 .checked_add(container_offset)
406 .ok_or(ProtocolError::OsonInvalid("relative offset overflow"))?;
407 }
408 offsets_pos = self.reader.pos;
409 self.reader.seek_to(self.tree_seg_pos + offset as usize)?;
410 let child = self.decode_node()?;
411 if is_object {
412 object.push((name, child));
413 } else {
414 array.push(child);
415 }
416 }
417
418 if is_object {
419 Ok(OsonValue::Object(object))
420 } else {
421 Ok(OsonValue::Array(array))
422 }
423 }
424
425 fn decode_scalar_with_node_type(&mut self, node_type: u8) -> Result<OsonValue> {
426 match node_type {
427 TNS_JSON_TYPE_NULL => Ok(OsonValue::Null),
428 TNS_JSON_TYPE_TRUE => Ok(OsonValue::Bool(true)),
429 TNS_JSON_TYPE_FALSE => Ok(OsonValue::Bool(false)),
430 TNS_JSON_TYPE_DATE | TNS_JSON_TYPE_TIMESTAMP7 => {
431 self.decode_datetime(ORA_TYPE_SIZE_DATE)
432 }
433 TNS_JSON_TYPE_TIMESTAMP => self.decode_datetime(ORA_TYPE_SIZE_TIMESTAMP),
434 TNS_JSON_TYPE_TIMESTAMP_TZ => self.decode_datetime(ORA_TYPE_SIZE_TIMESTAMP_TZ),
435 TNS_JSON_TYPE_BINARY_FLOAT => {
436 let raw = self.reader.read_raw(4)?;
437 Ok(OsonValue::BinaryFloat(decode_binary_float(raw)?))
438 }
439 TNS_JSON_TYPE_BINARY_DOUBLE => {
440 let raw = self.reader.read_raw(8)?;
441 Ok(OsonValue::BinaryDouble(decode_binary_double(raw)?))
442 }
443 TNS_JSON_TYPE_INTERVAL_DS => {
444 let raw = self.reader.read_raw(ORA_TYPE_SIZE_INTERVAL_DS)?;
445 match decode_interval_ds(raw)? {
446 QueryValue::IntervalDS {
447 days,
448 hours,
449 minutes,
450 seconds,
451 fseconds,
452 } => Ok(OsonValue::IntervalDS {
453 days,
454 hours,
455 minutes,
456 seconds,
457 fseconds,
458 }),
459 _ => Err(ProtocolError::OsonInvalid("INTERVAL DS decode mismatch")),
460 }
461 }
462 TNS_JSON_TYPE_INTERVAL_YM => {
463 Err(ProtocolError::OsonTypeNotSupported("DB_TYPE_INTERVAL_YM"))
464 }
465 TNS_JSON_TYPE_STRING_LENGTH_UINT8 => {
466 let len = usize::from(self.reader.read_u8()?);
467 self.decode_string(len)
468 }
469 TNS_JSON_TYPE_STRING_LENGTH_UINT16 => {
470 let len = usize::from(self.reader.read_u16be()?);
471 self.decode_string(len)
472 }
473 TNS_JSON_TYPE_STRING_LENGTH_UINT32 => {
474 let len = self.reader.read_u32be()? as usize;
475 self.decode_string(len)
476 }
477 TNS_JSON_TYPE_NUMBER_LENGTH_UINT8 => {
478 let len = usize::from(self.reader.read_u8()?);
479 self.decode_number(len)
480 }
481 TNS_JSON_TYPE_ID => {
482 let len = usize::from(self.reader.read_u8()?);
483 Ok(OsonValue::Raw(self.reader.read_raw(len)?.to_vec()))
484 }
485 TNS_JSON_TYPE_BINARY_LENGTH_UINT16 => {
486 let len = usize::from(self.reader.read_u16be()?);
487 Ok(OsonValue::Raw(self.reader.read_raw(len)?.to_vec()))
488 }
489 TNS_JSON_TYPE_BINARY_LENGTH_UINT32 => {
490 let len = self.reader.read_u32be()? as usize;
491 Ok(OsonValue::Raw(self.reader.read_raw(len)?.to_vec()))
492 }
493 TNS_JSON_TYPE_EXTENDED => {
494 let extended_type = self.reader.read_u8()?;
495 if extended_type == TNS_JSON_TYPE_VECTOR {
496 let len = self.reader.read_u32be()? as usize;
497 let raw = self.reader.read_raw(len)?;
498 let vector = crate::vector::decode_vector(raw)
499 .map_err(|_| ProtocolError::OsonInvalid("invalid embedded VECTOR"))?;
500 Ok(OsonValue::Vector(vector))
501 } else {
502 Err(ProtocolError::OsonTypeNotSupported("JSON extended type"))
503 }
504 }
505 _ => self.decode_node_type_with_inline_length(node_type),
506 }
507 }
508
509 fn decode_node_type_with_inline_length(&mut self, node_type: u8) -> Result<OsonValue> {
512 match node_type & 0xf0 {
513 0x20 | 0x60 => {
514 let len = usize::from(node_type & 0x0f) + 1;
515 self.decode_number(len)
516 }
517 0x40 | 0x50 => {
518 let len = usize::from(node_type & 0x0f);
519 self.decode_number(len)
520 }
521 _ => {
522 if node_type & 0xe0 == 0 {
523 if node_type == 0 {
524 return Ok(OsonValue::String(String::new()));
525 }
526 self.decode_string(usize::from(node_type))
527 } else {
528 Err(ProtocolError::OsonInvalid("unsupported OSON node type"))
529 }
530 }
531 }
532 }
533
534 fn decode_datetime(&mut self, len: usize) -> Result<OsonValue> {
535 let raw = self.reader.read_raw(len)?;
536 match decode_datetime_value(raw)? {
537 QueryValue::DateTime {
538 year,
539 month,
540 day,
541 hour,
542 minute,
543 second,
544 nanosecond,
545 } => Ok(OsonValue::DateTime {
546 year,
547 month,
548 day,
549 hour,
550 minute,
551 second,
552 nanosecond,
553 }),
554 _ => Err(ProtocolError::OsonInvalid("datetime decode mismatch")),
555 }
556 }
557
558 fn decode_string(&mut self, len: usize) -> Result<OsonValue> {
559 let raw = self.reader.read_raw(len)?;
560 Ok(OsonValue::String(
561 std::str::from_utf8(raw)
562 .map_err(|_| ProtocolError::OsonInvalid("string is not valid UTF-8"))?
563 .to_string(),
564 ))
565 }
566
567 fn decode_number(&mut self, len: usize) -> Result<OsonValue> {
568 let raw = self.reader.read_raw(len)?;
569 match decode_number_value(raw)? {
570 QueryValue::Number(num) => Ok(OsonValue::Number(num.to_canonical_string())),
573 _ => Err(ProtocolError::OsonInvalid("number decode mismatch")),
574 }
575 }
576
577 fn decode_node(&mut self) -> Result<OsonValue> {
578 let node_type = self.reader.read_u8()?;
579 if node_type & 0x80 != 0 {
580 self.depth += 1;
581 if self.depth > MAX_OSON_DEPTH {
582 return Err(ProtocolError::OsonInvalid(
583 "OSON nesting depth exceeds limit",
584 ));
585 }
586 let value = self.decode_container_node(node_type);
587 self.depth -= 1;
588 return value;
589 }
590 self.decode_scalar_with_node_type(node_type)
591 }
592}
593
594pub fn decode_oson(data: &[u8]) -> Result<OsonValue> {
601 let mut reader = OsonReader::new(data);
602
603 let magic = reader
604 .read_raw(3)
605 .map_err(|_| ProtocolError::OsonNotEncoded("image too short for header"))?;
606 if magic[0] != TNS_JSON_MAGIC_BYTE_1
607 || magic[1] != TNS_JSON_MAGIC_BYTE_2
608 || magic[2] != TNS_JSON_MAGIC_BYTE_3
609 {
610 return Err(ProtocolError::OsonNotEncoded("bad OSON magic"));
611 }
612 let version = reader
613 .read_u8()
614 .map_err(|_| ProtocolError::OsonNotEncoded("missing OSON version"))?;
615 if version != TNS_JSON_VERSION_MAX_FNAME_255 && version != TNS_JSON_VERSION_MAX_FNAME_65535 {
616 return Err(ProtocolError::OsonNotEncoded("unsupported OSON version"));
617 }
618 let primary_flags = reader
619 .read_u16be()
620 .map_err(|_| ProtocolError::OsonNotEncoded("missing OSON flags"))?;
621 let relative_offsets = primary_flags & TNS_JSON_FLAG_REL_OFFSET_MODE != 0;
622
623 if primary_flags & TNS_JSON_FLAG_IS_SCALAR != 0 {
625 if primary_flags & TNS_JSON_FLAG_TREE_SEG_UINT32 != 0 {
626 reader.skip(4)?;
627 } else {
628 reader.skip(2)?;
629 }
630 let mut decoder = OsonDecoder {
631 reader,
632 field_names: Vec::new(),
633 field_id_length: 1,
634 tree_seg_pos: 0,
635 relative_offsets,
636 depth: 0,
637 };
638 decoder.tree_seg_pos = decoder.reader.pos;
639 return decoder.decode_node();
640 }
641
642 let (num_short_field_names, field_id_length) =
644 if primary_flags & TNS_JSON_FLAG_NUM_FNAMES_UINT32 != 0 {
645 (reader.read_u32be()? as usize, 4usize)
646 } else if primary_flags & TNS_JSON_FLAG_NUM_FNAMES_UINT16 != 0 {
647 (usize::from(reader.read_u16be()?), 2usize)
648 } else {
649 (usize::from(reader.read_u8()?), 1usize)
650 };
651
652 let (short_offsets_size, short_seg_size) =
654 if primary_flags & TNS_JSON_FLAG_FNAMES_SEG_UINT32 != 0 {
655 (4usize, reader.read_u32be()? as usize)
656 } else {
657 (2usize, usize::from(reader.read_u16be()?))
658 };
659
660 let mut num_long_field_names = 0usize;
662 let mut long_offsets_size = 0usize;
663 let mut long_seg_size = 0usize;
664 if version == TNS_JSON_VERSION_MAX_FNAME_65535 {
665 let secondary_flags = reader.read_u16be()?;
666 long_offsets_size = if secondary_flags & TNS_JSON_FLAG_SEC_FNAMES_SEG_UINT16 != 0 {
667 2
668 } else {
669 4
670 };
671 num_long_field_names = reader.read_u32be()? as usize;
672 long_seg_size = reader.read_u32be()? as usize;
673 }
674
675 let _tree_seg_size = if primary_flags & TNS_JSON_FLAG_TREE_SEG_UINT32 != 0 {
677 reader.read_u32be()? as usize
678 } else {
679 usize::from(reader.read_u16be()?)
680 };
681
682 let _num_tiny_nodes = reader.read_u16be()?;
684
685 let field_names = reader.with_capacity_bounded(
692 num_short_field_names.saturating_add(num_long_field_names),
693 1,
694 );
695 let mut decoder = OsonDecoder {
696 reader,
697 field_names,
698 field_id_length,
699 tree_seg_pos: 0,
700 relative_offsets,
701 depth: 0,
702 };
703
704 if num_short_field_names > 0 {
705 let names = decoder.read_field_names(
706 num_short_field_names,
707 1,
708 short_offsets_size,
709 1,
710 short_seg_size,
711 )?;
712 decoder.field_names.extend(names);
713 }
714 if num_long_field_names > 0 {
715 let names = decoder.read_field_names(
716 num_long_field_names,
717 2,
718 long_offsets_size,
719 2,
720 long_seg_size,
721 )?;
722 decoder.field_names.extend(names);
723 }
724
725 decoder.tree_seg_pos = decoder.reader.pos;
726 decoder.decode_node()
727}
728
729#[derive(Clone)]
736struct FieldName {
737 name: String,
738 name_bytes: Vec<u8>,
739 hash_id: u32,
740 offset: usize,
741 field_id: u32,
742}
743
744impl FieldName {
745 fn new(name: &str, max_fname_size: usize) -> Result<Self> {
746 let name_bytes = name.as_bytes().to_vec();
747 if name_bytes.len() > max_fname_size {
748 return Err(ProtocolError::OsonInvalid(
749 "field name exceeds maximum length for this connection",
750 ));
751 }
752 let mut hash_id: u32 = 0x811C_9DC5;
754 for &b in &name_bytes {
755 hash_id = (hash_id ^ u32::from(b)).wrapping_mul(16_777_619);
756 }
757 Ok(Self {
758 name: name.to_string(),
759 name_bytes,
760 hash_id,
761 offset: 0,
762 field_id: 0,
763 })
764 }
765
766 fn sort_key(&self) -> (u8, usize, &[u8]) {
769 (
770 (self.hash_id & 0xff) as u8,
771 self.name_bytes.len(),
772 &self.name_bytes,
773 )
774 }
775}
776
777struct FieldNamesSegment {
779 buffer: Vec<u8>,
780 field_names: Vec<FieldName>,
781 num_field_names: u32,
782}
783
784impl FieldNamesSegment {
785 fn new() -> Self {
786 Self {
787 buffer: Vec::new(),
788 field_names: Vec::new(),
789 num_field_names: 0,
790 }
791 }
792
793 fn add_name(&mut self, mut field_name: FieldName) {
794 field_name.offset = self.buffer.len();
795 if field_name.name_bytes.len() <= 255 {
796 self.buffer.push(field_name.name_bytes.len() as u8);
797 } else {
798 self.buffer
799 .extend_from_slice(&(field_name.name_bytes.len() as u16).to_be_bytes());
800 }
801 self.buffer.extend_from_slice(&field_name.name_bytes);
802 self.field_names.push(field_name);
803 }
804
805 fn process_field_names(&mut self, field_id_offset: u32) {
806 self.field_names
807 .sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
808 for (index, field_name) in self.field_names.iter_mut().enumerate() {
809 field_name.field_id = field_id_offset + index as u32 + 1;
810 }
811 self.num_field_names = self.field_names.len() as u32;
812 }
813}
814
815struct TreeSegment {
817 buffer: Vec<u8>,
818}
819
820impl TreeSegment {
821 fn new() -> Self {
822 Self { buffer: Vec::new() }
823 }
824
825 fn encode_container_header(&mut self, mut node_type: u8, num_children: usize) {
826 node_type |= 0x20; if num_children > 65535 {
828 node_type |= 0x10;
829 } else if num_children > 255 {
830 node_type |= 0x08;
831 }
832 self.buffer.push(node_type);
833 if num_children < 256 {
834 self.buffer.push(num_children as u8);
835 } else if num_children < 65536 {
836 self.buffer
837 .extend_from_slice(&(num_children as u16).to_be_bytes());
838 } else {
839 self.buffer
840 .extend_from_slice(&(num_children as u32).to_be_bytes());
841 }
842 }
843
844 fn encode_array(&mut self, values: &[OsonValue], encoder: &OsonEncoder) -> Result<()> {
845 let num_children = values.len();
846 self.encode_container_header(TNS_JSON_TYPE_ARRAY, num_children);
847 let mut offset = self.buffer.len();
848 self.buffer.resize(self.buffer.len() + num_children * 4, 0);
849 for element in values {
850 let pos = self.buffer.len() as u32;
851 self.buffer[offset..offset + 4].copy_from_slice(&pos.to_be_bytes());
852 offset += 4;
853 self.encode_node(element, encoder)?;
854 }
855 Ok(())
856 }
857
858 fn encode_object(
859 &mut self,
860 entries: &[(String, OsonValue)],
861 encoder: &OsonEncoder,
862 ) -> Result<()> {
863 let num_children = entries.len();
864 self.encode_container_header(TNS_JSON_TYPE_OBJECT, num_children);
865 let mut field_id_offset = self.buffer.len();
866 let mut value_offset = self.buffer.len() + num_children * encoder.field_id_size;
867 let final_offset = value_offset + num_children * 4;
868 self.buffer.resize(final_offset, 0);
869 for (key, child_value) in entries {
870 let field_name = encoder
871 .field_names_dict
872 .get(key)
873 .ok_or(ProtocolError::OsonInvalid("missing field id for key"))?;
874 match encoder.field_id_size {
875 1 => self.buffer[field_id_offset] = field_name.field_id as u8,
876 2 => self.buffer[field_id_offset..field_id_offset + 2]
877 .copy_from_slice(&(field_name.field_id as u16).to_be_bytes()),
878 _ => self.buffer[field_id_offset..field_id_offset + 4]
879 .copy_from_slice(&field_name.field_id.to_be_bytes()),
880 }
881 let pos = self.buffer.len() as u32;
882 self.buffer[value_offset..value_offset + 4].copy_from_slice(&pos.to_be_bytes());
883 field_id_offset += encoder.field_id_size;
884 value_offset += 4;
885 self.encode_node(child_value, encoder)?;
886 }
887 Ok(())
888 }
889
890 fn write_string(&mut self, bytes: &[u8]) {
891 let len = bytes.len();
892 if len < 256 {
893 self.buffer.push(TNS_JSON_TYPE_STRING_LENGTH_UINT8);
894 self.buffer.push(len as u8);
895 } else if len < 65536 {
896 self.buffer.push(TNS_JSON_TYPE_STRING_LENGTH_UINT16);
897 self.buffer.extend_from_slice(&(len as u16).to_be_bytes());
898 } else {
899 self.buffer.push(TNS_JSON_TYPE_STRING_LENGTH_UINT32);
900 self.buffer.extend_from_slice(&(len as u32).to_be_bytes());
901 }
902 if len > 0 {
903 self.buffer.extend_from_slice(bytes);
904 }
905 }
906
907 fn encode_node(&mut self, value: &OsonValue, encoder: &OsonEncoder) -> Result<()> {
908 match value {
909 OsonValue::Null => self.buffer.push(TNS_JSON_TYPE_NULL),
910 OsonValue::Bool(true) => self.buffer.push(TNS_JSON_TYPE_TRUE),
911 OsonValue::Bool(false) => self.buffer.push(TNS_JSON_TYPE_FALSE),
912 OsonValue::Number(text) => {
913 let encoded = encode_number_text(text)
914 .map_err(|_| ProtocolError::OsonInvalid("invalid JSON number"))?;
915 self.buffer.push(TNS_JSON_TYPE_NUMBER_LENGTH_UINT8);
916 self.buffer.push(encoded.len() as u8);
917 self.buffer.extend_from_slice(&encoded);
918 }
919 OsonValue::BinaryFloat(value) => {
920 self.buffer.push(TNS_JSON_TYPE_BINARY_FLOAT);
921 self.buffer.extend_from_slice(&encode_binary_float(*value));
922 }
923 OsonValue::BinaryDouble(value) => {
924 self.buffer.push(TNS_JSON_TYPE_BINARY_DOUBLE);
925 self.buffer.extend_from_slice(&encode_binary_double(*value));
926 }
927 OsonValue::String(text) => self.write_string(text.as_bytes()),
928 OsonValue::Raw(bytes) => {
929 let len = bytes.len();
930 if len < 65536 {
931 self.buffer.push(TNS_JSON_TYPE_BINARY_LENGTH_UINT16);
932 self.buffer.extend_from_slice(&(len as u16).to_be_bytes());
933 } else {
934 self.buffer.push(TNS_JSON_TYPE_BINARY_LENGTH_UINT32);
935 self.buffer.extend_from_slice(&(len as u32).to_be_bytes());
936 }
937 self.buffer.extend_from_slice(bytes);
938 }
939 OsonValue::DateTime {
940 year,
941 month,
942 day,
943 hour,
944 minute,
945 second,
946 nanosecond,
947 } => {
948 if *nanosecond == 0 {
949 self.buffer.push(TNS_JSON_TYPE_TIMESTAMP7);
950 let bytes = encode_oracle_date(*year, *month, *day, *hour, *minute, *second)?;
951 self.buffer.extend_from_slice(&bytes);
952 } else {
953 self.buffer.push(TNS_JSON_TYPE_TIMESTAMP);
954 let bytes = encode_oracle_timestamp(
955 *year,
956 *month,
957 *day,
958 *hour,
959 *minute,
960 *second,
961 *nanosecond,
962 )?;
963 self.buffer.extend_from_slice(&bytes);
965 }
966 }
967 OsonValue::IntervalDS {
968 days,
969 hours,
970 minutes,
971 seconds,
972 fseconds,
973 } => {
974 let total_seconds = hours * 3600 + minutes * 60 + seconds;
975 let microseconds = fseconds / 1000;
976 let bytes = encode_interval_ds(*days, total_seconds, microseconds)?;
977 self.buffer.push(TNS_JSON_TYPE_INTERVAL_DS);
978 self.buffer.extend_from_slice(&bytes);
979 }
980 OsonValue::Vector(vector) => {
981 self.buffer.push(TNS_JSON_TYPE_EXTENDED);
982 self.buffer.push(TNS_JSON_TYPE_VECTOR);
983 let image = crate::vector::encode_vector(vector);
984 self.buffer
985 .extend_from_slice(&(image.len() as u32).to_be_bytes());
986 self.buffer.extend_from_slice(&image);
987 }
988 OsonValue::Array(values) => self.encode_array(values, encoder)?,
989 OsonValue::Object(entries) => self.encode_object(entries, encoder)?,
990 }
991 Ok(())
992 }
993}
994
995struct OsonEncoder {
997 buffer: Vec<u8>,
998 field_names_dict: BTreeMap<String, FieldName>,
999 short_fnames_seg: Option<FieldNamesSegment>,
1000 long_fnames_seg: Option<FieldNamesSegment>,
1001 num_field_names: u32,
1002 field_id_size: usize,
1003 max_fname_size: usize,
1004 is_scalar: bool,
1005}
1006
1007impl OsonEncoder {
1008 fn new(max_fname_size: usize) -> Self {
1009 Self {
1010 buffer: Vec::new(),
1011 field_names_dict: BTreeMap::new(),
1012 short_fnames_seg: None,
1013 long_fnames_seg: None,
1014 num_field_names: 0,
1015 field_id_size: 1,
1016 max_fname_size,
1017 is_scalar: false,
1018 }
1019 }
1020
1021 fn add_field_name(&mut self, name: &str) -> Result<()> {
1022 if self.field_names_dict.contains_key(name) {
1023 return Ok(());
1024 }
1025 let field_name = FieldName::new(name, self.max_fname_size)?;
1026 self.field_names_dict
1027 .insert(name.to_string(), field_name.clone());
1028 if field_name.name_bytes.len() <= 255 {
1029 self.short_fnames_seg
1030 .get_or_insert_with(FieldNamesSegment::new)
1031 .add_name(field_name);
1032 } else {
1033 self.long_fnames_seg
1034 .get_or_insert_with(FieldNamesSegment::new)
1035 .add_name(field_name);
1036 }
1037 Ok(())
1038 }
1039
1040 fn examine_node(&mut self, value: &OsonValue) -> Result<()> {
1042 match value {
1043 OsonValue::Array(values) => {
1044 for child in values {
1045 self.examine_node(child)?;
1046 }
1047 }
1048 OsonValue::Object(entries) => {
1049 for (key, child) in entries {
1050 self.add_field_name(key)?;
1051 self.examine_node(child)?;
1052 }
1053 }
1054 _ => {}
1055 }
1056 Ok(())
1057 }
1058
1059 fn determine_flags(&mut self, value: &OsonValue) -> Result<u16> {
1061 let mut flags = TNS_JSON_FLAG_INLINE_LEAF;
1062 if !matches!(value, OsonValue::Array(_) | OsonValue::Object(_)) {
1063 self.is_scalar = true;
1064 flags |= TNS_JSON_FLAG_IS_SCALAR;
1065 return Ok(flags);
1066 }
1067
1068 self.short_fnames_seg = Some(FieldNamesSegment::new());
1069 self.examine_node(value)?;
1070
1071 if let Some(seg) = self.short_fnames_seg.as_mut() {
1072 seg.process_field_names(0);
1073 self.num_field_names += seg.num_field_names;
1074 }
1075 if let Some(seg) = self.long_fnames_seg.as_mut() {
1076 seg.process_field_names(self.num_field_names);
1077 self.num_field_names += seg.num_field_names;
1078 }
1079 self.sync_field_ids();
1082
1083 flags |= TNS_JSON_FLAG_HASH_ID_UINT8 | TNS_JSON_FLAG_TINY_NODES_STAT;
1084 if self.num_field_names > 65535 {
1085 flags |= TNS_JSON_FLAG_NUM_FNAMES_UINT32;
1086 self.field_id_size = 4;
1087 } else if self.num_field_names > 255 {
1088 flags |= TNS_JSON_FLAG_NUM_FNAMES_UINT16;
1089 self.field_id_size = 2;
1090 } else {
1091 self.field_id_size = 1;
1092 }
1093 if let Some(seg) = self.short_fnames_seg.as_ref() {
1094 if seg.buffer.len() > 65535 {
1095 flags |= TNS_JSON_FLAG_FNAMES_SEG_UINT32;
1096 }
1097 }
1098 Ok(flags)
1099 }
1100
1101 fn sync_field_ids(&mut self) {
1104 for seg in [
1105 self.short_fnames_seg.as_ref(),
1106 self.long_fnames_seg.as_ref(),
1107 ]
1108 .into_iter()
1109 .flatten()
1110 {
1111 for field_name in &seg.field_names {
1112 if let Some(entry) = self.field_names_dict.get_mut(&field_name.name) {
1113 entry.field_id = field_name.field_id;
1114 entry.offset = field_name.offset;
1115 }
1116 }
1117 }
1118 }
1119
1120 fn write_u8(&mut self, value: u8) {
1121 self.buffer.push(value);
1122 }
1123
1124 fn write_u16be(&mut self, value: u16) {
1125 self.buffer.extend_from_slice(&value.to_be_bytes());
1126 }
1127
1128 fn write_u32be(&mut self, value: u32) {
1129 self.buffer.extend_from_slice(&value.to_be_bytes());
1130 }
1131
1132 fn write_extended_header(&mut self) {
1133 let short_num = self
1134 .short_fnames_seg
1135 .as_ref()
1136 .map_or(0, |seg| seg.num_field_names);
1137 match self.field_id_size {
1138 1 => self.write_u8(short_num as u8),
1139 2 => self.write_u16be(short_num as u16),
1140 _ => self.write_u32be(short_num),
1141 }
1142 let short_seg_len = self
1143 .short_fnames_seg
1144 .as_ref()
1145 .map_or(0, |seg| seg.buffer.len());
1146 if short_seg_len < 65536 {
1147 self.write_u16be(short_seg_len as u16);
1148 } else {
1149 self.write_u32be(short_seg_len as u32);
1150 }
1151 if let Some(long_seg) = self.long_fnames_seg.as_ref() {
1152 let long_seg_len = long_seg.buffer.len();
1153 let long_num = long_seg.num_field_names;
1154 let secondary_flags = if long_seg_len < 65536 {
1155 TNS_JSON_FLAG_SEC_FNAMES_SEG_UINT16
1156 } else {
1157 0
1158 };
1159 self.write_u16be(secondary_flags);
1160 self.write_u32be(long_num);
1161 self.write_u32be(long_seg_len as u32);
1162 }
1163 }
1164
1165 fn write_fnames_seg_for(&mut self, long: bool) {
1166 let Some(seg) = (if long {
1168 self.long_fnames_seg.as_ref()
1169 } else {
1170 self.short_fnames_seg.as_ref()
1171 }) else {
1172 return;
1173 };
1174 let names: Vec<(u32, usize, usize)> = seg
1175 .field_names
1176 .iter()
1177 .map(|f| (f.hash_id, f.name_bytes.len(), f.offset))
1178 .collect();
1179 let seg_len = seg.buffer.len();
1180 let seg_buffer = seg.buffer.clone();
1181
1182 for (hash_id, name_len, _) in &names {
1184 if *name_len <= 255 {
1185 self.write_u8((*hash_id & 0xff) as u8);
1186 } else {
1187 self.write_u16be((*hash_id & 0xffff) as u16);
1188 }
1189 }
1190 for (_, _, offset) in &names {
1192 if seg_len < 65536 {
1193 self.write_u16be(*offset as u16);
1194 } else {
1195 self.write_u32be(*offset as u32);
1196 }
1197 }
1198 if seg_len > 0 {
1200 self.buffer.extend_from_slice(&seg_buffer);
1201 }
1202 }
1203
1204 fn encode(&mut self, value: &OsonValue, supports_long_fnames: bool) -> Result<Vec<u8>> {
1205 self.max_fname_size = if supports_long_fnames {
1206 MAX_FNAME_SIZE_LONG
1207 } else {
1208 MAX_FNAME_SIZE_SHORT
1209 };
1210 let mut flags = self.determine_flags(value)?;
1211
1212 let mut tree_seg = TreeSegment::new();
1214 tree_seg.encode_node(value, self)?;
1215 if tree_seg.buffer.len() > 65535 {
1216 flags |= TNS_JSON_FLAG_TREE_SEG_UINT32;
1217 }
1218
1219 self.write_u8(TNS_JSON_MAGIC_BYTE_1);
1221 self.write_u8(TNS_JSON_MAGIC_BYTE_2);
1222 self.write_u8(TNS_JSON_MAGIC_BYTE_3);
1223 if self.long_fnames_seg.is_some() {
1224 self.write_u8(TNS_JSON_VERSION_MAX_FNAME_65535);
1225 } else {
1226 self.write_u8(TNS_JSON_VERSION_MAX_FNAME_255);
1227 }
1228 self.write_u16be(flags);
1229
1230 if self.short_fnames_seg.is_some() {
1232 self.write_extended_header();
1233 }
1234
1235 let tree_len = tree_seg.buffer.len();
1237 if tree_len < 65536 {
1238 self.write_u16be(tree_len as u16);
1239 } else {
1240 self.write_u32be(tree_len as u32);
1241 }
1242
1243 if self.short_fnames_seg.is_some() {
1245 self.write_u16be(0); self.write_fnames_seg_for(false);
1247 if self.long_fnames_seg.is_some() {
1248 self.write_fnames_seg_for(true);
1249 }
1250 }
1251
1252 self.buffer.extend_from_slice(&tree_seg.buffer);
1254 Ok(std::mem::take(&mut self.buffer))
1255 }
1256}
1257
1258pub fn encode_oson(value: &OsonValue, supports_long_fnames: bool) -> Result<Vec<u8>> {
1263 let mut encoder = OsonEncoder::new(if supports_long_fnames {
1264 MAX_FNAME_SIZE_LONG
1265 } else {
1266 MAX_FNAME_SIZE_SHORT
1267 });
1268 encoder.encode(value, supports_long_fnames)
1269}
1270
1271#[cfg(test)]
1272mod tests {
1273 use super::*;
1274 use serde_json::json;
1275 use std::fs;
1276 use std::path::PathBuf;
1277
1278 fn golden_path() -> PathBuf {
1279 PathBuf::from(env!("CARGO_MANIFEST_DIR"))
1280 .join("tests")
1281 .join("golden")
1282 .join("oson_golden.json")
1283 }
1284
1285 fn hex_to_bytes(s: &str) -> Vec<u8> {
1286 (0..s.len())
1287 .step_by(2)
1288 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
1289 .collect()
1290 }
1291
1292 fn obj(pairs: &[(&str, OsonValue)]) -> OsonValue {
1293 OsonValue::Object(
1294 pairs
1295 .iter()
1296 .map(|(k, v)| (k.to_string(), v.clone()))
1297 .collect(),
1298 )
1299 }
1300
1301 fn num(text: &str) -> OsonValue {
1302 OsonValue::Number(text.to_string())
1303 }
1304
1305 fn s(text: &str) -> OsonValue {
1306 OsonValue::String(text.to_string())
1307 }
1308
1309 fn golden_value(name: &str) -> Option<OsonValue> {
1312 Some(match name {
1313 "scalar_int_42" => num("42"),
1314 "scalar_str_hello" => s("hello"),
1315 "scalar_true" => OsonValue::Bool(true),
1316 "scalar_false" => OsonValue::Bool(false),
1317 "scalar_null" => OsonValue::Null,
1318 "scalar_empty_str" => s(""),
1319 "scalar_float_25_25" => num("25.25"),
1320 "scalar_decimal" => num("319438950232418390.273596"),
1321 "scalar_neg_big" => num("-9999999999999999999"),
1322 "scalar_bytes" => OsonValue::Raw(b"Some Bytes".to_vec()),
1323 "empty_obj" => obj(&[]),
1324 "simple_obj" => obj(&[("id", num("6901")), ("value", s("string 6901"))]),
1325 "name_none" => obj(&[("name", OsonValue::Null)]),
1326 "nested" => obj(&[(
1327 "employee",
1328 obj(&[
1329 ("name", s("John")),
1330 ("age", num("30")),
1331 ("city", s("Delhi")),
1332 ("Parmanent", OsonValue::Bool(true)),
1333 ]),
1334 )]),
1335 "list_in_obj" => obj(&[(
1336 "employees",
1337 OsonValue::Array(vec![s("John"), s("Matthew"), s("James")]),
1338 )]),
1339 "list_of_obj" => obj(&[(
1340 "employees",
1341 OsonValue::Array(vec![obj(&[(
1342 "employee1",
1343 obj(&[("name", s("John")), ("city", s("Delhi"))]),
1344 )])]),
1345 )]),
1346 "obj_3516" => obj(&[("key_1", s("test_3516a")), ("key_2", s("test_3516b"))]),
1347 "timestamp7" => OsonValue::DateTime {
1348 year: 2004,
1349 month: 2,
1350 day: 1,
1351 hour: 3,
1352 minute: 4,
1353 second: 5,
1354 nanosecond: 0,
1355 },
1356 "timestamp_fs" => OsonValue::DateTime {
1357 year: 2002,
1358 month: 12,
1359 day: 13,
1360 hour: 9,
1361 minute: 36,
1362 second: 0,
1363 nanosecond: 123_000_000,
1364 },
1365 "date_only" => OsonValue::DateTime {
1366 year: 2002,
1367 month: 12,
1368 day: 13,
1369 hour: 0,
1370 minute: 0,
1371 second: 0,
1372 nanosecond: 0,
1373 },
1374 "interval_ds" => OsonValue::IntervalDS {
1375 days: 8,
1376 hours: 12,
1377 minutes: 0,
1378 seconds: 0,
1379 fseconds: 0,
1380 },
1381 "long_fname_256" => obj(&[(&"A".repeat(256), num("6700"))]),
1382 _ => return None,
1383 })
1384 }
1385
1386 #[test]
1387 fn golden_encode_matches_byte_for_byte() {
1388 let raw = fs::read_to_string(golden_path()).expect("golden file");
1389 let doc: serde_json::Value = serde_json::from_str(&raw).unwrap();
1390 let cases = doc["cases"].as_array().unwrap();
1391 let mut checked = 0;
1392 for case in cases {
1393 let name = case["name"].as_str().unwrap();
1394 let expected = hex_to_bytes(case["hex"].as_str().unwrap());
1395 let Some(value) = golden_value(name) else {
1396 continue;
1397 };
1398 let supports_long = name == "long_fname_256";
1400 let encoded = encode_oson(&value, supports_long)
1401 .unwrap_or_else(|e| panic!("encode {name} failed: {e}"));
1402 assert_eq!(
1403 encoded,
1404 expected,
1405 "OSON encode mismatch for golden case {name}\n got: {}\nwant: {}",
1406 hex(&encoded),
1407 hex(&expected)
1408 );
1409 checked += 1;
1410 }
1411 assert!(
1412 checked >= 20,
1413 "expected to check >=20 golden cases, got {checked}"
1414 );
1415 }
1416
1417 #[test]
1418 fn golden_decode_round_trips() {
1419 let raw = fs::read_to_string(golden_path()).expect("golden file");
1420 let doc: serde_json::Value = serde_json::from_str(&raw).unwrap();
1421 let cases = doc["cases"].as_array().unwrap();
1422 for case in cases {
1423 let name = case["name"].as_str().unwrap();
1424 let bytes = hex_to_bytes(case["hex"].as_str().unwrap());
1425 let Some(expected) = golden_value(name) else {
1426 continue;
1427 };
1428 let decoded =
1429 decode_oson(&bytes).unwrap_or_else(|e| panic!("decode {name} failed: {e}"));
1430 assert_eq!(decoded, expected, "OSON decode mismatch for {name}");
1431 }
1432 }
1433
1434 fn hex(bytes: &[u8]) -> String {
1435 bytes.iter().map(|b| format!("{b:02x}")).collect()
1436 }
1437
1438 #[test]
1439 fn round_trip_via_encode_decode() {
1440 let value = obj(&[
1441 ("id", num("6903")),
1442 ("value", s("string 6903")),
1443 ("flag", OsonValue::Bool(false)),
1444 ("nothing", OsonValue::Null),
1445 (
1446 "nums",
1447 OsonValue::Array(vec![num("1"), num("2.5"), num("-3")]),
1448 ),
1449 ("bf", OsonValue::BinaryFloat(38.75)),
1450 ("bd", OsonValue::BinaryDouble(125.875)),
1451 ]);
1452 let encoded = encode_oson(&value, false).unwrap();
1453 let decoded = decode_oson(&encoded).unwrap();
1454 assert_eq!(decoded, value);
1455 }
1456
1457 #[test]
1458 fn bad_magic_is_dpy_5004() {
1459 let bytes = b"{'not a previous encoded value': 3}";
1460 let err = decode_oson(bytes).unwrap_err();
1461 assert!(
1462 matches!(err, ProtocolError::OsonNotEncoded(_)),
1463 "got {err:?}"
1464 );
1465 }
1466
1467 #[test]
1468 fn corrupt_offset_is_dpy_5006() {
1469 let value = obj(&[("key_1", s("test_3516a")), ("key_2", s("test_3516b"))]);
1472 let mut encoded = encode_oson(&value, false).unwrap();
1473 encoded[15] = 0xFF;
1474 let err = decode_oson(&encoded).unwrap_err();
1475 assert!(matches!(err, ProtocolError::OsonInvalid(_)), "got {err:?}");
1476 }
1477
1478 #[test]
1479 fn binary_float_double_use_oracle_sign_transform() {
1480 for v in [-1.0f64, -123.456, -0.0, f64::MIN] {
1483 let value = OsonValue::BinaryDouble(v);
1484 let decoded = decode_oson(&encode_oson(&value, false).unwrap()).unwrap();
1485 assert_eq!(decoded, OsonValue::BinaryDouble(v));
1486 }
1487 for v in [-1.0f32, -123.5, f32::MIN] {
1488 let value = OsonValue::BinaryFloat(v);
1489 let decoded = decode_oson(&encode_oson(&value, false).unwrap()).unwrap();
1490 assert_eq!(decoded, OsonValue::BinaryFloat(v));
1491 }
1492 }
1493
1494 #[test]
1495 fn long_field_name_round_trips() {
1496 let key = "Z".repeat(300);
1497 let value = obj(&[(&key, num("6700")), ("short", s("v"))]);
1498 let encoded = encode_oson(&value, true).unwrap();
1499 assert_eq!(encoded[3], TNS_JSON_VERSION_MAX_FNAME_65535);
1501 let decoded = decode_oson(&encoded).unwrap();
1502 assert_eq!(decoded, value);
1503 }
1504
1505 #[test]
1506 fn json_value_helper_silences_unused_import() {
1507 let _ = json!({"a": 1});
1509 }
1510
1511 #[test]
1517 fn fuzz_regression_oom_oversized_counts() {
1518 let input = [
1519 255, 74, 90, 1, 255, 74, 90, 1, 33, 2, 2, 0, 0, 0, 9, 0, 0, 0, 0, 0,
1520 ];
1521 let err = decode_oson(&input).expect_err("malformed OSON must fail closed");
1522 assert!(
1523 matches!(
1524 err,
1525 ProtocolError::OsonInvalid(_) | ProtocolError::OsonNotEncoded(_)
1526 ),
1527 "got {err:?}"
1528 );
1529 }
1530
1531 #[test]
1534 fn fuzz_regression_deep_nesting_is_bounded() {
1535 let mut v = OsonValue::Number("1".into());
1543 for _ in 0..50 {
1544 v = OsonValue::Array(vec![v]);
1545 }
1546 let encoded = encode_oson(&v, false).expect("encode deep array");
1548 let decoded = decode_oson(&encoded).expect("decode deep array");
1549 assert_eq!(decoded, v);
1550 }
1551}