1use core::fmt;
2
3use crate::{
4 bytecode::{CodeUnit, 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 #[must_use]
25 pub const fn as_u8(self) -> u8 {
26 self.0
27 }
28
29 #[must_use]
31 pub const fn as_u32(self) -> u32 {
32 self.0 as u32
33 }
34}
35
36impl From<u8> for OpArgByte {
37 fn from(raw: u8) -> Self {
38 Self::new(raw)
39 }
40}
41
42impl From<OpArgByte> for u8 {
43 fn from(value: OpArgByte) -> Self {
44 value.as_u8()
45 }
46}
47
48impl fmt::Debug for OpArgByte {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 self.0.fmt(f)
51 }
52}
53
54#[derive(Copy, Clone, Debug)]
56#[repr(transparent)]
57pub struct OpArg(u32);
58
59impl OpArg {
60 pub const NULL: Self = Self::new(0);
61
62 #[must_use]
63 pub const fn new(value: u32) -> Self {
64 Self(value)
65 }
66
67 #[inline]
69 #[must_use]
70 pub const fn instr_size(self) -> usize {
71 (self.0 > 0xff) as usize + (self.0 > 0xff_ff) as usize + (self.0 > 0xff_ff_ff) as usize + 1
72 }
73
74 #[inline(always)]
77 pub fn split(self) -> (impl ExactSizeIterator<Item = OpArgByte>, OpArgByte) {
78 let mut it = self
79 .0
80 .to_le_bytes()
81 .map(OpArgByte)
82 .into_iter()
83 .take(self.instr_size());
84 let lo = it.next().unwrap();
85 (it.rev(), lo)
86 }
87}
88
89impl From<u32> for OpArg {
90 fn from(raw: u32) -> Self {
91 Self::new(raw)
92 }
93}
94
95impl From<OpArg> for u32 {
96 fn from(value: OpArg) -> Self {
97 value.0
98 }
99}
100
101#[derive(Default, Copy, Clone)]
102#[repr(transparent)]
103pub struct OpArgState {
104 state: u32,
105}
106
107impl OpArgState {
108 #[inline(always)]
109 pub const fn get(&mut self, ins: CodeUnit) -> (Instruction, OpArg) {
110 let arg = self.extend(ins.arg);
111 if !matches!(ins.op, Instruction::ExtendedArg) {
112 self.reset();
113 }
114 (ins.op, arg)
115 }
116
117 #[inline(always)]
118 pub const fn extend(&mut self, arg: OpArgByte) -> OpArg {
119 self.state = (self.state << 8) | arg.as_u32();
120 OpArg::new(self.state)
121 }
122
123 #[inline(always)]
124 pub const fn reset(&mut self) {
125 self.state = 0
126 }
127}
128
129macro_rules! oparg_enum {
177 (
178 $(#[$enum_meta:meta])*
179 $vis:vis enum $name:ident {
180 $(
181 $(#[$variant_meta:meta])*
182 $variant:ident = $value:tt
183 ),* $(,)?
184 }
185 ) => {
186 $(#[$enum_meta])*
187 $vis enum $name {
188 $(
189 $(#[$variant_meta])*
190 $variant, )*
192 }
193
194 impl_oparg_enum!(
195 $vis enum $name {
196 $(
197 $variant = $value,
198 )*
199 }
200 );
201 };
202}
203
204macro_rules! impl_oparg_enum {
205 (
206 $vis:vis enum $name:ident {
207 $(
208 $variant:ident = $value:tt
209 ),* $(,)?
210 }
211 ) => {
212 impl $name {
213 #[must_use]
215 $vis const fn as_u8(self) -> u8 {
216 match self {
217 $(
218 Self::$variant => impl_oparg_enum!(@discriminant $value),
219 )*
220 }
221 }
222
223 #[must_use]
225 $vis const fn as_u32(self) -> u32 {
226 self.as_u8() as u32
227 }
228
229 $vis const fn try_from_u8(value: u8) -> Result<Self, $crate::marshal::MarshalError> {
230 Ok(match value {
231 $(
232 impl_oparg_enum!(@discriminant $value) => Self::$variant,
233 )*
234 _ => return Err($crate::marshal::MarshalError::InvalidBytecode),
235 })
236 }
237
238 $vis const fn try_from_u32(value: u32) -> Result<Self, $crate::marshal::MarshalError> {
239 if value > (u8::MAX as u32) {
240 return Err($crate::marshal::MarshalError::InvalidBytecode);
241 }
242
243 Self::try_from_u8(value as u8)
245 }
246
247 $vis fn iter() -> impl Iterator<Item = Self> {
249 [$(Self::$variant),*].iter().copied()
250 }
251 }
252
253 impl TryFrom<u8> for $name {
254 type Error = $crate::marshal::MarshalError;
255
256 fn try_from(value: u8) -> Result<Self, Self::Error> {
257 Self::try_from_u8(value)
258 }
259 }
260
261 impl TryFrom<u32> for $name {
262 type Error = $crate::marshal::MarshalError;
263
264 fn try_from(value: u32) -> Result<Self, Self::Error> {
265 Self::try_from_u32(value)
266 }
267 }
268
269 impl From<$name> for u8 {
270 fn from(value: $name) -> Self {
271 value.as_u8()
272 }
273 }
274
275 impl From<$name> for u32 {
276 fn from(value: $name) -> Self {
277 value.as_u32()
278 }
279 }
280
281 impl ::core::fmt::Display for $name {
282 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
283 match self {
284 $(
285 Self::$variant => impl_oparg_enum!(@display f, $value),
286 )*
287 }
288 }
289 }
290
291 impl OpArgType for $name {}
292 };
293
294 (@discriminant ($num:literal, $str:literal)) => { $num };
295 (@discriminant $num:literal) => { $num };
296 (@display $f:expr, ($num:literal, $str:literal)) => {
297 ::core::fmt::Display::fmt($str, $f)
298 };
299 (@display $f:expr, $num:literal) => {
300 ::core::fmt::Display::fmt(&$num, $f)
301 };
302}
303
304oparg_enum!(
305 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
311 pub enum ConvertValueOparg {
312 None = 0,
321 Str = (1, "str"),
328 Repr = (2, "repr"),
335 Ascii = (3, "ascii"),
342 }
343);
344
345pub type NameIdx = u32;
346
347impl OpArgType for u32 {}
348
349oparg_enum!(
350 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
352 pub enum RaiseKind {
353 BareRaise = 0,
357 Raise = 1,
360 RaiseCause = 2,
363 ReraiseFromStack = 3,
368 }
369);
370
371oparg_enum!(
372 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
374 pub enum IntrinsicFunction1 {
375 Invalid = 0,
376 Print = 1,
377 ImportStar = 2,
379 StopIterationError = 3,
381 AsyncGenWrap = 4,
382 UnaryPositive = 5,
383 ListToTuple = 6,
385 TypeVar = 7,
387 ParamSpec = 8,
388 TypeVarTuple = 9,
389 SubscriptGeneric = 10,
391 TypeAlias = 11,
392 }
393);
394
395impl IntrinsicFunction1 {
396 #[must_use]
398 pub const fn desc(&self) -> &str {
399 match self {
400 Self::Invalid => "INTRINSIC_1_INVALID",
401 Self::Print => "INTRINSIC_PRINT",
402 Self::ImportStar => "INTRINSIC_IMPORT_STAR",
403 Self::StopIterationError => "INTRINSIC_STOPITERATION_ERROR",
404 Self::AsyncGenWrap => "INTRINSIC_ASYNC_GEN_WRAP",
405 Self::UnaryPositive => "INTRINSIC_UNARY_POSITIVE",
406 Self::ListToTuple => "INTRINSIC_LIST_TO_TUPLE",
407 Self::TypeVar => "INTRINSIC_TYPEVAR",
408 Self::ParamSpec => "INTRINSIC_PARAMSPEC",
409 Self::TypeVarTuple => "INTRINSIC_TYPEVARTUPLE",
410 Self::SubscriptGeneric => "INTRINSIC_SUBSCRIPT_GENERIC",
411 Self::TypeAlias => "INTRINSIC_TYPEALIAS",
412 }
413 }
414}
415
416oparg_enum!(
417 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
419 pub enum IntrinsicFunction2 {
420 Invalid = 0,
421 PrepReraiseStar = 1,
422 TypeVarWithBound = 2,
423 TypeVarWithConstraint = 3,
424 SetFunctionTypeParams = 4,
425 SetTypeparamDefault = 5,
427 }
428);
429
430impl IntrinsicFunction2 {
431 #[must_use]
433 pub const fn desc(&self) -> &str {
434 match self {
435 Self::Invalid => "INTRINSIC_2_INVALID",
436 Self::PrepReraiseStar => "INTRINSIC_PREP_RERAISE_STAR",
437 Self::TypeVarWithBound => "INTRINSIC_TYPEVAR_WITH_BOUND",
438 Self::TypeVarWithConstraint => "INTRINSIC_TYPEVAR_WITH_CONSTRAINTS",
439 Self::SetFunctionTypeParams => "INTRINSIC_SET_FUNCTION_TYPE_PARAMS",
440 Self::SetTypeparamDefault => "INTRINSIC_SET_TYPEPARAM_DEFAULT",
441 }
442 }
443}
444
445bitflagset::bitflag! {
446 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
451 #[repr(u8)]
452 pub enum MakeFunctionFlag {
453 Defaults = 0,
454 KwOnlyDefaults = 1,
455 Annotations = 2,
456 Closure = 3,
457 Annotate = 4,
459 TypeParams = 5,
460 }
461}
462
463bitflagset::bitflagset! {
464 #[derive(Copy, Clone, PartialEq, Eq)]
465 pub struct MakeFunctionFlags(u8): MakeFunctionFlag
466}
467
468impl TryFrom<u32> for MakeFunctionFlag {
469 type Error = MarshalError;
470
471 fn try_from(value: u32) -> Result<Self, Self::Error> {
473 match value {
474 0x01 => Ok(Self::Defaults),
475 0x02 => Ok(Self::KwOnlyDefaults),
476 0x04 => Ok(Self::Annotations),
477 0x08 => Ok(Self::Closure),
478 0x10 => Ok(Self::Annotate),
479 0x20 => Ok(Self::TypeParams),
480 _ => Err(MarshalError::InvalidBytecode),
481 }
482 }
483}
484
485impl From<MakeFunctionFlag> for u32 {
486 fn from(flag: MakeFunctionFlag) -> Self {
488 1u32 << (flag as Self)
489 }
490}
491
492impl OpArgType for MakeFunctionFlag {}
493
494pub const COMPARE_OP_BOOL_MASK: u32 = 1 << 4;
499
500#[derive(Debug, Copy, Clone, PartialEq, Eq)]
501pub enum ComparisonOperator {
502 Less,
503 LessOrEqual,
504 Equal,
505 NotEqual,
506 Greater,
507 GreaterOrEqual,
508}
509
510impl TryFrom<u8> for ComparisonOperator {
511 type Error = MarshalError;
512 fn try_from(value: u8) -> Result<Self, Self::Error> {
513 Self::try_from(value as u32)
514 }
515}
516
517impl TryFrom<u32> for ComparisonOperator {
518 type Error = MarshalError;
519 fn try_from(value: u32) -> Result<Self, Self::Error> {
521 match value >> 5 {
522 0 => Ok(Self::Less),
523 1 => Ok(Self::LessOrEqual),
524 2 => Ok(Self::Equal),
525 3 => Ok(Self::NotEqual),
526 4 => Ok(Self::Greater),
527 5 => Ok(Self::GreaterOrEqual),
528 _ => Err(MarshalError::InvalidBytecode),
529 }
530 }
531}
532
533impl From<ComparisonOperator> for u8 {
534 fn from(value: ComparisonOperator) -> Self {
536 match value {
537 ComparisonOperator::Less => 2,
538 ComparisonOperator::LessOrEqual => (1 << 5) | 2 | 8,
539 ComparisonOperator::Equal => (2 << 5) | 8,
540 ComparisonOperator::NotEqual => (3 << 5) | 1 | 2 | 4,
541 ComparisonOperator::Greater => (4 << 5) | 4,
542 ComparisonOperator::GreaterOrEqual => (5 << 5) | 4 | 8,
543 }
544 }
545}
546
547impl From<ComparisonOperator> for u32 {
548 fn from(value: ComparisonOperator) -> Self {
549 Self::from(u8::from(value))
550 }
551}
552
553impl OpArgType for ComparisonOperator {}
554
555impl fmt::Display for ComparisonOperator {
556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557 let op = match self {
558 Self::Less => "<",
559 Self::LessOrEqual => "<=",
560 Self::Equal => "==",
561 Self::NotEqual => "!=",
562 Self::Greater => ">",
563 Self::GreaterOrEqual => ">=",
564 };
565 f.write_str(op)
566 }
567}
568
569oparg_enum!(
570 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
583 pub enum BinaryOperator {
584 Add = (0, "+"),
586 And = (1, "&"),
588 FloorDivide = (2, "//"),
590 Lshift = (3, "<<"),
592 MatrixMultiply = (4, "@"),
594 Multiply = (5, "*"),
596 Remainder = (6, "%"),
598 Or = (7, "|"),
600 Power = (8, "**"),
602 Rshift = (9, ">>"),
604 Subtract = (10, "-"),
606 TrueDivide = (11, "/"),
608 Xor = (12, "^"),
610 InplaceAdd = (13, "+="),
612 InplaceAnd = (14, "&="),
614 InplaceFloorDivide = (15, "//="),
616 InplaceLshift = (16, "<<="),
618 InplaceMatrixMultiply = (17, "@="),
620 InplaceMultiply = (18, "*="),
622 InplaceRemainder = (19, "%="),
624 InplaceOr = (20, "|="),
626 InplacePower = (21, "**="),
628 InplaceRshift = (22, ">>="),
630 InplaceSubtract = (23, "-="),
632 InplaceTrueDivide = (24, "/="),
634 InplaceXor = (25, "^="),
636 Subscr = (26, "[]"),
638 }
639);
640
641impl BinaryOperator {
642 #[must_use]
654 pub const fn as_inplace(self) -> Self {
655 match self {
656 Self::Add => Self::InplaceAdd,
657 Self::And => Self::InplaceAnd,
658 Self::FloorDivide => Self::InplaceFloorDivide,
659 Self::Lshift => Self::InplaceLshift,
660 Self::MatrixMultiply => Self::InplaceMatrixMultiply,
661 Self::Multiply => Self::InplaceMultiply,
662 Self::Remainder => Self::InplaceRemainder,
663 Self::Or => Self::InplaceOr,
664 Self::Power => Self::InplacePower,
665 Self::Rshift => Self::InplaceRshift,
666 Self::Subtract => Self::InplaceSubtract,
667 Self::TrueDivide => Self::InplaceTrueDivide,
668 Self::Xor => Self::InplaceXor,
669 _ => self,
670 }
671 }
672
673 #[must_use]
675 pub const fn desc(&self) -> &str {
676 match self {
677 Self::Add => "NB_ADD",
678 Self::And => "NB_AND",
679 Self::FloorDivide => "NB_FLOOR_DIVIDE",
680 Self::Lshift => "NB_LSHIFT",
681 Self::MatrixMultiply => "NB_MATRIX_MULTIPLY",
682 Self::Multiply => "NB_MULTIPLY",
683 Self::Remainder => "NB_REMAINDER",
684 Self::Or => "NB_OR",
685 Self::Power => "NB_POWER",
686 Self::Rshift => "NB_RSHIFT",
687 Self::Subtract => "NB_SUBTRACT",
688 Self::TrueDivide => "NB_TRUE_DIVIDE",
689 Self::Xor => "NB_XOR",
690 Self::InplaceAdd => "NB_INPLACE_ADD",
691 Self::InplaceAnd => "NB_INPLACE_AND",
692 Self::InplaceFloorDivide => "NB_INPLACE_FLOOR_DIVIDE",
693 Self::InplaceLshift => "NB_INPLACE_LSHIFT",
694 Self::InplaceMatrixMultiply => "NB_INPLACE_MATRIX_MULTIPLY",
695 Self::InplaceMultiply => "NB_INPLACE_MULTIPLY",
696 Self::InplaceRemainder => "NB_INPLACE_REMAINDER",
697 Self::InplaceOr => "NB_INPLACE_OR",
698 Self::InplacePower => "NB_INPLACE_POWER",
699 Self::InplaceRshift => "NB_INPLACE_RSHIFT",
700 Self::InplaceSubtract => "NB_INPLACE_SUBTRACT",
701 Self::InplaceTrueDivide => "NB_INPLACE_TRUE_DIVIDE",
702 Self::InplaceXor => "NB_INPLACE_XOR",
703 Self::Subscr => "NB_SUBSCR",
704 }
705 }
706}
707
708oparg_enum!(
709 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
711 pub enum Invert {
712 No = 0,
717 Yes = 1,
722 }
723);
724
725oparg_enum!(
726 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
728 pub enum SpecialMethod {
729 Enter = (0, "__enter__"),
731 Exit = (1, "__exit__"),
733 AEnter = (2, "__aenter__"),
735 AExit = (3, "__aexit__"),
737 }
738);
739
740oparg_enum!(
741 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
744 pub enum CommonConstant {
745 AssertionError = (0, "AssertionError"),
747 NotImplementedError = (1, "NotImplementedError"),
749 BuiltinTuple = (2, "tuple"),
751 BuiltinAll = (3, "all"),
753 BuiltinAny = (4, "any"),
755 BuiltinList = (5, "list"),
757 BuiltinSet = (6, "set"),
759 }
760);
761
762oparg_enum!(
763 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
765 pub enum BuildSliceArgCount {
766 Two = 2,
770 Three = 3,
774 }
775);
776
777#[derive(Copy, Clone)]
778pub struct UnpackExArgs {
779 pub before: u8,
780 pub after: u32,
781}
782
783impl From<u32> for UnpackExArgs {
784 fn from(value: u32) -> Self {
785 let before = (value & 0xFF) as u8;
786 let after = value >> 8;
787 Self { before, after }
788 }
789}
790
791impl From<UnpackExArgs> for u32 {
792 fn from(value: UnpackExArgs) -> Self {
793 Self::from(value.before) | (value.after << 8)
794 }
795}
796
797impl OpArgType for UnpackExArgs {}
798
799impl fmt::Display for UnpackExArgs {
800 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
801 write!(f, "before: {}, after: {}", self.before, self.after)
802 }
803}
804
805macro_rules! newtype_oparg {
806 (
807 $(#[$oparg_meta:meta])*
808 $vis:vis struct $name:ident(u32)
809 ) => {
810 $(#[$oparg_meta])*
811 $vis struct $name(u32);
812
813 impl $name {
814 #[doc = concat!("Creates a new [`", stringify!($name), "`] instance.")]
815 #[must_use]
816 pub const fn from_u32(value: u32) -> Self {
817 Self(value)
818 }
819
820 #[must_use]
822 pub const fn as_u32(self) -> u32 {
823 self.0
824 }
825
826 #[must_use]
828 pub const fn as_usize(self) -> usize {
829 self.0 as usize
830 }
831 }
832
833 impl From<u32> for $name {
834 fn from(value: u32) -> Self {
835 Self::from_u32(value)
836 }
837 }
838
839 impl From<$name> for u32 {
840 fn from(value: $name) -> Self {
841 value.as_u32()
842 }
843 }
844
845 impl From<$name> for usize {
846 fn from(value: $name) -> Self {
847 value.as_usize()
848 }
849 }
850
851 impl ::core::fmt::Display for $name {
852 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
853 self.0.fmt(f)
854 }
855 }
856
857 impl OpArgType for $name {}
858 }
859}
860
861newtype_oparg!(
862 #[derive(Clone, Copy)]
863 #[repr(transparent)]
864 pub struct ConstIdx(u32)
865);
866
867newtype_oparg!(
868 #[derive(Clone, Copy)]
869 #[repr(transparent)]
870 pub struct VarNum(u32)
871);
872
873newtype_oparg!(
874 #[derive(Clone, Copy)]
875 #[repr(transparent)]
876 pub struct VarNums(u32)
877);
878
879newtype_oparg!(
880 #[derive(Clone, Copy)]
881 #[repr(transparent)]
882 pub struct LoadAttr(u32)
883);
884
885newtype_oparg!(
886 #[derive(Clone, Copy)]
887 #[repr(transparent)]
888 pub struct LoadSuperAttr(u32)
889);
890
891newtype_oparg!(
892 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
893 #[repr(transparent)]
894 pub struct Label(u32)
895);
896
897newtype_oparg!(
898 #[derive(Clone, Copy)]
904 #[repr(transparent)]
905 pub struct ResumeContext(u32)
906);
907
908impl ResumeContext {
909 pub const LOCATION_MASK: u32 = 0x3;
911
912 pub const DEPTH1_MASK: u32 = 0x4;
914
915 #[must_use]
916 pub const fn new(location: ResumeLocation, is_exception_depth1: bool) -> Self {
917 let value = if is_exception_depth1 {
918 Self::DEPTH1_MASK
919 } else {
920 0
921 };
922
923 Self::from_u32(location.as_u32() | value)
924 }
925
926 #[must_use]
928 pub fn location(&self) -> ResumeLocation {
929 unsafe { ResumeLocation::try_from(self.as_u32() & Self::LOCATION_MASK).unwrap_unchecked() }
931 }
932
933 #[must_use]
935 pub const fn is_exception_depth1(&self) -> bool {
936 (self.as_u32() & Self::DEPTH1_MASK) != 0
937 }
938}
939
940#[derive(Copy, Clone)]
941pub enum ResumeLocation {
942 AtFuncStart,
944 AfterYield,
946 AfterYieldFrom,
948 AfterAwait,
950}
951
952impl From<ResumeLocation> for ResumeContext {
953 fn from(location: ResumeLocation) -> Self {
954 Self::new(location, false)
955 }
956}
957
958impl TryFrom<u32> for ResumeLocation {
959 type Error = MarshalError;
960
961 fn try_from(value: u32) -> Result<Self, Self::Error> {
962 Ok(match value {
963 0 => Self::AtFuncStart,
964 1 => Self::AfterYield,
965 2 => Self::AfterYieldFrom,
966 3 => Self::AfterAwait,
967 _ => return Err(Self::Error::InvalidBytecode),
968 })
969 }
970}
971
972impl ResumeLocation {
973 #[must_use]
974 pub const fn as_u8(&self) -> u8 {
975 match self {
976 Self::AtFuncStart => 0,
977 Self::AfterYield => 1,
978 Self::AfterYieldFrom => 2,
979 Self::AfterAwait => 3,
980 }
981 }
982
983 #[must_use]
984 pub const fn as_u32(&self) -> u32 {
985 self.as_u8() as u32
986 }
987}
988
989impl From<ResumeLocation> for u8 {
990 fn from(location: ResumeLocation) -> Self {
991 location.as_u8()
992 }
993}
994
995impl From<ResumeLocation> for u32 {
996 fn from(location: ResumeLocation) -> Self {
997 location.as_u32()
998 }
999}
1000
1001impl VarNums {
1002 #[must_use]
1003 pub const fn idx_1(self) -> VarNum {
1004 VarNum::from_u32(self.0 >> 4)
1005 }
1006
1007 #[must_use]
1008 pub const fn idx_2(self) -> VarNum {
1009 VarNum::from_u32(self.0 & 15)
1010 }
1011
1012 #[must_use]
1013 pub const fn indexes(self) -> (VarNum, VarNum) {
1014 (self.idx_1(), self.idx_2())
1015 }
1016}
1017
1018impl LoadAttr {
1019 #[must_use]
1020 pub const fn new(name_idx: u32, is_method: bool) -> Self {
1021 Self::from_u32((name_idx << 1) | (is_method as u32))
1022 }
1023
1024 #[must_use]
1025 pub const fn name_idx(self) -> u32 {
1026 self.0 >> 1
1027 }
1028
1029 #[must_use]
1030 pub const fn is_method(self) -> bool {
1031 (self.0 & 1) == 1
1032 }
1033}
1034
1035impl LoadSuperAttr {
1036 #[must_use]
1037 pub const fn new(name_idx: u32, is_load_method: bool, has_class: bool) -> Self {
1038 Self::from_u32((name_idx << 2) | (is_load_method as u32) | ((has_class as u32) << 1))
1039 }
1040
1041 #[must_use]
1042 pub const fn name_idx(self) -> u32 {
1043 self.0 >> 2
1044 }
1045
1046 #[must_use]
1047 pub const fn is_load_method(self) -> bool {
1048 (self.0 & 1) == 1
1049 }
1050
1051 #[must_use]
1052 pub const fn has_class(self) -> bool {
1053 (self.0 & 2) == 2
1054 }
1055}