1use crate::{OneIndexed, SourceLocation, bytecode::*};
2use alloc::{boxed::Box, vec::Vec};
3use core::convert::Infallible;
4use malachite_bigint::{BigInt, Sign};
5use num_complex::Complex64;
6use rustpython_wtf8::Wtf8;
7
8pub const FORMAT_VERSION: u32 = 5;
9
10#[derive(Clone, Copy, Debug)]
11pub enum MarshalError {
12 Eof,
14 EofObject,
16 DataTooShort,
18 InvalidBytecode,
20 InvalidUtf8,
22 InvalidLocation,
24 BadType,
26 UnknownType,
28 InvalidRef,
30 NullObject,
32 BadSize(&'static str),
34}
35
36impl core::fmt::Display for MarshalError {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 match self {
39 Self::Eof => f.write_str("unexpected end of data"),
40 Self::EofObject => f.write_str("unexpected end of data where an object was expected"),
41 Self::DataTooShort => f.write_str("data ends in the middle of a value"),
42 Self::InvalidBytecode => f.write_str("invalid bytecode"),
43 Self::InvalidUtf8 => f.write_str("invalid utf8"),
44 Self::InvalidLocation => f.write_str("invalid source location"),
45 Self::BadType => f.write_str("bad type marker"),
46 Self::UnknownType => f.write_str("unknown type code"),
47 Self::InvalidRef => f.write_str("invalid reference"),
48 Self::NullObject => f.write_str("NULL object in marshal data for object"),
49 Self::BadSize(what) => write!(f, "{what} size out of range"),
50 }
51 }
52}
53
54impl From<core::str::Utf8Error> for MarshalError {
55 fn from(_: core::str::Utf8Error) -> Self {
56 Self::InvalidUtf8
57 }
58}
59
60impl core::error::Error for MarshalError {}
61
62type Result<T, E = MarshalError> = core::result::Result<T, E>;
63
64#[derive(Clone, Copy)]
65#[repr(u8)]
66enum Type {
67 Null = b'0',
68 None = b'N',
69 False = b'F',
70 True = b'T',
71 StopIter = b'S',
72 Ellipsis = b'.',
73 Int = b'i',
74 Int64 = b'I',
75 Long = b'l',
76 Float = b'g',
77 FloatStr = b'f',
78 ComplexStr = b'x',
79 Complex = b'y',
80 Bytes = b's',
81 Interned = b't',
82 Ref = b'r',
83 Tuple = b'(',
84 SmallTuple = b')',
85 List = b'[',
86 Dict = b'{',
87 Code = b'c',
88 Unicode = b'u',
89 Set = b'<',
90 FrozenSet = b'>',
91 Slice = b':',
92 Ascii = b'a',
93 AsciiInterned = b'A',
94 ShortAscii = b'z',
95 ShortAsciiInterned = b'Z',
96}
97
98impl TryFrom<u8> for Type {
99 type Error = MarshalError;
100
101 fn try_from(value: u8) -> Result<Self> {
102 Ok(match value {
103 b'0' => Self::Null,
104 b'N' => Self::None,
105 b'F' => Self::False,
106 b'T' => Self::True,
107 b'S' => Self::StopIter,
108 b'.' => Self::Ellipsis,
109 b'i' => Self::Int,
110 b'I' => Self::Int64,
111 b'l' => Self::Long,
112 b'f' => Self::FloatStr,
113 b'g' => Self::Float,
114 b'x' => Self::ComplexStr,
115 b'y' => Self::Complex,
116 b's' => Self::Bytes,
117 b't' => Self::Interned,
118 b'r' => Self::Ref,
119 b'(' => Self::Tuple,
120 b')' => Self::SmallTuple,
121 b'[' => Self::List,
122 b'{' => Self::Dict,
123 b'c' => Self::Code,
124 b'u' => Self::Unicode,
125 b'<' => Self::Set,
126 b'>' => Self::FrozenSet,
127 b':' => Self::Slice,
128 b'a' => Self::Ascii,
129 b'A' => Self::AsciiInterned,
130 b'z' => Self::ShortAscii,
131 b'Z' => Self::ShortAsciiInterned,
132 _ => return Err(MarshalError::UnknownType),
133 })
134 }
135}
136
137pub trait Read {
138 fn read_slice(&mut self, n: u32) -> Result<&[u8]>;
139
140 fn read_array<const N: usize>(&mut self) -> Result<&[u8; N]> {
141 self.read_slice(N as u32).map(|s| s.try_into().unwrap())
142 }
143
144 fn read_str(&mut self, len: u32) -> Result<&str> {
145 Ok(core::str::from_utf8(self.read_slice(len)?)?)
146 }
147
148 fn read_wtf8(&mut self, len: u32) -> Result<&Wtf8> {
149 Wtf8::from_bytes(self.read_slice(len)?).ok_or(MarshalError::InvalidUtf8)
150 }
151
152 fn read_u8(&mut self) -> Result<u8> {
153 let byte = self.read_array().map_err(|_| MarshalError::Eof)?;
155 Ok(u8::from_le_bytes(*byte))
156 }
157
158 fn read_u16(&mut self) -> Result<u16> {
159 Ok(u16::from_le_bytes(*self.read_array()?))
160 }
161
162 fn read_u32(&mut self) -> Result<u32> {
163 Ok(u32::from_le_bytes(*self.read_array()?))
164 }
165
166 fn read_u64(&mut self) -> Result<u64> {
167 Ok(u64::from_le_bytes(*self.read_array()?))
168 }
169
170 fn read_len(&mut self, what: &'static str) -> Result<usize> {
173 let len = self.read_u32()? as i32;
174 usize::try_from(len).map_err(|_| MarshalError::BadSize(what))
175 }
176}
177
178pub(crate) trait ReadBorrowed<'a>: Read {
179 fn read_slice_borrow(&mut self, n: u32) -> Result<&'a [u8]>;
180
181 fn read_str_borrow(&mut self, len: u32) -> Result<&'a str> {
182 Ok(core::str::from_utf8(self.read_slice_borrow(len)?)?)
183 }
184}
185
186impl Read for &[u8] {
187 fn read_slice(&mut self, n: u32) -> Result<&[u8]> {
188 self.read_slice_borrow(n)
189 }
190
191 fn read_array<const N: usize>(&mut self) -> Result<&[u8; N]> {
192 let (chunk, rest) = self
193 .split_first_chunk::<N>()
194 .ok_or(MarshalError::DataTooShort)?;
195 *self = rest;
196 Ok(chunk)
197 }
198}
199
200impl<'a> ReadBorrowed<'a> for &'a [u8] {
201 fn read_slice_borrow(&mut self, n: u32) -> Result<&'a [u8]> {
202 self.split_off(..n as usize)
203 .ok_or(MarshalError::DataTooShort)
204 }
205}
206
207pub struct Cursor<B> {
208 pub data: B,
209 pub position: usize,
210}
211
212impl<B: AsRef<[u8]>> Read for Cursor<B> {
213 fn read_slice(&mut self, n: u32) -> Result<&[u8]> {
214 let data = &self.data.as_ref()[self.position..];
215 let slice = data.get(..n as usize).ok_or(MarshalError::DataTooShort)?;
216 self.position += n as usize;
217 Ok(slice)
218 }
219}
220
221pub fn deserialize_code<R: Read, Bag: ConstantBag>(
223 rdr: &mut R,
224 bag: Bag,
225) -> Result<CodeObject<Bag::Constant>> {
226 let mut refs: Vec<Option<Bag::Constant>> = Vec::new();
227 deserialize_code_inner(rdr, bag, MAX_MARSHAL_STACK_DEPTH, &mut refs)
228}
229
230fn deserialize_code_inner<R: Read, Bag: ConstantBag>(
234 rdr: &mut R,
235 bag: Bag,
236 depth: usize,
237 refs: &mut Vec<Option<Bag::Constant>>,
238) -> Result<CodeObject<Bag::Constant>> {
239 if depth == 0 {
240 return Err(MarshalError::InvalidBytecode);
241 }
242 let arg_count = rdr.read_u32()?;
244 let posonlyarg_count = rdr.read_u32()?;
245 let kwonlyarg_count = rdr.read_u32()?;
246 let max_stackdepth = rdr.read_u32()?;
247 let flags = CodeFlags::from_bits_truncate(rdr.read_u32()?);
248
249 let code_bytes = read_marshal_bytes(rdr, &bag, refs)?;
251
252 let constants = read_marshal_const_tuple(rdr, bag, depth, refs)?;
254
255 let names = read_marshal_name_tuple(rdr, &bag, refs)?;
257
258 let localsplusnames = read_marshal_str_vec(rdr, &bag, refs)?;
260
261 let localspluskinds = read_marshal_bytes(rdr, &bag, refs)?;
263
264 let source_path = bag.make_name(&read_marshal_str(rdr, &bag, refs)?);
266 let obj_name = bag.make_name(&read_marshal_str(rdr, &bag, refs)?);
267 let qualname = bag.make_name(&read_marshal_str(rdr, &bag, refs)?);
268
269 let first_line_raw = rdr.read_u32()? as i32;
271 let first_line_number = if first_line_raw > 0 {
272 OneIndexed::new(first_line_raw as usize)
273 } else {
274 None
275 };
276
277 let linetable = read_marshal_bytes(rdr, &bag, refs)?.into_boxed_slice();
279 let exceptiontable = read_marshal_bytes(rdr, &bag, refs)?.into_boxed_slice();
280
281 let lp = split_localplus(
283 &localsplusnames
284 .iter()
285 .map(|s| s.as_str())
286 .collect::<Vec<&str>>(),
287 &localspluskinds,
288 arg_count,
289 kwonlyarg_count,
290 flags,
291 )?;
292
293 let instructions = CodeUnits::try_from(code_bytes.as_slice())?;
295 let locations = linetable_to_locations(&linetable, first_line_raw, instructions.len());
296
297 let localspluskinds = localspluskinds.into_boxed_slice();
299
300 Ok(CodeObject {
301 instructions,
302 locations,
303 flags,
304 posonlyarg_count,
305 arg_count,
306 kwonlyarg_count,
307 source_path,
308 first_line_number,
309 max_stackdepth,
310 obj_name,
311 qualname,
312 constants,
313 names,
314 varnames: lp.varnames.iter().map(|s| bag.make_name(s)).collect(),
315 cellvars: lp.cellvars.iter().map(|s| bag.make_name(s)).collect(),
316 freevars: lp.freevars.iter().map(|s| bag.make_name(s)).collect(),
317 localspluskinds,
318 linetable,
319 exceptiontable,
320 })
321}
322
323fn reserve_ref_slot<T>(has_flag: bool, refs: &mut Vec<Option<T>>) -> Option<usize> {
325 if has_flag {
326 let idx = refs.len();
327 refs.push(None);
328 Some(idx)
329 } else {
330 None
331 }
332}
333
334fn resolve_ref<T: Clone>(idx: usize, refs: &[Option<T>]) -> Result<T> {
336 refs.get(idx)
337 .and_then(|v| v.clone())
338 .ok_or(MarshalError::InvalidRef)
339}
340
341fn read_marshal_bytes<R: Read, Bag: ConstantBag>(
344 rdr: &mut R,
345 bag: &Bag,
346 refs: &mut Vec<Option<Bag::Constant>>,
347) -> Result<Vec<u8>> {
348 let raw = rdr.read_u8()?;
349 let type_byte = raw & !FLAG_REF;
350 let has_flag = raw & FLAG_REF != 0;
351
352 if type_byte == Type::Ref as u8 {
353 let idx = rdr.read_u32()? as usize;
354 let stored = resolve_ref(idx, refs)?;
355 return match stored.borrow_constant() {
356 BorrowedConstant::Bytes { value } => Ok(value.to_vec()),
357 _ => Err(MarshalError::BadType),
358 };
359 }
360
361 if type_byte != Type::Bytes as u8 {
362 return Err(MarshalError::BadType);
363 }
364
365 let slot = reserve_ref_slot(has_flag, refs);
366 let len = rdr.read_u32()?;
367 let bytes = rdr.read_slice(len)?.to_vec();
368 if let Some(idx) = slot {
369 refs[idx] =
370 Some(bag.make_constant::<Bag::Constant>(BorrowedConstant::Bytes { value: &bytes }));
371 }
372 Ok(bytes)
373}
374
375fn read_marshal_str<R: Read, Bag: ConstantBag>(
378 rdr: &mut R,
379 bag: &Bag,
380 refs: &mut Vec<Option<Bag::Constant>>,
381) -> Result<alloc::string::String> {
382 let raw = rdr.read_u8()?;
383 let type_byte = raw & !FLAG_REF;
384 let has_flag = raw & FLAG_REF != 0;
385
386 if type_byte == Type::Ref as u8 {
387 let idx = rdr.read_u32()? as usize;
388 let stored = resolve_ref(idx, refs)?;
389 return match stored.borrow_constant() {
390 BorrowedConstant::Str { value } => Ok(value.to_string_lossy().into_owned()),
391 _ => Err(MarshalError::BadType),
392 };
393 }
394
395 let slot = reserve_ref_slot(has_flag, refs);
396 let owned = match type_byte {
397 b'u' | b't' | b'a' | b'A' => {
398 let len = rdr.read_u32()?;
399 alloc::string::String::from(rdr.read_str(len)?)
400 }
401 b'z' | b'Z' => {
402 let len = rdr.read_u8()? as u32;
403 alloc::string::String::from(rdr.read_str(len)?)
404 }
405 _ => return Err(MarshalError::BadType),
406 };
407 if let Some(idx) = slot {
408 refs[idx] = Some(bag.make_constant::<Bag::Constant>(BorrowedConstant::Str {
409 value: Wtf8::new(owned.as_str()),
410 }));
411 }
412 Ok(owned)
413}
414
415fn read_marshal_str_vec<R: Read, Bag: ConstantBag>(
417 rdr: &mut R,
418 bag: &Bag,
419 refs: &mut Vec<Option<Bag::Constant>>,
420) -> Result<Vec<alloc::string::String>> {
421 let raw = rdr.read_u8()?;
422 let type_byte = raw & !FLAG_REF;
423 let has_flag = raw & FLAG_REF != 0;
424
425 if type_byte == Type::Ref as u8 {
426 let idx = rdr.read_u32()? as usize;
427 let stored = resolve_ref(idx, refs)?;
428 return match stored.borrow_constant() {
429 BorrowedConstant::Tuple { elements } => elements
430 .iter()
431 .map(|c| match c.borrow_constant() {
432 BorrowedConstant::Str { value } => Ok(value.to_string_lossy().into_owned()),
433 _ => Err(MarshalError::BadType),
434 })
435 .collect(),
436 _ => Err(MarshalError::BadType),
437 };
438 }
439
440 let n = match type_byte {
441 b'(' => rdr.read_len("tuple")?,
442 b')' => rdr.read_u8()? as usize,
443 _ => return Err(MarshalError::BadType),
444 };
445 let slot = reserve_ref_slot(has_flag, refs);
446 let items: Vec<alloc::string::String> = (0..n)
447 .map(|_| read_marshal_str(rdr, bag, refs))
448 .collect::<Result<_>>()?;
449 if let Some(idx) = slot {
450 let elements: Vec<Bag::Constant> = items
451 .iter()
452 .map(|s| {
453 bag.make_constant::<Bag::Constant>(BorrowedConstant::Str {
454 value: Wtf8::new(s.as_str()),
455 })
456 })
457 .collect();
458 refs[idx] = Some(bag.make_constant::<Bag::Constant>(BorrowedConstant::Tuple {
459 elements: &elements,
460 }));
461 }
462 Ok(items)
463}
464
465fn read_marshal_name_tuple<R: Read, Bag: ConstantBag>(
466 rdr: &mut R,
467 bag: &Bag,
468 refs: &mut Vec<Option<Bag::Constant>>,
469) -> Result<Box<[<Bag::Constant as Constant>::Name]>> {
470 let names = read_marshal_str_vec(rdr, bag, refs)?;
471 Ok(names
472 .iter()
473 .map(|s| bag.make_name(s))
474 .collect::<Vec<_>>()
475 .into_boxed_slice())
476}
477
478fn read_marshal_const_tuple<R: Read, Bag: ConstantBag>(
482 rdr: &mut R,
483 bag: Bag,
484 depth: usize,
485 refs: &mut Vec<Option<Bag::Constant>>,
486) -> Result<Constants<Bag::Constant>> {
487 if depth == 0 {
488 return Err(MarshalError::InvalidBytecode);
489 }
490 let raw = rdr.read_u8()?;
491 let type_byte = raw & !FLAG_REF;
492 let has_flag = raw & FLAG_REF != 0;
493
494 if type_byte == Type::Ref as u8 {
495 let idx = rdr.read_u32()? as usize;
496 let stored = resolve_ref(idx, refs)?;
497 return match stored.borrow_constant() {
498 BorrowedConstant::Tuple { elements } => Ok(elements.iter().cloned().collect()),
499 _ => Err(MarshalError::BadType),
500 };
501 }
502
503 let n = match type_byte {
504 b'(' => rdr.read_len("tuple")?,
505 b')' => rdr.read_u8()? as usize,
506 _ => return Err(MarshalError::BadType),
507 };
508 let slot = reserve_ref_slot(has_flag, refs);
509 let child_depth = depth - 1;
510 let items: Vec<Bag::Constant> = (0..n)
511 .map(|_| read_const_value(rdr, bag, child_depth, refs))
512 .collect::<Result<_>>()?;
513 if let Some(idx) = slot {
514 refs[idx] =
515 Some(bag.make_constant::<Bag::Constant>(BorrowedConstant::Tuple { elements: &items }));
516 }
517 Ok(items.into_iter().collect())
518}
519
520fn read_const_value<R: Read, Bag: ConstantBag>(
526 rdr: &mut R,
527 bag: Bag,
528 depth: usize,
529 refs: &mut Vec<Option<Bag::Constant>>,
530) -> Result<Bag::Constant> {
531 if depth == 0 {
532 return Err(MarshalError::InvalidBytecode);
533 }
534 let raw = rdr.read_u8()?;
535 let flag = raw & FLAG_REF != 0;
536 let type_code = raw & !FLAG_REF;
537
538 if type_code == Type::Ref as u8 {
539 let idx = rdr.read_u32()? as usize;
540 return resolve_ref(idx, refs);
541 }
542
543 let slot = reserve_ref_slot(flag, refs);
544 let typ = Type::try_from(type_code)?;
545 let value = if matches!(typ, Type::Code) {
546 let code = deserialize_code_inner(rdr, bag, depth - 1, refs)?;
547 bag.make_code(code)
548 } else {
549 deserialize_value_typed(rdr, bag, depth, refs, typ, slot)?
550 };
551 if let Some(idx) = slot {
552 refs[idx] = Some(value.clone());
553 }
554 Ok(value)
555}
556
557pub trait MarshalBag: Copy {
558 type Value: Clone;
559 type ConstantBag: ConstantBag;
560
561 fn make_bool(&self, value: bool) -> Self::Value;
562
563 fn make_none(&self) -> Self::Value;
564
565 fn make_ellipsis(&self) -> Self::Value;
566
567 fn make_float(&self, value: f64) -> Self::Value;
568
569 fn make_complex(&self, value: Complex64) -> Self::Value;
570
571 fn make_str(&self, value: &Wtf8) -> Self::Value;
572
573 fn make_interned_str(&self, value: &Wtf8) -> Self::Value {
574 self.make_str(value)
575 }
576
577 fn make_bytes(&self, value: &[u8]) -> Self::Value;
578
579 fn make_int(&self, value: BigInt) -> Self::Value;
580
581 fn make_tuple(&self, elements: impl Iterator<Item = Self::Value>) -> Self::Value;
582
583 fn make_code(
584 &self,
585 code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
586 ) -> Result<Self::Value>;
587
588 fn make_code_with_constants(
593 &self,
594 code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
595 _constants: Vec<Self::Value>,
596 ) -> Result<Self::Value> {
597 self.make_code(code)
598 }
599
600 fn code_units_from_bytes(&self, code_bytes: &[u8]) -> Result<CodeUnits> {
608 CodeUnits::try_from(code_bytes)
609 }
610
611 fn make_code_with_constants_and_bytes(
619 &self,
620 code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
621 constants: Vec<Self::Value>,
622 _code_bytes: Vec<u8>,
623 ) -> Result<Self::Value> {
624 self.make_code_with_constants(code, constants)
625 }
626
627 fn make_stop_iter(&self) -> Result<Self::Value>;
628
629 fn make_list(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
630
631 fn make_set(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
632
633 fn make_frozenset(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
634
635 fn make_dict(
636 &self,
637 it: impl Iterator<Item = (Self::Value, Self::Value)>,
638 ) -> Result<Self::Value>;
639
640 fn make_tuple_placeholder(&self, _len: usize) -> Result<Option<Self::Value>> {
648 Ok(None)
649 }
650
651 fn set_tuple_item(
652 &self,
653 _tuple: &Self::Value,
654 _index: usize,
655 _value: Self::Value,
656 ) -> Result<()> {
657 Err(MarshalError::BadType)
658 }
659
660 fn make_list_placeholder(&self, _len: usize) -> Result<Option<Self::Value>> {
661 Ok(None)
662 }
663
664 fn set_list_item(&self, _list: &Self::Value, _index: usize, _value: Self::Value) -> Result<()> {
665 Err(MarshalError::BadType)
666 }
667
668 fn make_set_placeholder(&self) -> Option<Self::Value> {
669 None
670 }
671
672 fn insert_set_item(&self, _set: &Self::Value, _value: Self::Value) -> Result<()> {
673 Err(MarshalError::BadType)
674 }
675
676 fn make_dict_placeholder(&self) -> Option<Self::Value> {
677 None
678 }
679
680 fn insert_dict_item(
681 &self,
682 _dict: &Self::Value,
683 _key: Self::Value,
684 _value: Self::Value,
685 ) -> Result<()> {
686 Err(MarshalError::BadType)
687 }
688
689 fn make_slice(
690 &self,
691 _start: Self::Value,
692 _stop: Self::Value,
693 _step: Self::Value,
694 ) -> Result<Self::Value> {
695 Err(MarshalError::BadType)
696 }
697
698 fn constant_bag(self) -> Self::ConstantBag;
699
700 fn constant_ref_from_value(
701 &self,
702 _value: &Self::Value,
703 ) -> Option<<Self::ConstantBag as ConstantBag>::Constant> {
704 None
705 }
706
707 fn code_constant_from_value(
712 &self,
713 value: &Self::Value,
714 ) -> Result<<Self::ConstantBag as ConstantBag>::Constant> {
715 self.constant_ref_from_value(value)
716 .ok_or(MarshalError::BadType)
717 }
718
719 fn bytes_from_value(&self, _value: &Self::Value) -> Option<Vec<u8>> {
720 None
721 }
722
723 fn str_from_value(&self, _value: &Self::Value) -> Option<alloc::string::String> {
724 None
725 }
726
727 fn tuple_elements_from_value(&self, _value: &Self::Value) -> Option<Vec<Self::Value>> {
728 None
729 }
730}
731
732impl<Bag: ConstantBag> MarshalBag for Bag {
733 type Value = Bag::Constant;
734 type ConstantBag = Self;
735
736 fn make_bool(&self, value: bool) -> Self::Value {
737 self.make_constant::<Bag::Constant>(BorrowedConstant::Boolean { value })
738 }
739
740 fn make_none(&self) -> Self::Value {
741 self.make_constant::<Bag::Constant>(BorrowedConstant::None)
742 }
743
744 fn make_ellipsis(&self) -> Self::Value {
745 self.make_constant::<Bag::Constant>(BorrowedConstant::Ellipsis)
746 }
747
748 fn make_float(&self, value: f64) -> Self::Value {
749 self.make_constant::<Bag::Constant>(BorrowedConstant::Float { value })
750 }
751
752 fn make_complex(&self, value: Complex64) -> Self::Value {
753 self.make_constant::<Bag::Constant>(BorrowedConstant::Complex { value })
754 }
755
756 fn make_str(&self, value: &Wtf8) -> Self::Value {
757 self.make_constant::<Bag::Constant>(BorrowedConstant::Str { value })
758 }
759
760 fn make_bytes(&self, value: &[u8]) -> Self::Value {
761 self.make_constant::<Bag::Constant>(BorrowedConstant::Bytes { value })
762 }
763
764 fn make_int(&self, value: BigInt) -> Self::Value {
765 self.make_int(value)
766 }
767
768 fn make_tuple(&self, elements: impl Iterator<Item = Self::Value>) -> Self::Value {
769 self.make_tuple(elements)
770 }
771
772 fn make_slice(
773 &self,
774 start: Self::Value,
775 stop: Self::Value,
776 step: Self::Value,
777 ) -> Result<Self::Value> {
778 let elements = [start, stop, step];
779 Ok(
780 self.make_constant::<Bag::Constant>(BorrowedConstant::Slice {
781 elements: &elements,
782 }),
783 )
784 }
785
786 fn make_code(
787 &self,
788 code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
789 ) -> Result<Self::Value> {
790 Ok(self.make_code(code))
791 }
792
793 fn make_stop_iter(&self) -> Result<Self::Value> {
794 Err(MarshalError::BadType)
795 }
796
797 fn make_list(&self, _: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
798 Err(MarshalError::BadType)
799 }
800
801 fn make_set(&self, _: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
802 Err(MarshalError::BadType)
803 }
804
805 fn make_frozenset(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
806 let elements: Vec<Self::Value> = it.collect();
807 Ok(
808 self.make_constant::<Bag::Constant>(BorrowedConstant::Frozenset {
809 elements: &elements,
810 }),
811 )
812 }
813
814 fn make_dict(
815 &self,
816 _: impl Iterator<Item = (Self::Value, Self::Value)>,
817 ) -> Result<Self::Value> {
818 Err(MarshalError::BadType)
819 }
820
821 fn constant_bag(self) -> Self::ConstantBag {
822 self
823 }
824
825 fn constant_ref_from_value(
826 &self,
827 value: &Self::Value,
828 ) -> Option<<Self::ConstantBag as ConstantBag>::Constant> {
829 Some(value.clone())
830 }
831
832 fn bytes_from_value(&self, value: &Self::Value) -> Option<Vec<u8>> {
833 match value.borrow_constant() {
834 BorrowedConstant::Bytes { value } => Some(value.to_vec()),
835 _ => None,
836 }
837 }
838
839 fn str_from_value(&self, value: &Self::Value) -> Option<alloc::string::String> {
840 match value.borrow_constant() {
841 BorrowedConstant::Str { value } => Some(value.to_string_lossy().into_owned()),
842 _ => None,
843 }
844 }
845
846 fn tuple_elements_from_value(&self, value: &Self::Value) -> Option<Vec<Self::Value>> {
847 match value.borrow_constant() {
848 BorrowedConstant::Tuple { elements } => Some(elements.to_vec()),
849 _ => None,
850 }
851 }
852}
853
854pub const MAX_MARSHAL_STACK_DEPTH: usize = 2000;
855
856pub fn deserialize_value<R: Read, Bag: MarshalBag>(rdr: &mut R, bag: Bag) -> Result<Bag::Value> {
857 let mut refs: Vec<Option<Bag::Value>> = Vec::new();
858 deserialize_value_depth(rdr, bag, MAX_MARSHAL_STACK_DEPTH, &mut refs)
859}
860
861fn read_object_type<R: Read>(rdr: &mut R) -> Result<u8> {
864 rdr.read_u8().map_err(|_| MarshalError::EofObject)
865}
866
867fn deserialize_value_depth<R: Read, Bag: MarshalBag>(
868 rdr: &mut R,
869 bag: Bag,
870 depth: usize,
871 refs: &mut Vec<Option<Bag::Value>>,
872) -> Result<Bag::Value> {
873 if depth == 0 {
874 return Err(MarshalError::InvalidBytecode);
875 }
876 let raw = read_object_type(rdr)?;
877 deserialize_value_after_header(rdr, bag, depth, refs, raw)
878}
879
880fn deserialize_value_after_header<R: Read, Bag: MarshalBag>(
885 rdr: &mut R,
886 bag: Bag,
887 depth: usize,
888 refs: &mut Vec<Option<Bag::Value>>,
889 raw: u8,
890) -> Result<Bag::Value> {
891 if depth == 0 {
892 return Err(MarshalError::InvalidBytecode);
893 }
894 let flag = raw & FLAG_REF != 0;
895 let type_code = raw & !FLAG_REF;
896
897 if type_code == Type::Ref as u8 {
899 let idx = rdr.read_u32()? as usize;
900 return resolve_ref(idx, refs);
901 }
902
903 let slot = if flag {
905 let idx = refs.len();
906 refs.push(None);
907 Some(idx)
908 } else {
909 None
910 };
911
912 let typ = Type::try_from(type_code)?;
913 let value = if matches!(typ, Type::Code) {
914 deserialize_code_value_inner(rdr, bag, depth - 1, refs)?
915 } else {
916 deserialize_value_typed(rdr, bag, depth, refs, typ, slot)?
917 };
918
919 if let Some(idx) = slot {
920 refs[idx] = Some(value.clone());
921 }
922 Ok(value)
923}
924
925fn deserialize_code_value_inner<R: Read, Bag: MarshalBag>(
930 rdr: &mut R,
931 bag: Bag,
932 depth: usize,
933 refs: &mut Vec<Option<Bag::Value>>,
934) -> Result<Bag::Value> {
935 if depth == 0 {
936 return Err(MarshalError::InvalidBytecode);
937 }
938 let arg_count = rdr.read_u32()?;
939 let posonlyarg_count = rdr.read_u32()?;
940 let kwonlyarg_count = rdr.read_u32()?;
941 let max_stackdepth = rdr.read_u32()?;
942 let flags = CodeFlags::from_bits_truncate(rdr.read_u32()?);
943 let child_depth = depth - 1;
944
945 let code_value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
946 let code_bytes = bag
947 .bytes_from_value(&code_value)
948 .ok_or(MarshalError::BadType)?;
949
950 let consts_value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
951 let constant_values = bag
952 .tuple_elements_from_value(&consts_value)
953 .ok_or(MarshalError::BadType)?;
954 let constants = constant_values
955 .iter()
956 .map(|value| bag.code_constant_from_value(value))
957 .collect::<Result<Vec<_>>>()?
958 .into_iter()
959 .collect();
960
961 let read_strings =
962 |rdr: &mut R, refs: &mut Vec<Option<Bag::Value>>| -> Result<Vec<alloc::string::String>> {
963 let tuple = deserialize_value_depth(rdr, bag, child_depth, refs)?;
964 bag.tuple_elements_from_value(&tuple)
965 .ok_or(MarshalError::BadType)?
966 .iter()
967 .map(|value| bag.str_from_value(value).ok_or(MarshalError::BadType))
968 .collect()
969 };
970 let names_raw = read_strings(rdr, refs)?;
971 let localsplusnames = read_strings(rdr, refs)?;
972
973 let kinds_value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
974 let localspluskinds = bag
975 .bytes_from_value(&kinds_value)
976 .ok_or(MarshalError::BadType)?;
977
978 let read_string =
979 |rdr: &mut R, refs: &mut Vec<Option<Bag::Value>>| -> Result<alloc::string::String> {
980 let value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
981 bag.str_from_value(&value).ok_or(MarshalError::BadType)
982 };
983 let source_path_raw = read_string(rdr, refs)?;
984 let obj_name_raw = read_string(rdr, refs)?;
985 let qualname_raw = read_string(rdr, refs)?;
986
987 let first_line_raw = rdr.read_u32()? as i32;
988 let first_line_number = if first_line_raw > 0 {
989 OneIndexed::new(first_line_raw as usize)
990 } else {
991 None
992 };
993 let linetable_value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
994 let linetable = bag
995 .bytes_from_value(&linetable_value)
996 .ok_or(MarshalError::BadType)?
997 .into_boxed_slice();
998 let exceptiontable_value = deserialize_value_depth(rdr, bag, child_depth, refs)?;
999 let exceptiontable = bag
1000 .bytes_from_value(&exceptiontable_value)
1001 .ok_or(MarshalError::BadType)?
1002 .into_boxed_slice();
1003
1004 let lp = split_localplus(
1005 &localsplusnames
1006 .iter()
1007 .map(|s| s.as_str())
1008 .collect::<Vec<_>>(),
1009 &localspluskinds,
1010 arg_count,
1011 kwonlyarg_count,
1012 flags,
1013 )?;
1014 let instructions = bag.code_units_from_bytes(&code_bytes)?;
1015 let locations = linetable_to_locations(&linetable, first_line_raw, instructions.len());
1016 let constant_bag = bag.constant_bag();
1017 let code = CodeObject {
1018 instructions,
1019 locations,
1020 flags,
1021 posonlyarg_count,
1022 arg_count,
1023 kwonlyarg_count,
1024 source_path: constant_bag.make_name(&source_path_raw),
1025 first_line_number,
1026 max_stackdepth,
1027 obj_name: constant_bag.make_name(&obj_name_raw),
1028 qualname: constant_bag.make_name(&qualname_raw),
1029 constants,
1030 names: names_raw
1031 .iter()
1032 .map(|name| constant_bag.make_name(name))
1033 .collect(),
1034 varnames: lp
1035 .varnames
1036 .iter()
1037 .map(|name| constant_bag.make_name(name))
1038 .collect(),
1039 cellvars: lp
1040 .cellvars
1041 .iter()
1042 .map(|name| constant_bag.make_name(name))
1043 .collect(),
1044 freevars: lp
1045 .freevars
1046 .iter()
1047 .map(|name| constant_bag.make_name(name))
1048 .collect(),
1049 localspluskinds: localspluskinds.into_boxed_slice(),
1050 linetable,
1051 exceptiontable,
1052 };
1053 bag.make_code_with_constants_and_bytes(code, constant_values, code_bytes)
1054}
1055
1056fn deserialize_value_typed<R: Read, Bag: MarshalBag>(
1057 rdr: &mut R,
1058 bag: Bag,
1059 depth: usize,
1060 refs: &mut Vec<Option<Bag::Value>>,
1061 typ: Type,
1062 slot: Option<usize>,
1063) -> Result<Bag::Value> {
1064 if depth == 0 {
1065 return Err(MarshalError::InvalidBytecode);
1066 }
1067 let value = match typ {
1068 Type::True => bag.make_bool(true),
1069 Type::False => bag.make_bool(false),
1070 Type::None => bag.make_none(),
1071 Type::StopIter => bag.make_stop_iter()?,
1072 Type::Ellipsis => bag.make_ellipsis(),
1073 Type::Int => {
1074 let val = rdr.read_u32()? as i32;
1075 bag.make_int(BigInt::from(val))
1076 }
1077 Type::Int64 => {
1078 let lo = rdr.read_u32()? as u64;
1079 let hi = rdr.read_u32()? as u64;
1080 bag.make_int(BigInt::from(((hi << 32) | lo) as i64))
1081 }
1082 Type::Long => bag.make_int(read_pylong(rdr)?),
1083 Type::FloatStr => bag.make_float(read_float_str(rdr)?),
1084 Type::Float => {
1085 let value = f64::from_bits(rdr.read_u64()?);
1086 bag.make_float(value)
1087 }
1088 Type::ComplexStr => {
1089 let re = read_float_str(rdr)?;
1090 let im = read_float_str(rdr)?;
1091 bag.make_complex(Complex64 { re, im })
1092 }
1093 Type::Complex => {
1094 let re = f64::from_bits(rdr.read_u64()?);
1095 let im = f64::from_bits(rdr.read_u64()?);
1096 let value = Complex64 { re, im };
1097 bag.make_complex(value)
1098 }
1099 Type::Ascii | Type::Unicode => {
1100 let len = rdr.read_len("string")?;
1101 let value = rdr.read_wtf8(len as u32)?;
1102 bag.make_str(value)
1103 }
1104 Type::AsciiInterned | Type::Interned => {
1105 let len = rdr.read_len("string")?;
1106 let value = rdr.read_wtf8(len as u32)?;
1107 bag.make_interned_str(value)
1108 }
1109 Type::ShortAscii => {
1110 let len = rdr.read_u8()? as u32;
1111 let value = rdr.read_wtf8(len)?;
1112 bag.make_str(value)
1113 }
1114 Type::ShortAsciiInterned => {
1115 let len = rdr.read_u8()? as u32;
1116 let value = rdr.read_wtf8(len)?;
1117 bag.make_interned_str(value)
1118 }
1119 Type::SmallTuple => {
1120 let len = rdr.read_u8()? as usize;
1121 let d = depth - 1;
1122 if let Some(index) = slot
1123 && let Some(tuple) = bag.make_tuple_placeholder(len)?
1124 {
1125 refs[index] = Some(tuple.clone());
1126 for item_index in 0..len {
1127 let item = deserialize_value_depth(rdr, bag, d, refs)?;
1128 bag.set_tuple_item(&tuple, item_index, item)?;
1129 }
1130 tuple
1131 } else {
1132 let it = (0..len).map(|_| deserialize_value_depth(rdr, bag, d, refs));
1133 itertools::process_results(it, |it| bag.make_tuple(it))?
1134 }
1135 }
1136 Type::Null => {
1137 return Err(MarshalError::NullObject);
1138 }
1139 Type::Ref => {
1140 return Err(MarshalError::BadType);
1142 }
1143 Type::Tuple => {
1144 let len = rdr.read_len("tuple")?;
1145 let d = depth - 1;
1146 if let Some(index) = slot
1147 && let Some(tuple) = bag.make_tuple_placeholder(len)?
1148 {
1149 refs[index] = Some(tuple.clone());
1150 for item_index in 0..len {
1151 let item = deserialize_value_depth(rdr, bag, d, refs)?;
1152 bag.set_tuple_item(&tuple, item_index, item)?;
1153 }
1154 tuple
1155 } else {
1156 let it = (0..len).map(|_| deserialize_value_depth(rdr, bag, d, refs));
1157 itertools::process_results(it, |it| bag.make_tuple(it))?
1158 }
1159 }
1160 Type::List => {
1161 let len = rdr.read_len("list")?;
1162 let d = depth - 1;
1163 if let Some(index) = slot
1164 && let Some(list) = bag.make_list_placeholder(len)?
1165 {
1166 refs[index] = Some(list.clone());
1167 for item_index in 0..len {
1168 let item = deserialize_value_depth(rdr, bag, d, refs)?;
1169 bag.set_list_item(&list, item_index, item)?;
1170 }
1171 list
1172 } else {
1173 let it = (0..len).map(|_| deserialize_value_depth(rdr, bag, d, refs));
1174 itertools::process_results(it, |it| bag.make_list(it))??
1175 }
1176 }
1177 Type::Set => {
1178 let len = rdr.read_len("set")?;
1179 let d = depth - 1;
1180 if let Some(index) = slot
1181 && let Some(set) = bag.make_set_placeholder()
1182 {
1183 refs[index] = Some(set.clone());
1184 for _ in 0..len {
1185 let item = deserialize_value_depth(rdr, bag, d, refs)?;
1186 bag.insert_set_item(&set, item)?;
1187 }
1188 set
1189 } else {
1190 let it = (0..len).map(|_| deserialize_value_depth(rdr, bag, d, refs));
1191 itertools::process_results(it, |it| bag.make_set(it))??
1192 }
1193 }
1194 Type::FrozenSet => {
1195 let len = rdr.read_len("set")?;
1196 let d = depth - 1;
1197 let it = (0..len).map(|_| deserialize_value_depth(rdr, bag, d, refs));
1198 itertools::process_results(it, |it| bag.make_frozenset(it))??
1199 }
1200 Type::Dict => {
1201 let d = depth - 1;
1202 if let Some(index) = slot
1203 && let Some(dict) = bag.make_dict_placeholder()
1204 {
1205 refs[index] = Some(dict.clone());
1206 loop {
1207 let raw = read_object_type(rdr)?;
1208 if raw & !FLAG_REF == b'0' {
1209 break;
1210 }
1211 let key = deserialize_value_after_header(rdr, bag, d, refs, raw)?;
1212 let value = deserialize_value_depth(rdr, bag, d, refs)?;
1213 bag.insert_dict_item(&dict, key, value)?;
1214 }
1215 dict
1216 } else {
1217 let mut pairs = Vec::new();
1218 loop {
1219 let raw = read_object_type(rdr)?;
1220 if raw & !FLAG_REF == b'0' {
1221 break;
1222 }
1223 let key = deserialize_value_after_header(rdr, bag, d, refs, raw)?;
1224 let value = deserialize_value_depth(rdr, bag, d, refs)?;
1225 pairs.push((key, value));
1226 }
1227 bag.make_dict(pairs.into_iter())?
1228 }
1229 }
1230 Type::Bytes => {
1231 let len = rdr.read_len("bytes object")?;
1233 let value = rdr.read_slice(len as u32)?;
1234 bag.make_bytes(value)
1235 }
1236 Type::Code => return Err(MarshalError::BadType),
1237 Type::Slice => {
1238 let d = depth - 1;
1239 let start = deserialize_value_depth(rdr, bag, d, refs)?;
1240 let stop = deserialize_value_depth(rdr, bag, d, refs)?;
1241 let step = deserialize_value_depth(rdr, bag, d, refs)?;
1242 bag.make_slice(start, stop, step)?
1243 }
1244 };
1245 Ok(value)
1246}
1247
1248pub trait Dumpable: Sized {
1249 type Error;
1250 type Constant: Constant;
1251
1252 fn with_dump<R>(&self, f: impl FnOnce(DumpableValue<'_, Self>) -> R) -> Result<R, Self::Error>;
1253}
1254
1255pub enum DumpableValue<'a, D: Dumpable> {
1256 Integer(&'a BigInt),
1257 Float(f64),
1258 Complex(Complex64),
1259 Boolean(bool),
1260 Str(&'a Wtf8),
1261 Bytes(&'a [u8]),
1262 Code(&'a CodeObject<D::Constant>),
1263 Tuple(&'a [D]),
1264 None,
1265 Ellipsis,
1266 StopIter,
1267 List(&'a [D]),
1268 Set(&'a [D]),
1269 Frozenset(&'a [D]),
1270 Dict(&'a [(D, D)]),
1271 Slice(&'a D, &'a D, &'a D),
1272}
1273
1274impl<'a, C: Constant> From<BorrowedConstant<'a, C>> for DumpableValue<'a, C> {
1275 fn from(c: BorrowedConstant<'a, C>) -> Self {
1276 match c {
1277 BorrowedConstant::Integer { value } => Self::Integer(value),
1278 BorrowedConstant::Float { value } => Self::Float(value),
1279 BorrowedConstant::Complex { value } => Self::Complex(value),
1280 BorrowedConstant::Boolean { value } => Self::Boolean(value),
1281 BorrowedConstant::Str { value } => Self::Str(value),
1282 BorrowedConstant::Bytes { value } => Self::Bytes(value),
1283 BorrowedConstant::Code { code } => Self::Code(code),
1284 BorrowedConstant::Tuple { elements } => Self::Tuple(elements),
1285 BorrowedConstant::Slice { elements } => {
1286 Self::Slice(&elements[0], &elements[1], &elements[2])
1287 }
1288 BorrowedConstant::Frozenset { elements } => Self::Frozenset(elements),
1289 BorrowedConstant::None => Self::None,
1290 BorrowedConstant::Ellipsis => Self::Ellipsis,
1291 }
1292 }
1293}
1294
1295impl<C: Constant> Dumpable for C {
1296 type Error = Infallible;
1297 type Constant = Self;
1298
1299 #[inline(always)]
1300 fn with_dump<R>(&self, f: impl FnOnce(DumpableValue<'_, Self>) -> R) -> Result<R, Self::Error> {
1301 Ok(f(self.borrow_constant().into()))
1302 }
1303}
1304
1305pub trait Write {
1306 fn write_slice(&mut self, slice: &[u8]);
1307
1308 fn write_u8(&mut self, v: u8) {
1309 self.write_slice(&v.to_le_bytes())
1310 }
1311
1312 fn write_u16(&mut self, v: u16) {
1313 self.write_slice(&v.to_le_bytes())
1314 }
1315
1316 fn write_u32(&mut self, v: u32) {
1317 self.write_slice(&v.to_le_bytes())
1318 }
1319
1320 fn write_u64(&mut self, v: u64) {
1321 self.write_slice(&v.to_le_bytes())
1322 }
1323}
1324
1325impl Write for Vec<u8> {
1326 fn write_slice(&mut self, slice: &[u8]) {
1327 self.extend_from_slice(slice)
1328 }
1329}
1330
1331pub(crate) fn write_len<W: Write>(buf: &mut W, len: usize) {
1332 let Ok(len) = len.try_into() else {
1333 panic!("too long to serialize")
1334 };
1335 buf.write_u32(len);
1336}
1337
1338pub(crate) fn write_vec<W: Write>(buf: &mut W, slice: &[u8]) {
1339 write_len(buf, slice.len());
1340 buf.write_slice(slice);
1341}
1342
1343pub fn serialize_value<W: Write, D: Dumpable>(
1344 buf: &mut W,
1345 constant: DumpableValue<'_, D>,
1346) -> Result<(), D::Error> {
1347 match constant {
1348 DumpableValue::Integer(int) => {
1349 if let Ok(val) = i32::try_from(int) {
1350 buf.write_u8(Type::Int as u8); buf.write_u32(val as u32);
1352 } else {
1353 buf.write_u8(Type::Long as u8);
1354 let (sign, raw) = int.to_bytes_le();
1355 let mut digits = alloc::vec::Vec::new();
1356 let mut accum: u32 = 0;
1357 let mut bits = 0u32;
1358 for &byte in &raw {
1359 accum |= (byte as u32) << bits;
1360 bits += 8;
1361 while bits >= 15 {
1362 digits.push((accum & 0x7fff) as u16);
1363 accum >>= 15;
1364 bits -= 15;
1365 }
1366 }
1367 if accum > 0 || digits.is_empty() {
1368 digits.push(accum as u16);
1369 }
1370 while digits.len() > 1 && *digits.last().unwrap() == 0 {
1371 digits.pop();
1372 }
1373 let n = digits.len() as i32;
1374 let n = if sign == Sign::Minus { -n } else { n };
1375 buf.write_u32(n as u32);
1376 for d in &digits {
1377 buf.write_u16(*d);
1378 }
1379 }
1380 }
1381 DumpableValue::Float(f) => {
1382 buf.write_u8(Type::Float as u8);
1383 buf.write_u64(f.to_bits());
1384 }
1385 DumpableValue::Complex(c) => {
1386 buf.write_u8(Type::Complex as u8);
1387 buf.write_u64(c.re.to_bits());
1388 buf.write_u64(c.im.to_bits());
1389 }
1390 DumpableValue::Boolean(b) => {
1391 buf.write_u8(if b { Type::True } else { Type::False } as u8);
1392 }
1393 DumpableValue::Str(s) => {
1394 buf.write_u8(Type::Unicode as u8);
1395 write_vec(buf, s.as_bytes());
1396 }
1397 DumpableValue::Bytes(b) => {
1398 buf.write_u8(Type::Bytes as u8);
1399 write_vec(buf, b);
1400 }
1401 DumpableValue::Code(c) => {
1402 buf.write_u8(Type::Code as u8);
1403 serialize_code(buf, c);
1404 }
1405 DumpableValue::Tuple(tup) => {
1406 buf.write_u8(Type::Tuple as u8);
1407 write_len(buf, tup.len());
1408 for val in tup {
1409 val.with_dump(|val| serialize_value(buf, val))??
1410 }
1411 }
1412 DumpableValue::None => {
1413 buf.write_u8(Type::None as u8);
1414 }
1415 DumpableValue::Ellipsis => {
1416 buf.write_u8(Type::Ellipsis as u8);
1417 }
1418 DumpableValue::StopIter => {
1419 buf.write_u8(Type::StopIter as u8);
1420 }
1421 DumpableValue::List(l) => {
1422 buf.write_u8(Type::List as u8);
1423 write_len(buf, l.len());
1424 for val in l {
1425 val.with_dump(|val| serialize_value(buf, val))??
1426 }
1427 }
1428 DumpableValue::Set(set) => {
1429 buf.write_u8(Type::Set as u8);
1430 write_len(buf, set.len());
1431 for val in set {
1432 val.with_dump(|val| serialize_value(buf, val))??
1433 }
1434 }
1435 DumpableValue::Frozenset(set) => {
1436 buf.write_u8(Type::FrozenSet as u8);
1437 write_len(buf, set.len());
1438 for val in set {
1439 val.with_dump(|val| serialize_value(buf, val))??
1440 }
1441 }
1442 DumpableValue::Dict(d) => {
1443 buf.write_u8(Type::Dict as u8);
1444 for (k, v) in d {
1445 k.with_dump(|val| serialize_value(buf, val))??;
1446 v.with_dump(|val| serialize_value(buf, val))??;
1447 }
1448 buf.write_u8(b'0'); }
1450 DumpableValue::Slice(start, stop, step) => {
1451 buf.write_u8(Type::Slice as u8);
1452 start.with_dump(|val| serialize_value(buf, val))??;
1453 stop.with_dump(|val| serialize_value(buf, val))??;
1454 step.with_dump(|val| serialize_value(buf, val))??;
1455 }
1456 }
1457 Ok(())
1458}
1459
1460pub fn serialize_code<W: Write, C: Constant>(buf: &mut W, code: &CodeObject<C>) {
1465 serialize_code_with(buf, code, |buf, constant| {
1466 serialize_value(buf, constant.borrow_constant().into()).unwrap_or_else(|x| match x {});
1467 Ok::<(), core::convert::Infallible>(())
1468 })
1469 .unwrap_or_else(|x| match x {})
1470}
1471
1472pub fn serialize_code_with<W: Write, C: Constant, E>(
1480 buf: &mut W,
1481 code: &CodeObject<C>,
1482 mut write_constant: impl FnMut(&mut W, &C) -> core::result::Result<(), E>,
1483) -> core::result::Result<(), E> {
1484 buf.write_u32(code.arg_count);
1486 buf.write_u32(code.posonlyarg_count);
1487 buf.write_u32(code.kwonlyarg_count);
1488 buf.write_u32(code.max_stackdepth);
1489 buf.write_u32(code.flags.bits());
1490
1491 let bytecode = code.instructions.original_bytes();
1493 buf.write_u8(Type::Bytes as u8);
1494 write_vec(buf, &bytecode);
1495
1496 buf.write_u8(Type::Tuple as u8);
1498 write_len(buf, code.constants.len());
1499 for constant in &*code.constants {
1500 write_constant(buf, constant)?;
1501 }
1502
1503 write_marshal_name_tuple(buf, &code.names);
1505
1506 let cell_only_names: Vec<&str> = code
1508 .cellvars
1509 .iter()
1510 .filter(|cv| !code.varnames.iter().any(|v| v.as_ref() == cv.as_ref()))
1511 .map(|cv| cv.as_ref())
1512 .collect();
1513 let total_lp_count = code.varnames.len() + cell_only_names.len() + code.freevars.len();
1514 buf.write_u8(Type::Tuple as u8);
1515 write_len(buf, total_lp_count);
1516 for n in &code.varnames {
1517 write_marshal_str(buf, n.as_ref());
1518 }
1519 for &n in &cell_only_names {
1520 write_marshal_str(buf, n);
1521 }
1522 for n in &code.freevars {
1523 write_marshal_str(buf, n.as_ref());
1524 }
1525 buf.write_u8(Type::Bytes as u8);
1527 write_vec(buf, &code.localspluskinds);
1528
1529 write_marshal_str(buf, code.source_path.as_ref());
1531 write_marshal_str(buf, code.obj_name.as_ref());
1533 write_marshal_str(buf, code.qualname.as_ref());
1535 buf.write_u32(code.first_line_number.map_or(0, |x| x.get() as _));
1537 buf.write_u8(Type::Bytes as u8);
1539 write_vec(buf, &code.linetable);
1540 buf.write_u8(Type::Bytes as u8);
1542 write_vec(buf, &code.exceptiontable);
1543 Ok(())
1544}
1545
1546fn write_marshal_str<W: Write>(buf: &mut W, s: &str) {
1547 let bytes = s.as_bytes();
1548 if bytes.len() < 256 && bytes.is_ascii() {
1549 buf.write_u8(b'z'); buf.write_u8(bytes.len() as u8);
1551 } else {
1552 buf.write_u8(Type::Unicode as u8);
1553 write_len(buf, bytes.len());
1554 }
1555 buf.write_slice(bytes);
1556}
1557
1558fn write_marshal_name_tuple<W: Write, N: AsRef<str>>(buf: &mut W, names: &[N]) {
1559 buf.write_u8(Type::Tuple as u8);
1560 write_len(buf, names.len());
1561 for name in names {
1562 write_marshal_str(buf, name.as_ref());
1563 }
1564}
1565
1566pub const FLAG_REF: u8 = 0x80;
1567
1568pub fn read_i32<R: Read>(rdr: &mut R) -> Result<i32> {
1570 let bytes = rdr.read_array::<4>()?;
1571 Ok(i32::from_le_bytes(*bytes))
1572}
1573
1574pub fn read_pylong<R: Read>(rdr: &mut R) -> Result<BigInt> {
1576 const MARSHAL_SHIFT: u32 = 15;
1577 const MARSHAL_BASE: u32 = 1 << MARSHAL_SHIFT;
1578 let n = read_i32(rdr)?;
1579 if n == 0 {
1580 return Ok(BigInt::from(0));
1581 }
1582 let negative = n < 0;
1583 let num_digits = n.unsigned_abs() as usize;
1584 let mut accum = BigInt::from(0);
1585 let mut last_digit = 0u32;
1586 for i in 0..num_digits {
1587 let d = rdr.read_u16()? as u32;
1588 if d >= MARSHAL_BASE {
1589 return Err(MarshalError::InvalidBytecode);
1590 }
1591 last_digit = d;
1592 accum += BigInt::from(d) << (i as u32 * MARSHAL_SHIFT);
1593 }
1594 if num_digits > 0 && last_digit == 0 {
1595 return Err(MarshalError::InvalidBytecode);
1596 }
1597 if negative {
1598 accum = -accum;
1599 }
1600 Ok(accum)
1601}
1602
1603pub fn read_float_str<R: Read>(rdr: &mut R) -> Result<f64> {
1605 let n = rdr.read_u8()? as u32;
1606 let s = rdr.read_str(n)?;
1607 s.parse::<f64>().map_err(|_| MarshalError::InvalidBytecode)
1608}
1609
1610pub fn read_pstring<R: Read>(rdr: &mut R) -> Result<&[u8]> {
1612 let n = read_i32(rdr)?;
1613 if n < 0 {
1614 return Err(MarshalError::InvalidBytecode);
1615 }
1616 rdr.read_slice(n as u32)
1617}
1618
1619pub struct LocalsPlusResult<S> {
1620 pub varnames: Vec<S>,
1621 pub cellvars: Vec<S>,
1622 pub freevars: Vec<S>,
1623 pub cell2arg: Option<Box<[i32]>>,
1624 pub deref_map: Vec<u32>,
1625}
1626
1627pub fn split_localplus<S: Clone>(
1628 names: &[S],
1629 kinds: &[u8],
1630 arg_count: u32,
1631 kwonlyarg_count: u32,
1632 flags: CodeFlags,
1633) -> Result<LocalsPlusResult<S>> {
1634 if names.len() != kinds.len() {
1635 return Err(MarshalError::InvalidBytecode);
1636 }
1637
1638 let mut varnames = Vec::new();
1639 let mut cellvars = Vec::new();
1640 let mut freevars = Vec::new();
1641
1642 for (name, &kind) in names.iter().zip(kinds.iter()) {
1644 let kind = CoFastFlags::from_bits_retain(kind);
1645 if kind.contains(&CoFastFlag::Local) {
1646 varnames.push(name.clone());
1647 }
1648 if kind.contains(&CoFastFlag::Free) {
1649 freevars.push(name.clone());
1650 }
1651 }
1652
1653 let mut arg_cell_positions = Vec::new(); for (i, (name, &kind)) in names.iter().zip(kinds.iter()).enumerate() {
1659 let kind = CoFastFlags::from_bits_retain(kind);
1660 let is_local = kind.contains(&CoFastFlag::Local);
1661 let is_cell = kind.contains(&CoFastFlag::Cell);
1662 if is_cell {
1663 let cell_idx = cellvars.len();
1664 cellvars.push(name.clone());
1665 if is_local {
1666 arg_cell_positions.push((cell_idx, i));
1667 }
1668 }
1669 }
1670
1671 let total_args = {
1672 let mut t = arg_count + kwonlyarg_count;
1673 if flags.contains(CodeFlags::VARARGS) {
1674 t += 1;
1675 }
1676 if flags.contains(CodeFlags::VARKEYWORDS) {
1677 t += 1;
1678 }
1679 t
1680 };
1681
1682 let cell2arg = if !cellvars.is_empty() {
1683 let mut mapping = alloc::vec![-1i32; cellvars.len()];
1684 for &(cell_idx, localplus_idx) in &arg_cell_positions {
1685 if (localplus_idx as u32) < total_args {
1686 mapping[cell_idx] = localplus_idx as i32;
1687 }
1688 }
1689 if mapping.iter().any(|&x| x >= 0) {
1690 Some(mapping.into_boxed_slice())
1691 } else {
1692 None
1693 }
1694 } else {
1695 None
1696 };
1697
1698 let mut deref_map = alloc::vec![u32::MAX; names.len()];
1700 let mut cell_idx = 0u32;
1701 for (i, &kind) in kinds.iter().enumerate() {
1702 if CoFastFlags::from_bits_retain(kind).contains(&CoFastFlag::Cell) {
1703 deref_map[i] = cell_idx;
1704 cell_idx += 1;
1705 }
1706 }
1707 let ncells = cellvars.len();
1708 let mut free_idx = 0u32;
1709 for (i, &kind) in kinds.iter().enumerate() {
1710 if CoFastFlags::from_bits_retain(kind).contains(&CoFastFlag::Free) {
1711 deref_map[i] = ncells as u32 + free_idx;
1712 free_idx += 1;
1713 }
1714 }
1715
1716 Ok(LocalsPlusResult {
1717 varnames,
1718 cellvars,
1719 freevars,
1720 cell2arg,
1721 deref_map,
1722 })
1723}
1724
1725#[must_use]
1726pub fn linetable_to_locations(
1727 linetable: &[u8],
1728 first_line: i32,
1729 num_instructions: usize,
1730) -> Box<[(SourceLocation, SourceLocation)]> {
1731 let default_loc = || {
1732 let line = if first_line > 0 {
1733 OneIndexed::new(first_line as usize).unwrap_or(OneIndexed::MIN)
1734 } else {
1735 OneIndexed::MIN
1736 };
1737 let loc = SourceLocation {
1738 line,
1739 character_offset: OneIndexed::from_zero_indexed(0),
1740 };
1741 (loc, loc)
1742 };
1743 if linetable.is_empty() {
1744 return alloc::vec![default_loc(); num_instructions].into_boxed_slice();
1745 }
1746
1747 let mut locations = Vec::with_capacity(num_instructions);
1748 let mut pos = 0;
1749 let mut line = first_line;
1750
1751 while pos < linetable.len() && locations.len() < num_instructions {
1752 let first_byte = linetable[pos];
1753 pos += 1;
1754 if first_byte & 0x80 == 0 {
1755 break;
1756 }
1757 let code = (first_byte >> 3) & 0x0f;
1758 let length = ((first_byte & 0x07) + 1) as usize;
1759 let kind = match PyCodeLocationInfoKind::from_code(code) {
1760 Some(k) => k,
1761 None => break,
1762 };
1763
1764 let (line_delta, end_line_delta, col, end_col): (i32, i32, Option<u32>, Option<u32>) =
1765 match kind {
1766 PyCodeLocationInfoKind::None => (0, 0, None, None),
1767 PyCodeLocationInfoKind::Long => {
1768 let d = lt_read_signed_varint(linetable, &mut pos);
1769 let ed = lt_read_varint(linetable, &mut pos) as i32;
1770 let c = lt_read_varint(linetable, &mut pos);
1771 let ec = lt_read_varint(linetable, &mut pos);
1772 (
1773 d,
1774 ed,
1775 if c == 0 { None } else { Some(c - 1) },
1776 if ec == 0 { None } else { Some(ec - 1) },
1777 )
1778 }
1779 PyCodeLocationInfoKind::NoColumns => {
1780 (lt_read_signed_varint(linetable, &mut pos), 0, None, None)
1781 }
1782 PyCodeLocationInfoKind::OneLine0
1783 | PyCodeLocationInfoKind::OneLine1
1784 | PyCodeLocationInfoKind::OneLine2 => {
1785 let c = lt_byte(linetable, &mut pos) as u32;
1786 let ec = lt_byte(linetable, &mut pos) as u32;
1787 (kind.one_line_delta().unwrap_or(0), 0, Some(c), Some(ec))
1788 }
1789 _ if kind.is_short() => {
1790 let d = lt_byte(linetable, &mut pos);
1791 let g = kind.short_column_group().unwrap_or(0);
1792 let c = ((g as u32) << 3) | ((d >> 4) as u32);
1793 (0, 0, Some(c), Some(c + (d & 0x0f) as u32))
1794 }
1795 _ => (0, 0, None, None),
1796 };
1797
1798 line += line_delta;
1799 let mk = |l: i32| {
1800 if l > 0 {
1801 OneIndexed::new(l as usize).unwrap_or(OneIndexed::MIN)
1802 } else {
1803 OneIndexed::MIN
1804 }
1805 };
1806 for _ in 0..length {
1807 if locations.len() >= num_instructions {
1808 break;
1809 }
1810 if kind == PyCodeLocationInfoKind::None {
1811 let loc = SourceLocation {
1812 line: mk(line),
1813 character_offset: OneIndexed::from_zero_indexed(0),
1814 };
1815 locations.push((loc, loc));
1816 } else {
1817 locations.push((
1818 SourceLocation {
1819 line: mk(line),
1820 character_offset: OneIndexed::from_zero_indexed(col.unwrap_or(0) as usize),
1821 },
1822 SourceLocation {
1823 line: mk(line + end_line_delta),
1824 character_offset: OneIndexed::from_zero_indexed(
1825 end_col.unwrap_or(0) as usize
1826 ),
1827 },
1828 ));
1829 }
1830 }
1831 }
1832 while locations.len() < num_instructions {
1833 locations.push(default_loc());
1834 }
1835 locations.into_boxed_slice()
1836}
1837
1838fn lt_byte(data: &[u8], pos: &mut usize) -> u8 {
1839 if *pos < data.len() {
1840 let b = data[*pos];
1841 *pos += 1;
1842 b
1843 } else {
1844 0
1845 }
1846}
1847
1848fn lt_read_varint(data: &[u8], pos: &mut usize) -> u32 {
1850 let mut result: u32 = 0;
1851 let mut shift = 0;
1852 loop {
1853 if *pos >= data.len() {
1854 break;
1855 }
1856 let b = data[*pos];
1857 *pos += 1;
1858 result |= ((b & 0x3f) as u32) << shift;
1859 shift += 6;
1860 if b & 0x40 == 0 {
1861 break;
1862 }
1863 }
1864 result
1865}
1866
1867fn lt_read_signed_varint(data: &[u8], pos: &mut usize) -> i32 {
1868 let val = lt_read_varint(data, pos);
1869 if val & 1 != 0 {
1870 -((val >> 1) as i32)
1871 } else {
1872 (val >> 1) as i32
1873 }
1874}
1875
1876#[cfg(test)]
1877mod tests {
1878 use super::*;
1879 use crate::bytecode::{BasicBag, ConstantData};
1880
1881 fn hex_to_bytes(hex: &str) -> Vec<u8> {
1882 (0..hex.len())
1883 .step_by(2)
1884 .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
1885 .collect()
1886 }
1887
1888 fn decode_code(hex: &str) -> CodeObject<ConstantData> {
1889 let bytes = hex_to_bytes(hex);
1890 let value = deserialize_value(&mut &bytes[..], BasicBag).expect("decode failed");
1891 match value {
1892 ConstantData::Code { code } => *code,
1893 other => panic!("expected Code, got {other:?}"),
1894 }
1895 }
1896
1897 fn decode_tuple(hex: &str) -> Vec<ConstantData> {
1898 let bytes = hex_to_bytes(hex);
1899 let value = deserialize_value(&mut &bytes[..], BasicBag).expect("decode failed");
1900 match value {
1901 ConstantData::Tuple { elements } => elements,
1902 other => panic!("expected Tuple, got {other:?}"),
1903 }
1904 }
1905
1906 #[test]
1910 fn cpython_314_trivial_assignment() {
1911 let hex = "e30000000000000000000000000100000000000000f30a00000080005e017400520123002902\
1912 e9010000004e2901da0178a900f300000000da033c743eda083c6d6f64756c653e72070000000100\
1913 0000730a000000f003010101d8040582017205000000";
1914 let code = decode_code(hex);
1915 assert_eq!(code.obj_name.as_str(), "<module>");
1916 assert_eq!(code.qualname.as_str(), "<module>");
1917 assert_eq!(code.source_path.as_str(), "<t>");
1918 assert_eq!(code.arg_count, 0);
1919 assert_eq!(code.max_stackdepth, 1);
1920 assert_eq!(code.names.len(), 1);
1921 assert_eq!(code.names[0].as_str(), "x");
1922 assert_eq!(code.constants.len(), 2);
1923 let consts: &[ConstantData] = &code.constants;
1925 assert!(matches!(
1926 consts[0],
1927 ConstantData::Integer { ref value } if *value == 1.into(),
1928 ));
1929 assert!(matches!(consts[1], ConstantData::None));
1930 }
1931
1932 #[test]
1936 fn cpython_314_nested_code_and_string_const() {
1937 let hex = "e30000000000000000000000000100000000000000f310000000800052001700740052017401\
1938 520223002903630200000000000000000000000200000003000000f3120000008000570\
1939 12c0000000000000000000000230029014ea9002902da0161da016273020000002626da033c743e\
1940 da0361646472070000000200000073090000008000d80b0c8d35804cf300000000da0568656c6c\
1941 6f4e29027207000000da084752454554494e47720300000072080000007206000000da083c6d6f\
1942 64756c653e720b000000010000007311000000f003010101f204010111f006000c1382087208000000";
1943 let code = decode_code(hex);
1944 assert_eq!(code.obj_name.as_str(), "<module>");
1945 assert_eq!(code.names.len(), 2);
1946 assert_eq!(code.names[0].as_str(), "add");
1947 assert_eq!(code.names[1].as_str(), "GREETING");
1948 assert_eq!(code.constants.len(), 3);
1949 let consts: &[ConstantData] = &code.constants;
1951 let inner = match &consts[0] {
1952 ConstantData::Code { code } => code,
1953 other => panic!("expected nested Code, got {other:?}"),
1954 };
1955 assert_eq!(inner.obj_name.as_str(), "add");
1956 assert_eq!(inner.qualname.as_str(), "add");
1957 assert_eq!(inner.arg_count, 2);
1958 assert_eq!(inner.varnames.len(), 2);
1959 assert_eq!(inner.varnames[0].as_str(), "a");
1960 assert_eq!(inner.varnames[1].as_str(), "b");
1961 assert!(matches!(
1962 consts[1],
1963 ConstantData::Str { ref value } if value.as_str().ok() == Some("hello"),
1964 ));
1965 assert!(matches!(consts[2], ConstantData::None));
1966 }
1967
1968 #[test]
1973 fn cpython_314_code_inside_tuple_preserves_ref_indexes() {
1974 let hex = "a901630000000000000000000000000100000000000000f30a00000080005e017400\
1975 520123002902e9010000004e2901da0178a900f300000000da033c743eda083c6d6f\
1976 64756c653e720700000001000000730a000000f003010101d8040582017205000000";
1977 let tuple = decode_tuple(hex);
1978 assert_eq!(tuple.len(), 1);
1979 let code = match &tuple[0] {
1980 ConstantData::Code { code } => code,
1981 other => panic!("expected nested Code, got {other:?}"),
1982 };
1983 assert_eq!(code.obj_name.as_str(), "<module>");
1984 assert_eq!(code.qualname.as_str(), "<module>");
1985 assert_eq!(code.source_path.as_str(), "<t>");
1986 assert_eq!(code.names.len(), 1);
1987 assert_eq!(code.names[0].as_str(), "x");
1988 assert_eq!(code.constants.len(), 2);
1989 }
1990}