1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49#[repr(u8)]
50pub enum TypeCode {
51 Custom = 0x00,
53 Int32 = 0x01,
55 Int64 = 0x02,
57 Float = 0x03,
59 Double = 0x04,
61 String = 0x05,
63 List = 0x06,
65 Map = 0x07,
67 Set = 0x08,
69 Uuid = 0x09,
71 Edge = 0x0A,
73 Vertex = 0x0B,
75 Path = 0x0C,
77 Property = 0x0D,
79 Traverser = 0x0E,
81 Bytecode = 0x0F,
83 Binding = 0x10,
85 Step = 0x11,
87 Boolean = 0x12,
89 Null = 0x13,
91 Bytes = 0x14,
93}
94
95impl TypeCode {
96 pub fn from_byte(b: u8) -> Option<Self> {
98 match b {
99 0x00 => Some(TypeCode::Custom),
100 0x01 => Some(TypeCode::Int32),
101 0x02 => Some(TypeCode::Int64),
102 0x03 => Some(TypeCode::Float),
103 0x04 => Some(TypeCode::Double),
104 0x05 => Some(TypeCode::String),
105 0x06 => Some(TypeCode::List),
106 0x07 => Some(TypeCode::Map),
107 0x08 => Some(TypeCode::Set),
108 0x09 => Some(TypeCode::Uuid),
109 0x0A => Some(TypeCode::Edge),
110 0x0B => Some(TypeCode::Vertex),
111 0x0C => Some(TypeCode::Path),
112 0x0D => Some(TypeCode::Property),
113 0x0E => Some(TypeCode::Traverser),
114 0x0F => Some(TypeCode::Bytecode),
115 0x10 => Some(TypeCode::Binding),
116 0x11 => Some(TypeCode::Step),
117 0x12 => Some(TypeCode::Boolean),
118 0x13 => Some(TypeCode::Null),
119 0x14 => Some(TypeCode::Bytes),
120 _ => None,
121 }
122 }
123
124 pub fn name(&self) -> &'static str {
126 match self {
127 TypeCode::Custom => "Custom",
128 TypeCode::Int32 => "Int32",
129 TypeCode::Int64 => "Int64",
130 TypeCode::Float => "Float",
131 TypeCode::Double => "Double",
132 TypeCode::String => "String",
133 TypeCode::List => "List",
134 TypeCode::Map => "Map",
135 TypeCode::Set => "Set",
136 TypeCode::Uuid => "UUID",
137 TypeCode::Edge => "Edge",
138 TypeCode::Vertex => "Vertex",
139 TypeCode::Path => "Path",
140 TypeCode::Property => "Property",
141 TypeCode::Traverser => "Traverser",
142 TypeCode::Bytecode => "Bytecode",
143 TypeCode::Binding => "Binding",
144 TypeCode::Step => "Step",
145 TypeCode::Boolean => "Boolean",
146 TypeCode::Null => "Null",
147 TypeCode::Bytes => "Bytes",
148 }
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154#[repr(u8)]
155pub enum ValueFlag {
156 Present = 0x00,
158 Null = 0x01,
160 Bulk = 0x02,
162}
163
164impl ValueFlag {
165 pub fn from_byte(b: u8) -> Self {
167 match b {
168 0x01 => ValueFlag::Null,
169 0x02 => ValueFlag::Bulk,
170 _ => ValueFlag::Present,
171 }
172 }
173}
174
175#[derive(Debug, Clone)]
177pub struct TypeInfo {
178 pub name: String,
180 pub version: u16,
182}
183
184impl TypeInfo {
185 pub fn new(name: impl Into<String>, version: u16) -> Self {
187 Self {
188 name: name.into(),
189 version,
190 }
191 }
192
193 pub fn to_bytes(&self) -> Vec<u8> {
195 let mut buf = Vec::new();
196 let name_bytes = self.name.as_bytes();
198 buf.extend(&(name_bytes.len() as u16).to_le_bytes());
199 buf.extend(name_bytes);
200 buf.extend(&self.version.to_le_bytes());
202 buf
203 }
204
205 pub fn from_bytes(data: &[u8]) -> Option<(Self, usize)> {
207 if data.len() < 4 {
208 return None;
209 }
210
211 let name_len = u16::from_le_bytes([data[0], data[1]]) as usize;
212 if data.len() < 4 + name_len {
213 return None;
214 }
215
216 let name = String::from_utf8(data[2..2 + name_len].to_vec()).ok()?;
217 let version = u16::from_le_bytes([data[2 + name_len], data[3 + name_len]]);
218
219 Some((Self { name, version }, 4 + name_len))
220 }
221}
222
223#[derive(Debug, Clone)]
225pub enum BinaryValue {
226 Null,
228 Boolean(bool),
230 Int32(i32),
232 Int64(i64),
234 Float(f32),
236 Double(f64),
238 String(String),
240 Bytes(Vec<u8>),
242 List(Vec<BinaryValue>),
244 Map(Vec<(BinaryValue, BinaryValue)>),
246 Uuid([u8; 16]),
248 Vertex { id: Box<BinaryValue>, label: String },
250 Edge {
252 id: Box<BinaryValue>,
253 label: String,
254 in_v: Box<BinaryValue>,
255 out_v: Box<BinaryValue>,
256 },
257 Property {
259 key: String,
260 value: Box<BinaryValue>,
261 },
262 Traverser { value: Box<BinaryValue>, bulk: u64 },
264 Bytecode(Bytecode),
266 Binding {
268 name: String,
269 value: Box<BinaryValue>,
270 },
271 Custom { type_info: TypeInfo, data: Vec<u8> },
273}
274
275impl BinaryValue {
276 pub fn type_code(&self) -> TypeCode {
278 match self {
279 BinaryValue::Null => TypeCode::Null,
280 BinaryValue::Boolean(_) => TypeCode::Boolean,
281 BinaryValue::Int32(_) => TypeCode::Int32,
282 BinaryValue::Int64(_) => TypeCode::Int64,
283 BinaryValue::Float(_) => TypeCode::Float,
284 BinaryValue::Double(_) => TypeCode::Double,
285 BinaryValue::String(_) => TypeCode::String,
286 BinaryValue::Bytes(_) => TypeCode::Bytes,
287 BinaryValue::List(_) => TypeCode::List,
288 BinaryValue::Map(_) => TypeCode::Map,
289 BinaryValue::Uuid(_) => TypeCode::Uuid,
290 BinaryValue::Vertex { .. } => TypeCode::Vertex,
291 BinaryValue::Edge { .. } => TypeCode::Edge,
292 BinaryValue::Property { .. } => TypeCode::Property,
293 BinaryValue::Traverser { .. } => TypeCode::Traverser,
294 BinaryValue::Bytecode(_) => TypeCode::Bytecode,
295 BinaryValue::Binding { .. } => TypeCode::Binding,
296 BinaryValue::Custom { .. } => TypeCode::Custom,
297 }
298 }
299
300 pub fn is_null(&self) -> bool {
302 matches!(self, BinaryValue::Null)
303 }
304}
305
306#[derive(Debug, Clone)]
308pub struct Bytecode {
309 pub sources: Vec<Instruction>,
311 pub steps: Vec<Instruction>,
313}
314
315impl Bytecode {
316 pub fn new() -> Self {
318 Self {
319 sources: Vec::new(),
320 steps: Vec::new(),
321 }
322 }
323
324 pub fn add_source(&mut self, name: &str, args: Vec<BinaryValue>) {
326 self.sources.push(Instruction::new(name, args));
327 }
328
329 pub fn add_step(&mut self, name: &str, args: Vec<BinaryValue>) {
331 self.steps.push(Instruction::new(name, args));
332 }
333}
334
335impl Default for Bytecode {
336 fn default() -> Self {
337 Self::new()
338 }
339}
340
341#[derive(Debug, Clone)]
343pub struct Instruction {
344 pub name: String,
346 pub args: Vec<BinaryValue>,
348}
349
350impl Instruction {
351 pub fn new(name: impl Into<String>, args: Vec<BinaryValue>) -> Self {
353 Self {
354 name: name.into(),
355 args,
356 }
357 }
358}
359
360pub struct BinarySerializer;
362
363impl BinarySerializer {
364 pub fn serialize(value: &BinaryValue) -> Vec<u8> {
366 let mut buf = Vec::new();
367 Self::write_value(&mut buf, value);
368 buf
369 }
370
371 fn write_value(buf: &mut Vec<u8>, value: &BinaryValue) {
373 buf.push(value.type_code() as u8);
375
376 match value {
377 BinaryValue::Null => {
378 buf.push(ValueFlag::Null as u8);
379 }
380 BinaryValue::Boolean(b) => {
381 buf.push(ValueFlag::Present as u8);
382 buf.push(if *b { 1 } else { 0 });
383 }
384 BinaryValue::Int32(i) => {
385 buf.push(ValueFlag::Present as u8);
386 buf.extend(&i.to_le_bytes());
387 }
388 BinaryValue::Int64(i) => {
389 buf.push(ValueFlag::Present as u8);
390 buf.extend(&i.to_le_bytes());
391 }
392 BinaryValue::Float(f) => {
393 buf.push(ValueFlag::Present as u8);
394 buf.extend(&f.to_le_bytes());
395 }
396 BinaryValue::Double(d) => {
397 buf.push(ValueFlag::Present as u8);
398 buf.extend(&d.to_le_bytes());
399 }
400 BinaryValue::String(s) => {
401 buf.push(ValueFlag::Present as u8);
402 Self::write_string(buf, s);
403 }
404 BinaryValue::Bytes(b) => {
405 buf.push(ValueFlag::Present as u8);
406 buf.extend(&(b.len() as u32).to_le_bytes());
407 buf.extend(b);
408 }
409 BinaryValue::List(items) => {
410 buf.push(ValueFlag::Present as u8);
411 buf.extend(&(items.len() as u32).to_le_bytes());
412 for item in items {
413 Self::write_value(buf, item);
414 }
415 }
416 BinaryValue::Map(pairs) => {
417 buf.push(ValueFlag::Present as u8);
418 buf.extend(&(pairs.len() as u32).to_le_bytes());
419 for (k, v) in pairs {
420 Self::write_value(buf, k);
421 Self::write_value(buf, v);
422 }
423 }
424 BinaryValue::Uuid(bytes) => {
425 buf.push(ValueFlag::Present as u8);
426 buf.extend(bytes);
427 }
428 BinaryValue::Vertex { id, label } => {
429 buf.push(ValueFlag::Present as u8);
430 Self::write_value(buf, id);
431 Self::write_string(buf, label);
432 }
433 BinaryValue::Edge {
434 id,
435 label,
436 in_v,
437 out_v,
438 } => {
439 buf.push(ValueFlag::Present as u8);
440 Self::write_value(buf, id);
441 Self::write_string(buf, label);
442 Self::write_value(buf, in_v);
443 Self::write_value(buf, out_v);
444 }
445 BinaryValue::Property { key, value } => {
446 buf.push(ValueFlag::Present as u8);
447 Self::write_string(buf, key);
448 Self::write_value(buf, value);
449 }
450 BinaryValue::Traverser { value, bulk } => {
451 buf.push(ValueFlag::Bulk as u8);
452 buf.extend(&bulk.to_le_bytes());
453 Self::write_value(buf, value);
454 }
455 BinaryValue::Bytecode(bc) => {
456 buf.push(ValueFlag::Present as u8);
457 Self::write_bytecode(buf, bc);
458 }
459 BinaryValue::Binding { name, value } => {
460 buf.push(ValueFlag::Present as u8);
461 Self::write_string(buf, name);
462 Self::write_value(buf, value);
463 }
464 BinaryValue::Custom { type_info, data } => {
465 buf.push(ValueFlag::Present as u8);
466 buf.extend(type_info.to_bytes());
467 buf.extend(&(data.len() as u32).to_le_bytes());
468 buf.extend(data);
469 }
470 }
471 }
472
473 fn write_string(buf: &mut Vec<u8>, s: &str) {
475 let bytes = s.as_bytes();
476 buf.extend(&(bytes.len() as u32).to_le_bytes());
477 buf.extend(bytes);
478 }
479
480 fn write_bytecode(buf: &mut Vec<u8>, bc: &Bytecode) {
482 buf.extend(&(bc.sources.len() as u32).to_le_bytes());
484 for inst in &bc.sources {
485 Self::write_instruction(buf, inst);
486 }
487
488 buf.extend(&(bc.steps.len() as u32).to_le_bytes());
490 for inst in &bc.steps {
491 Self::write_instruction(buf, inst);
492 }
493 }
494
495 fn write_instruction(buf: &mut Vec<u8>, inst: &Instruction) {
497 Self::write_string(buf, &inst.name);
498 buf.extend(&(inst.args.len() as u32).to_le_bytes());
499 for arg in &inst.args {
500 Self::write_value(buf, arg);
501 }
502 }
503}
504
505pub struct BinaryDeserializer;
507
508impl BinaryDeserializer {
509 pub fn deserialize(data: &[u8]) -> Option<(BinaryValue, usize)> {
511 Self::read_value(data)
512 }
513
514 fn read_value(data: &[u8]) -> Option<(BinaryValue, usize)> {
516 if data.len() < 2 {
517 return None;
518 }
519
520 let type_code = TypeCode::from_byte(data[0])?;
521 let flag = ValueFlag::from_byte(data[1]);
522
523 if flag == ValueFlag::Null {
525 return Some((BinaryValue::Null, 2));
526 }
527
528 let mut offset = 2;
529
530 let value = match type_code {
531 TypeCode::Null => BinaryValue::Null,
532 TypeCode::Boolean => {
533 if data.len() < offset + 1 {
534 return None;
535 }
536 let b = data[offset] != 0;
537 offset += 1;
538 BinaryValue::Boolean(b)
539 }
540 TypeCode::Int32 => {
541 if data.len() < offset + 4 {
542 return None;
543 }
544 let i = i32::from_le_bytes(data[offset..offset + 4].try_into().ok()?);
545 offset += 4;
546 BinaryValue::Int32(i)
547 }
548 TypeCode::Int64 => {
549 if data.len() < offset + 8 {
550 return None;
551 }
552 let i = i64::from_le_bytes(data[offset..offset + 8].try_into().ok()?);
553 offset += 8;
554 BinaryValue::Int64(i)
555 }
556 TypeCode::Float => {
557 if data.len() < offset + 4 {
558 return None;
559 }
560 let f = f32::from_le_bytes(data[offset..offset + 4].try_into().ok()?);
561 offset += 4;
562 BinaryValue::Float(f)
563 }
564 TypeCode::Double => {
565 if data.len() < offset + 8 {
566 return None;
567 }
568 let d = f64::from_le_bytes(data[offset..offset + 8].try_into().ok()?);
569 offset += 8;
570 BinaryValue::Double(d)
571 }
572 TypeCode::String => {
573 let (s, len) = Self::read_string(&data[offset..])?;
574 offset += len;
575 BinaryValue::String(s)
576 }
577 TypeCode::Bytes => {
578 if data.len() < offset + 4 {
579 return None;
580 }
581 let len = u32::from_le_bytes(data[offset..offset + 4].try_into().ok()?) as usize;
582 offset += 4;
583 if data.len() < offset + len {
584 return None;
585 }
586 let bytes = data[offset..offset + len].to_vec();
587 offset += len;
588 BinaryValue::Bytes(bytes)
589 }
590 TypeCode::List => {
591 if data.len() < offset + 4 {
592 return None;
593 }
594 let count = u32::from_le_bytes(data[offset..offset + 4].try_into().ok()?) as usize;
595 offset += 4;
596
597 let mut items = Vec::with_capacity(count);
598 for _ in 0..count {
599 let (item, len) = Self::read_value(&data[offset..])?;
600 offset += len;
601 items.push(item);
602 }
603 BinaryValue::List(items)
604 }
605 TypeCode::Map => {
606 if data.len() < offset + 4 {
607 return None;
608 }
609 let count = u32::from_le_bytes(data[offset..offset + 4].try_into().ok()?) as usize;
610 offset += 4;
611
612 let mut pairs = Vec::with_capacity(count);
613 for _ in 0..count {
614 let (key, len1) = Self::read_value(&data[offset..])?;
615 offset += len1;
616 let (val, len2) = Self::read_value(&data[offset..])?;
617 offset += len2;
618 pairs.push((key, val));
619 }
620 BinaryValue::Map(pairs)
621 }
622 TypeCode::Uuid => {
623 if data.len() < offset + 16 {
624 return None;
625 }
626 let mut bytes = [0u8; 16];
627 bytes.copy_from_slice(&data[offset..offset + 16]);
628 offset += 16;
629 BinaryValue::Uuid(bytes)
630 }
631 TypeCode::Traverser => {
632 if data.len() < offset + 8 {
634 return None;
635 }
636 let bulk = u64::from_le_bytes(data[offset..offset + 8].try_into().ok()?);
637 offset += 8;
638 let (value, len) = Self::read_value(&data[offset..])?;
640 offset += len;
641 BinaryValue::Traverser {
642 value: Box::new(value),
643 bulk,
644 }
645 }
646 TypeCode::Bytecode => {
647 let (bc, len) = Self::read_bytecode(&data[offset..])?;
648 offset += len;
649 BinaryValue::Bytecode(bc)
650 }
651 _ => return None, };
653
654 Some((value, offset))
655 }
656
657 fn read_string(data: &[u8]) -> Option<(String, usize)> {
659 if data.len() < 4 {
660 return None;
661 }
662 let len = u32::from_le_bytes(data[0..4].try_into().ok()?) as usize;
663 if data.len() < 4 + len {
664 return None;
665 }
666 let s = String::from_utf8(data[4..4 + len].to_vec()).ok()?;
667 Some((s, 4 + len))
668 }
669
670 fn read_bytecode(data: &[u8]) -> Option<(Bytecode, usize)> {
672 let mut offset = 0;
673
674 if data.len() < 4 {
676 return None;
677 }
678 let source_count = u32::from_le_bytes(data[0..4].try_into().ok()?) as usize;
679 offset += 4;
680
681 let mut sources = Vec::with_capacity(source_count);
682 for _ in 0..source_count {
683 let (inst, len) = Self::read_instruction(&data[offset..])?;
684 offset += len;
685 sources.push(inst);
686 }
687
688 if data.len() < offset + 4 {
690 return None;
691 }
692 let step_count = u32::from_le_bytes(data[offset..offset + 4].try_into().ok()?) as usize;
693 offset += 4;
694
695 let mut steps = Vec::with_capacity(step_count);
696 for _ in 0..step_count {
697 let (inst, len) = Self::read_instruction(&data[offset..])?;
698 offset += len;
699 steps.push(inst);
700 }
701
702 Some((Bytecode { sources, steps }, offset))
703 }
704
705 fn read_instruction(data: &[u8]) -> Option<(Instruction, usize)> {
707 let mut offset = 0;
708
709 let (name, len) = Self::read_string(data)?;
710 offset += len;
711
712 if data.len() < offset + 4 {
713 return None;
714 }
715 let arg_count = u32::from_le_bytes(data[offset..offset + 4].try_into().ok()?) as usize;
716 offset += 4;
717
718 let mut args = Vec::with_capacity(arg_count);
719 for _ in 0..arg_count {
720 let (arg, len) = Self::read_value(&data[offset..])?;
721 offset += len;
722 args.push(arg);
723 }
724
725 Some((Instruction::new(name, args), offset))
726 }
727}
728
729#[cfg(test)]
730mod tests {
731 use super::*;
732
733 #[test]
734 fn test_type_code_roundtrip() {
735 for code in [
736 TypeCode::Int32,
737 TypeCode::Int64,
738 TypeCode::String,
739 TypeCode::List,
740 TypeCode::Null,
741 ] {
742 assert_eq!(TypeCode::from_byte(code as u8), Some(code));
743 }
744 }
745
746 #[test]
747 fn test_serialize_int32() {
748 let value = BinaryValue::Int32(42);
749 let bytes = BinarySerializer::serialize(&value);
750
751 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
752 match decoded {
753 BinaryValue::Int32(i) => assert_eq!(i, 42),
754 _ => panic!("Expected Int32"),
755 }
756 }
757
758 #[test]
759 fn test_serialize_string() {
760 let value = BinaryValue::String("hello".to_string());
761 let bytes = BinarySerializer::serialize(&value);
762
763 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
764 match decoded {
765 BinaryValue::String(s) => assert_eq!(s, "hello"),
766 _ => panic!("Expected String"),
767 }
768 }
769
770 #[test]
771 fn test_serialize_list() {
772 let value = BinaryValue::List(vec![
773 BinaryValue::Int32(1),
774 BinaryValue::Int32(2),
775 BinaryValue::Int32(3),
776 ]);
777 let bytes = BinarySerializer::serialize(&value);
778
779 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
780 match decoded {
781 BinaryValue::List(items) => {
782 assert_eq!(items.len(), 3);
783 }
784 _ => panic!("Expected List"),
785 }
786 }
787
788 #[test]
789 fn test_serialize_null() {
790 let value = BinaryValue::Null;
791 let bytes = BinarySerializer::serialize(&value);
792
793 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
794 assert!(decoded.is_null());
795 }
796
797 #[test]
798 fn test_serialize_traverser() {
799 let value = BinaryValue::Traverser {
800 value: Box::new(BinaryValue::String("vertex1".to_string())),
801 bulk: 5,
802 };
803 let bytes = BinarySerializer::serialize(&value);
804
805 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
806 match decoded {
807 BinaryValue::Traverser { bulk, .. } => assert_eq!(bulk, 5),
808 _ => panic!("Expected Traverser"),
809 }
810 }
811
812 #[test]
813 fn test_bytecode_serialization() {
814 let mut bc = Bytecode::new();
815 bc.add_source("V", vec![]);
816 bc.add_step("out", vec![BinaryValue::String("knows".to_string())]);
817 bc.add_step(
818 "has",
819 vec![
820 BinaryValue::String("name".to_string()),
821 BinaryValue::String("alice".to_string()),
822 ],
823 );
824
825 let value = BinaryValue::Bytecode(bc);
826 let bytes = BinarySerializer::serialize(&value);
827
828 let (decoded, _) = BinaryDeserializer::deserialize(&bytes).unwrap();
829 match decoded {
830 BinaryValue::Bytecode(bc) => {
831 assert_eq!(bc.sources.len(), 1);
832 assert_eq!(bc.steps.len(), 2);
833 assert_eq!(bc.sources[0].name, "V");
834 assert_eq!(bc.steps[0].name, "out");
835 assert_eq!(bc.steps[1].name, "has");
836 }
837 _ => panic!("Expected Bytecode"),
838 }
839 }
840
841 #[test]
842 fn test_type_info() {
843 let info = TypeInfo::new("MyCustomType", 1);
844 let bytes = info.to_bytes();
845
846 let (decoded, _) = TypeInfo::from_bytes(&bytes).unwrap();
847 assert_eq!(decoded.name, "MyCustomType");
848 assert_eq!(decoded.version, 1);
849 }
850}