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