1use core::fmt;
2
3use crate::{
4 bytecode::{CodeUnit, instruction::Instruction},
5 marshal::MarshalError,
6};
7
8pub trait OpArgType: Copy + Into<u32> + TryFrom<u32> {}
9
10#[derive(Copy, Clone, PartialEq, Eq)]
12#[repr(transparent)]
13pub struct OpArgByte(u8);
14
15impl OpArgByte {
16 pub const NULL: Self = Self::new(0);
17
18 #[must_use]
19 pub const fn new(value: u8) -> Self {
20 Self(value)
21 }
22}
23
24impl From<u8> for OpArgByte {
25 fn from(raw: u8) -> Self {
26 Self::new(raw)
27 }
28}
29
30impl From<OpArgByte> for u8 {
31 fn from(value: OpArgByte) -> Self {
32 value.0
33 }
34}
35
36impl fmt::Debug for OpArgByte {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 self.0.fmt(f)
39 }
40}
41
42#[derive(Copy, Clone, Debug)]
44#[repr(transparent)]
45pub struct OpArg(u32);
46
47impl OpArg {
48 pub const NULL: Self = Self::new(0);
49
50 #[must_use]
51 pub const fn new(value: u32) -> Self {
52 Self(value)
53 }
54
55 #[inline]
57 pub const fn instr_size(self) -> usize {
58 (self.0 > 0xff) as usize + (self.0 > 0xff_ff) as usize + (self.0 > 0xff_ff_ff) as usize + 1
59 }
60
61 #[inline(always)]
64 pub fn split(self) -> (impl ExactSizeIterator<Item = OpArgByte>, OpArgByte) {
65 let mut it = self
66 .0
67 .to_le_bytes()
68 .map(OpArgByte)
69 .into_iter()
70 .take(self.instr_size());
71 let lo = it.next().unwrap();
72 (it.rev(), lo)
73 }
74}
75
76impl From<u32> for OpArg {
77 fn from(raw: u32) -> Self {
78 Self::new(raw)
79 }
80}
81
82impl From<OpArg> for u32 {
83 fn from(value: OpArg) -> Self {
84 value.0
85 }
86}
87
88#[derive(Default, Copy, Clone)]
89#[repr(transparent)]
90pub struct OpArgState {
91 state: u32,
92}
93
94impl OpArgState {
95 #[inline(always)]
96 pub fn get(&mut self, ins: CodeUnit) -> (Instruction, OpArg) {
97 let arg = self.extend(ins.arg);
98 if !matches!(ins.op, Instruction::ExtendedArg) {
99 self.reset();
100 }
101 (ins.op, arg)
102 }
103
104 #[inline(always)]
105 pub fn extend(&mut self, arg: OpArgByte) -> OpArg {
106 self.state = (self.state << 8) | u32::from(arg.0);
107 self.state.into()
108 }
109
110 #[inline(always)]
111 pub const fn reset(&mut self) {
112 self.state = 0
113 }
114}
115
116macro_rules! oparg_enum {
147 (
148 $(#[$enum_meta:meta])*
149 $vis:vis enum $name:ident {
150 $(
151 $(#[$variant_meta:meta])*
152 $variant:ident = $value:literal $(| $alternatives:expr)*
153 ),* $(,)?
154 }
155 ) => {
156 $(#[$enum_meta])*
157 $vis enum $name {
158 $(
159 $(#[$variant_meta])*
160 $variant, )*
162 }
163
164 impl_oparg_enum!(
165 enum $name {
166 $(
167 $variant = $value $(| $alternatives)*,
168 )*
169 }
170 );
171 };
172}
173
174macro_rules! impl_oparg_enum {
175 (
176 enum $name:ident {
177 $(
178 $variant:ident = $value:literal $(| $alternatives:expr)*
179 ),* $(,)?
180 }
181 ) => {
182 impl TryFrom<u8> for $name {
183 type Error = $crate::marshal::MarshalError;
184
185 fn try_from(value: u8) -> Result<Self, Self::Error> {
186 Ok(match value {
187 $(
188 $value $(| $alternatives)* => Self::$variant,
189 )*
190 _ => return Err(Self::Error::InvalidBytecode),
191 })
192 }
193 }
194
195 impl TryFrom<u32> for $name {
196 type Error = $crate::marshal::MarshalError;
197
198 fn try_from(value: u32) -> Result<Self, Self::Error> {
199 u8::try_from(value)
200 .map_err(|_| Self::Error::InvalidBytecode)
201 .map(TryInto::try_into)?
202 }
203 }
204
205 impl From<$name> for u8 {
206 fn from(value: $name) -> Self {
207 match value {
208 $(
209 $name::$variant => $value,
210 )*
211 }
212 }
213 }
214
215 impl From<$name> for u32 {
216 fn from(value: $name) -> Self {
217 Self::from(u8::from(value))
218 }
219 }
220
221 impl OpArgType for $name {}
222 };
223}
224
225oparg_enum!(
226 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
232 pub enum ConvertValueOparg {
233 None = 0 | 255,
241 Str = 1,
248 Repr = 2,
255 Ascii = 3,
262 }
263);
264
265impl fmt::Display for ConvertValueOparg {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 let out = match self {
268 Self::Str => "1 (str)",
269 Self::Repr => "2 (repr)",
270 Self::Ascii => "3 (ascii)",
271 Self::None => "",
273 };
274
275 write!(f, "{out}")
276 }
277}
278
279pub type NameIdx = u32;
280
281impl OpArgType for u32 {}
282
283oparg_enum!(
284 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
286 pub enum RaiseKind {
287 BareRaise = 0,
291 Raise = 1,
294 RaiseCause = 2,
297 ReraiseFromStack = 3,
302 }
303);
304
305oparg_enum!(
306 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
308 pub enum IntrinsicFunction1 {
309 Print = 1,
311 ImportStar = 2,
313 StopIterationError = 3,
315 AsyncGenWrap = 4,
316 UnaryPositive = 5,
317 ListToTuple = 6,
319 TypeVar = 7,
321 ParamSpec = 8,
322 TypeVarTuple = 9,
323 SubscriptGeneric = 10,
325 TypeAlias = 11,
326 }
327);
328
329oparg_enum!(
330 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
332 pub enum IntrinsicFunction2 {
333 PrepReraiseStar = 1,
334 TypeVarWithBound = 2,
335 TypeVarWithConstraint = 3,
336 SetFunctionTypeParams = 4,
337 SetTypeparamDefault = 5,
339 }
340);
341
342bitflagset::bitflag! {
343 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
348 #[repr(u8)]
349 pub enum MakeFunctionFlag {
350 Defaults = 0,
351 KwOnlyDefaults = 1,
352 Annotations = 2,
353 Closure = 3,
354 Annotate = 4,
356 TypeParams = 5,
357 }
358}
359
360bitflagset::bitflagset! {
361 #[derive(Copy, Clone, PartialEq, Eq)]
362 pub struct MakeFunctionFlags(u8): MakeFunctionFlag
363}
364
365impl TryFrom<u32> for MakeFunctionFlag {
366 type Error = MarshalError;
367
368 fn try_from(value: u32) -> Result<Self, Self::Error> {
370 match value {
371 0x01 => Ok(Self::Defaults),
372 0x02 => Ok(Self::KwOnlyDefaults),
373 0x04 => Ok(Self::Annotations),
374 0x08 => Ok(Self::Closure),
375 0x10 => Ok(Self::Annotate),
376 0x20 => Ok(Self::TypeParams),
377 _ => Err(MarshalError::InvalidBytecode),
378 }
379 }
380}
381
382impl From<MakeFunctionFlag> for u32 {
383 fn from(flag: MakeFunctionFlag) -> Self {
385 1u32 << (flag as u32)
386 }
387}
388
389impl OpArgType for MakeFunctionFlag {}
390
391#[derive(Debug, Copy, Clone, PartialEq, Eq)]
395pub enum ComparisonOperator {
396 Less,
397 LessOrEqual,
398 Equal,
399 NotEqual,
400 Greater,
401 GreaterOrEqual,
402}
403
404impl TryFrom<u8> for ComparisonOperator {
405 type Error = MarshalError;
406 fn try_from(value: u8) -> Result<Self, Self::Error> {
407 Self::try_from(value as u32)
408 }
409}
410
411impl TryFrom<u32> for ComparisonOperator {
412 type Error = MarshalError;
413 fn try_from(value: u32) -> Result<Self, Self::Error> {
415 match value >> 5 {
416 0 => Ok(Self::Less),
417 1 => Ok(Self::LessOrEqual),
418 2 => Ok(Self::Equal),
419 3 => Ok(Self::NotEqual),
420 4 => Ok(Self::Greater),
421 5 => Ok(Self::GreaterOrEqual),
422 _ => Err(MarshalError::InvalidBytecode),
423 }
424 }
425}
426
427impl From<ComparisonOperator> for u8 {
428 fn from(value: ComparisonOperator) -> Self {
430 match value {
431 ComparisonOperator::Less => 0,
432 ComparisonOperator::LessOrEqual => 1 << 5,
433 ComparisonOperator::Equal => 2 << 5,
434 ComparisonOperator::NotEqual => 3 << 5,
435 ComparisonOperator::Greater => 4 << 5,
436 ComparisonOperator::GreaterOrEqual => 5 << 5,
437 }
438 }
439}
440
441impl From<ComparisonOperator> for u32 {
442 fn from(value: ComparisonOperator) -> Self {
443 Self::from(u8::from(value))
444 }
445}
446
447impl OpArgType for ComparisonOperator {}
448
449oparg_enum!(
450 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
463 pub enum BinaryOperator {
464 Add = 0,
466 And = 1,
468 FloorDivide = 2,
470 Lshift = 3,
472 MatrixMultiply = 4,
474 Multiply = 5,
476 Remainder = 6,
478 Or = 7,
480 Power = 8,
482 Rshift = 9,
484 Subtract = 10,
486 TrueDivide = 11,
488 Xor = 12,
490 InplaceAdd = 13,
492 InplaceAnd = 14,
494 InplaceFloorDivide = 15,
496 InplaceLshift = 16,
498 InplaceMatrixMultiply = 17,
500 InplaceMultiply = 18,
502 InplaceRemainder = 19,
504 InplaceOr = 20,
506 InplacePower = 21,
508 InplaceRshift = 22,
510 InplaceSubtract = 23,
512 InplaceTrueDivide = 24,
514 InplaceXor = 25,
516 Subscr = 26,
518 }
519);
520
521impl BinaryOperator {
522 #[must_use]
534 pub const fn as_inplace(self) -> Self {
535 match self {
536 Self::Add => Self::InplaceAdd,
537 Self::And => Self::InplaceAnd,
538 Self::FloorDivide => Self::InplaceFloorDivide,
539 Self::Lshift => Self::InplaceLshift,
540 Self::MatrixMultiply => Self::InplaceMatrixMultiply,
541 Self::Multiply => Self::InplaceMultiply,
542 Self::Remainder => Self::InplaceRemainder,
543 Self::Or => Self::InplaceOr,
544 Self::Power => Self::InplacePower,
545 Self::Rshift => Self::InplaceRshift,
546 Self::Subtract => Self::InplaceSubtract,
547 Self::TrueDivide => Self::InplaceTrueDivide,
548 Self::Xor => Self::InplaceXor,
549 _ => self,
550 }
551 }
552}
553
554impl fmt::Display for BinaryOperator {
555 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
556 let op = match self {
557 Self::Add => "+",
558 Self::And => "&",
559 Self::FloorDivide => "//",
560 Self::Lshift => "<<",
561 Self::MatrixMultiply => "@",
562 Self::Multiply => "*",
563 Self::Remainder => "%",
564 Self::Or => "|",
565 Self::Power => "**",
566 Self::Rshift => ">>",
567 Self::Subtract => "-",
568 Self::TrueDivide => "/",
569 Self::Xor => "^",
570 Self::InplaceAdd => "+=",
571 Self::InplaceAnd => "&=",
572 Self::InplaceFloorDivide => "//=",
573 Self::InplaceLshift => "<<=",
574 Self::InplaceMatrixMultiply => "@=",
575 Self::InplaceMultiply => "*=",
576 Self::InplaceRemainder => "%=",
577 Self::InplaceOr => "|=",
578 Self::InplacePower => "**=",
579 Self::InplaceRshift => ">>=",
580 Self::InplaceSubtract => "-=",
581 Self::InplaceTrueDivide => "/=",
582 Self::InplaceXor => "^=",
583 Self::Subscr => "[]",
584 };
585 write!(f, "{op}")
586 }
587}
588
589oparg_enum!(
590 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
592 pub enum Invert {
593 No = 0,
598 Yes = 1,
603 }
604);
605
606oparg_enum!(
607 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
609 pub enum SpecialMethod {
610 Enter = 0,
612 Exit = 1,
614 AEnter = 2,
616 AExit = 3,
618 }
619);
620
621impl fmt::Display for SpecialMethod {
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 let method_name = match self {
624 Self::Enter => "__enter__",
625 Self::Exit => "__exit__",
626 Self::AEnter => "__aenter__",
627 Self::AExit => "__aexit__",
628 };
629 write!(f, "{method_name}")
630 }
631}
632
633oparg_enum!(
634 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
637 pub enum CommonConstant {
638 AssertionError = 0,
640 NotImplementedError = 1,
642 BuiltinTuple = 2,
644 BuiltinAll = 3,
646 BuiltinAny = 4,
648 BuiltinList = 5,
650 BuiltinSet = 6,
652 }
653);
654
655impl fmt::Display for CommonConstant {
656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657 let name = match self {
658 Self::AssertionError => "AssertionError",
659 Self::NotImplementedError => "NotImplementedError",
660 Self::BuiltinTuple => "tuple",
661 Self::BuiltinAll => "all",
662 Self::BuiltinAny => "any",
663 Self::BuiltinList => "list",
664 Self::BuiltinSet => "set",
665 };
666 write!(f, "{name}")
667 }
668}
669
670oparg_enum!(
671 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
673 pub enum BuildSliceArgCount {
674 Two = 2,
678 Three = 3,
682 }
683);
684
685#[derive(Copy, Clone)]
686pub struct UnpackExArgs {
687 pub before: u8,
688 pub after: u8,
689}
690
691impl From<u32> for UnpackExArgs {
692 fn from(value: u32) -> Self {
693 let [before, after, ..] = value.to_le_bytes();
694 Self { before, after }
695 }
696}
697
698impl From<UnpackExArgs> for u32 {
699 fn from(value: UnpackExArgs) -> Self {
700 Self::from_le_bytes([value.before, value.after, 0, 0])
701 }
702}
703
704impl OpArgType for UnpackExArgs {}
705
706impl fmt::Display for UnpackExArgs {
707 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708 write!(f, "before: {}, after: {}", self.before, self.after)
709 }
710}
711
712macro_rules! newtype_oparg {
713 (
714 $(#[$oparg_meta:meta])*
715 $vis:vis struct $name:ident(u32)
716 ) => {
717 $(#[$oparg_meta])*
718 $vis struct $name(u32);
719
720 impl $name {
721 #[must_use]
723 pub const fn from_u32(value: u32) -> Self {
724 Self(value)
725 }
726
727 #[must_use]
729 pub const fn as_u32(self) -> u32 {
730 self.0
731 }
732
733 #[must_use]
735 pub const fn as_usize(self) -> usize {
736 self.0 as usize
737 }
738 }
739
740 impl From<u32> for $name {
741 fn from(value: u32) -> Self {
742 Self::from_u32(value)
743 }
744 }
745
746 impl From<$name> for u32 {
747 fn from(value: $name) -> Self {
748 value.as_u32()
749 }
750 }
751
752 impl From<$name> for usize {
753 fn from(value: $name) -> Self {
754 value.as_usize()
755 }
756 }
757
758 impl ::core::fmt::Display for $name {
759 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
760 self.0.fmt(f)
761 }
762 }
763
764 impl OpArgType for $name {}
765 }
766}
767
768newtype_oparg!(
769 #[derive(Clone, Copy)]
770 #[repr(transparent)]
771 pub struct ConstIdx(u32)
772);
773
774newtype_oparg!(
775 #[derive(Clone, Copy)]
776 #[repr(transparent)]
777 pub struct VarNum(u32)
778);
779
780newtype_oparg!(
781 #[derive(Clone, Copy)]
782 #[repr(transparent)]
783 pub struct VarNums(u32)
784);
785
786newtype_oparg!(
787 #[derive(Clone, Copy)]
788 #[repr(transparent)]
789 pub struct LoadAttr(u32)
790);
791
792newtype_oparg!(
793 #[derive(Clone, Copy)]
794 #[repr(transparent)]
795 pub struct LoadSuperAttr(u32)
796);
797
798newtype_oparg!(
799 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
800 #[repr(transparent)]
801 pub struct Label(u32)
802);
803
804newtype_oparg!(
805 #[derive(Clone, Copy)]
811 #[repr(transparent)]
812 pub struct ResumeContext(u32)
813);
814
815impl ResumeContext {
816 pub const LOCATION_MASK: u32 = 0x3;
818
819 pub const DEPTH1_MASK: u32 = 0x4;
821
822 #[must_use]
823 pub const fn new(location: ResumeLocation, is_exception_depth1: bool) -> Self {
824 let value = if is_exception_depth1 {
825 Self::DEPTH1_MASK
826 } else {
827 0
828 };
829
830 Self::from_u32(location.as_u32() | value)
831 }
832
833 #[must_use]
835 pub fn location(&self) -> ResumeLocation {
836 unsafe { ResumeLocation::try_from(self.as_u32() & Self::LOCATION_MASK).unwrap_unchecked() }
838 }
839
840 #[must_use]
842 pub const fn is_exception_depth1(&self) -> bool {
843 (self.as_u32() & Self::DEPTH1_MASK) != 0
844 }
845}
846
847#[derive(Copy, Clone)]
848pub enum ResumeLocation {
849 AtFuncStart,
851 AfterYield,
853 AfterYieldFrom,
855 AfterAwait,
857}
858
859impl From<ResumeLocation> for ResumeContext {
860 fn from(location: ResumeLocation) -> Self {
861 Self::new(location, false)
862 }
863}
864
865impl TryFrom<u32> for ResumeLocation {
866 type Error = MarshalError;
867
868 fn try_from(value: u32) -> Result<Self, Self::Error> {
869 Ok(match value {
870 0 => Self::AtFuncStart,
871 1 => Self::AfterYield,
872 2 => Self::AfterYieldFrom,
873 3 => Self::AfterAwait,
874 _ => return Err(Self::Error::InvalidBytecode),
875 })
876 }
877}
878
879impl ResumeLocation {
880 #[must_use]
881 pub const fn as_u8(&self) -> u8 {
882 match self {
883 Self::AtFuncStart => 0,
884 Self::AfterYield => 1,
885 Self::AfterYieldFrom => 2,
886 Self::AfterAwait => 3,
887 }
888 }
889
890 #[must_use]
891 pub const fn as_u32(&self) -> u32 {
892 self.as_u8() as u32
893 }
894}
895
896impl From<ResumeLocation> for u8 {
897 fn from(location: ResumeLocation) -> Self {
898 location.as_u8()
899 }
900}
901
902impl From<ResumeLocation> for u32 {
903 fn from(location: ResumeLocation) -> Self {
904 location.as_u32()
905 }
906}
907
908impl VarNums {
909 #[must_use]
910 pub const fn idx_1(self) -> VarNum {
911 VarNum::from_u32(self.0 >> 4)
912 }
913
914 #[must_use]
915 pub const fn idx_2(self) -> VarNum {
916 VarNum::from_u32(self.0 & 15)
917 }
918
919 #[must_use]
920 pub const fn indexes(self) -> (VarNum, VarNum) {
921 (self.idx_1(), self.idx_2())
922 }
923}
924
925impl LoadAttr {
926 #[must_use]
927 pub const fn new(name_idx: u32, is_method: bool) -> Self {
928 Self::from_u32((name_idx << 1) | (is_method as u32))
929 }
930
931 #[must_use]
932 pub const fn name_idx(self) -> u32 {
933 self.0 >> 1
934 }
935
936 #[must_use]
937 pub const fn is_method(self) -> bool {
938 (self.0 & 1) == 1
939 }
940}
941
942impl LoadSuperAttr {
943 #[must_use]
944 pub const fn new(name_idx: u32, is_load_method: bool, has_class: bool) -> Self {
945 Self::from_u32((name_idx << 2) | (is_load_method as u32) | ((has_class as u32) << 1))
946 }
947
948 #[must_use]
949 pub const fn name_idx(self) -> u32 {
950 self.0 >> 2
951 }
952
953 #[must_use]
954 pub const fn is_load_method(self) -> bool {
955 (self.0 & 1) == 1
956 }
957
958 #[must_use]
959 pub const fn has_class(self) -> bool {
960 (self.0 & 2) == 2
961 }
962}