Skip to main content

datex_core/global/protocol_structures/
instructions.rs

1use crate::{
2    global::{
3        operators::AssignmentOperator,
4        type_instruction_codes::TypeReferenceMutabilityCode,
5    },
6    values::core_values::{
7        decimal::{Decimal, utils::decimal_to_string},
8        endpoint::{Endpoint, EndpointParsingError},
9        integer::Integer,
10    },
11};
12
13use crate::{
14    global::type_instruction_codes::{TypeLocalOrShared, TypeMutabilityCode},
15    prelude::*,
16    shared_values::pointer_address::{
17        PointerAddress, ReferencedPointerAddress,
18    },
19    values::core_values::r#type::TypeMetadata,
20};
21use binrw::{BinRead, BinWrite};
22use core::{fmt::Display, prelude::rust_2024::*};
23use modular_bitfield::{bitfield, specifiers::B4};
24use serde::{Deserialize, Serialize};
25
26#[derive(Clone, Debug, PartialEq)]
27pub enum Instruction {
28    // regular instruction
29    RegularInstruction(RegularInstruction),
30    // Type instruction that yields a type
31    TypeInstruction(TypeInstruction),
32}
33
34impl Display for Instruction {
35    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36        match self {
37            Instruction::RegularInstruction(instr) => {
38                core::write!(f, "{}", instr)
39            }
40            Instruction::TypeInstruction(instr) => {
41                core::write!(f, "TYPE_INSTRUCTION {}", instr)
42            }
43        }
44    }
45}
46
47impl From<RegularInstruction> for Instruction {
48    fn from(instruction: RegularInstruction) -> Self {
49        Instruction::RegularInstruction(instruction)
50    }
51}
52
53impl From<TypeInstruction> for Instruction {
54    fn from(instruction: TypeInstruction) -> Self {
55        Instruction::TypeInstruction(instruction)
56    }
57}
58
59#[derive(Clone, Debug, PartialEq)]
60pub enum RegularInstruction {
61    // signed integers
62    Int8(Int8Data),
63    Int16(Int16Data),
64    Int32(Int32Data),
65    Int64(Int64Data),
66    Int128(Int128Data),
67
68    // unsigned integers
69    UInt8(UInt8Data),
70    UInt16(UInt16Data),
71    UInt32(UInt32Data),
72    UInt64(UInt64Data),
73    UInt128(UInt128Data),
74
75    // big integers
76    BigInteger(IntegerData),
77
78    // default integer
79    Integer(IntegerData),
80    Range,
81
82    Endpoint(Endpoint),
83
84    DecimalF32(Float32Data),
85    DecimalF64(Float64Data),
86    DecimalAsInt16(FloatAsInt16Data),
87    DecimalAsInt32(FloatAsInt32Data),
88    BigDecimal(DecimalData),
89    // default decimal
90    Decimal(DecimalData),
91
92    RemoteExecution(InstructionBlockData),
93
94    ShortText(ShortTextData),
95    Text(TextData),
96    True,
97    False,
98    Null,
99    Statements(StatementsData),
100    ShortStatements(StatementsData),
101    UnboundedStatements,
102    UnboundedStatementsEnd(bool),
103    List(ListData),
104    ShortList(ListData),
105    Map(MapData),
106    ShortMap(MapData),
107
108    KeyValueDynamic,
109    KeyValueShortText(ShortTextData),
110
111    // binary operator
112    Add,
113    Subtract,
114    Multiply,
115    Divide,
116
117    // unary operator
118    // TODO #432 add missing unary operators
119    UnaryMinus,
120    // TODO #433: Do we need this for op overloading or can we avoid?
121    UnaryPlus,
122    BitwiseNot,
123
124    Apply(ApplyData),
125
126    GetPropertyText(ShortTextData),
127    SetPropertyText(ShortTextData),
128    SetPropertyDynamic,
129
130    GetPropertyIndex(UInt32Data),
131    SetPropertyIndex(UInt32Data),
132    GetPropertyDynamic,
133
134    // comparison operator
135    Is,
136    Matches,
137    StructuralEqual,
138    Equal,
139    NotStructuralEqual,
140    NotEqual,
141
142    // assignment operator
143    AddAssign(SlotAddress),
144    SubtractAssign(SlotAddress),
145    MultiplyAssign(SlotAddress),
146    DivideAssign(SlotAddress),
147
148    CreateSharedReference,
149
150    CreateShared,
151    CreateSharedMut,
152
153    // ' $ABCDE
154    GetSharedRef(RawRemotePointerAddress),
155    // 'mut $ABCDE
156    GetSharedRefMut(RawRemotePointerAddress),
157    GetLocalRef(RawLocalPointerAddress),
158    GetInternalRef(RawInternalPointerAddress),
159
160    // &ABCDE := ...
161    GetOrCreateRef(GetOrCreateRemoteRefData),
162    // &mut ABCDE := ...
163    GetOrCreateRefMut(GetOrCreateRemoteRefData),
164
165    AllocateSlot(SlotAddress),
166    GetSlot(SlotAddress),
167    DropSlot(SlotAddress),
168    SetSlot(SlotAddress),
169
170    GetInternalSlot(SlotAddress),
171
172    SetReferenceValue(AssignmentOperator),
173    Unbox,
174
175    TypedValue,
176    TypeExpression,
177}
178
179impl Display for RegularInstruction {
180    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181        match self {
182            RegularInstruction::Int8(data) => {
183                core::write!(f, "INT_8 {}", data.0)
184            }
185            RegularInstruction::Int16(data) => {
186                core::write!(f, "INT_16 {}", data.0)
187            }
188            RegularInstruction::Int32(data) => {
189                core::write!(f, "INT_32 {}", data.0)
190            }
191            RegularInstruction::Int64(data) => {
192                core::write!(f, "INT_64 {}", data.0)
193            }
194            RegularInstruction::Int128(data) => {
195                core::write!(f, "INT_128 {}", data.0)
196            }
197
198            RegularInstruction::UInt8(data) => {
199                core::write!(f, "UINT_8 {}", data.0)
200            }
201            RegularInstruction::UInt16(data) => {
202                core::write!(f, "UINT_16 {}", data.0)
203            }
204            RegularInstruction::UInt32(data) => {
205                core::write!(f, "UINT_32 {}", data.0)
206            }
207            RegularInstruction::UInt64(data) => {
208                core::write!(f, "UINT_64 {}", data.0)
209            }
210            RegularInstruction::UInt128(data) => {
211                core::write!(f, "UINT_128 {}", data.0)
212            }
213            RegularInstruction::Range => {
214                core::write!(f, "RANGE regular instruction")
215            }
216            RegularInstruction::Apply(count) => {
217                core::write!(f, "APPLY {}", count.arg_count)
218            }
219            RegularInstruction::BigInteger(data) => {
220                core::write!(f, "BIG_INTEGER {}", data.0)
221            }
222            RegularInstruction::Integer(data) => {
223                core::write!(f, "INTEGER {}", data.0)
224            }
225            RegularInstruction::Endpoint(data) => {
226                core::write!(f, "ENDPOINT {data}")
227            }
228
229            RegularInstruction::DecimalAsInt16(data) => {
230                core::write!(f, "DECIMAL_AS_INT_16 {}", data.0)
231            }
232            RegularInstruction::DecimalAsInt32(data) => {
233                core::write!(f, "DECIMAL_AS_INT_32 {}", data.0)
234            }
235            RegularInstruction::DecimalF32(data) => {
236                core::write!(
237                    f,
238                    "DECIMAL_F32 {}",
239                    decimal_to_string(data.0, false)
240                )
241            }
242            RegularInstruction::DecimalF64(data) => {
243                core::write!(
244                    f,
245                    "DECIMAL_F64 {}",
246                    decimal_to_string(data.0, false)
247                )
248            }
249            RegularInstruction::BigDecimal(data) => {
250                core::write!(f, "DECIMAL_BIG {}", data.0)
251            }
252            RegularInstruction::Decimal(data) => {
253                core::write!(f, "DECIMAL {}", data.0)
254            }
255            RegularInstruction::ShortText(data) => {
256                core::write!(f, "SHORT_TEXT {}", data.0)
257            }
258            RegularInstruction::Text(data) => {
259                core::write!(f, "TEXT {}", data.0)
260            }
261            RegularInstruction::True => core::write!(f, "TRUE"),
262            RegularInstruction::False => core::write!(f, "FALSE"),
263            RegularInstruction::Null => core::write!(f, "NULL"),
264            RegularInstruction::Statements(data) => {
265                core::write!(f, "STATEMENTS {}", data.statements_count)
266            }
267            RegularInstruction::ShortStatements(data) => {
268                core::write!(f, "SHORT_STATEMENTS {}", data.statements_count)
269            }
270            RegularInstruction::UnboundedStatements => {
271                core::write!(f, "UNBOUNDED_STATEMENTS")
272            }
273            RegularInstruction::UnboundedStatementsEnd(_) => {
274                core::write!(f, "STATEMENTS_END")
275            }
276            RegularInstruction::List(data) => {
277                core::write!(f, "LIST {}", data.element_count)
278            }
279            RegularInstruction::ShortList(data) => {
280                core::write!(f, "SHORT_LIST {}", data.element_count)
281            }
282            RegularInstruction::Map(data) => {
283                core::write!(f, "MAP {}", data.element_count)
284            }
285            RegularInstruction::ShortMap(data) => {
286                core::write!(f, "SHORT_MAP {}", data.element_count)
287            }
288            RegularInstruction::KeyValueDynamic => {
289                core::write!(f, "KEY_VALUE_DYNAMIC")
290            }
291            RegularInstruction::KeyValueShortText(data) => {
292                core::write!(f, "KEY_VALUE_SHORT_TEXT {}", data.0)
293            }
294            // operations
295            RegularInstruction::Add => core::write!(f, "ADD"),
296            RegularInstruction::Subtract => core::write!(f, "SUBTRACT"),
297            RegularInstruction::Multiply => core::write!(f, "MULTIPLY"),
298            RegularInstruction::Divide => core::write!(f, "DIVIDE"),
299
300            // equality checks
301            RegularInstruction::StructuralEqual => {
302                core::write!(f, "STRUCTURAL_EQUAL")
303            }
304            RegularInstruction::Equal => core::write!(f, "EQUAL"),
305            RegularInstruction::NotStructuralEqual => {
306                core::write!(f, "NOT_STRUCTURAL_EQUAL")
307            }
308            RegularInstruction::NotEqual => core::write!(f, "NOT_EQUAL"),
309            RegularInstruction::Is => core::write!(f, "IS"),
310            RegularInstruction::Matches => core::write!(f, "MATCHES"),
311
312            RegularInstruction::AllocateSlot(address) => {
313                core::write!(f, "ALLOCATE_SLOT {}", address.0)
314            }
315            RegularInstruction::GetSlot(address) => {
316                core::write!(f, "GET_SLOT {}", address.0)
317            }
318            RegularInstruction::GetInternalSlot(address) => {
319                core::write!(f, "GET_INTERNAL_SLOT {}", address.0)
320            }
321            RegularInstruction::DropSlot(address) => {
322                core::write!(f, "DROP_SLOT {}", address.0)
323            }
324            RegularInstruction::SetSlot(address) => {
325                core::write!(f, "SET_SLOT {}", address.0)
326            }
327            RegularInstruction::SetReferenceValue(operator) => {
328                core::write!(f, "SET_REFERENCE_VALUE ({})", operator)
329            }
330            RegularInstruction::Unbox => core::write!(f, "UNBOX"),
331            RegularInstruction::GetSharedRef(address) => {
332                core::write!(
333                    f,
334                    "GET_SHARED_REF [{}:{}]",
335                    address.endpoint().expect("Invalid endpoint"),
336                    hex::encode(address.id)
337                )
338            }
339            RegularInstruction::GetSharedRefMut(address) => {
340                core::write!(
341                    f,
342                    "GET_SHARED_REF_MUT [{}:{}]",
343                    address.endpoint().expect("Invalid endpoint"),
344                    hex::encode(address.id)
345                )
346            }
347            RegularInstruction::GetLocalRef(address) => {
348                core::write!(
349                    f,
350                    "GET_LOCAL_REF [origin_id: {}]",
351                    hex::encode(address.id)
352                )
353            }
354            RegularInstruction::GetInternalRef(address) => {
355                core::write!(
356                    f,
357                    "GET_INTERNAL_REF [internal_id: {}]",
358                    hex::encode(address.id)
359                )
360            }
361            RegularInstruction::CreateSharedReference => {
362                core::write!(f, "CREATE_SHARED_REF")
363            }
364            RegularInstruction::CreateShared => {
365                core::write!(f, "CREATE_SHARED")
366            }
367            RegularInstruction::CreateSharedMut => {
368                core::write!(f, "CREATE_SHARED_MUT")
369            }
370            RegularInstruction::GetOrCreateRef(data) => {
371                core::write!(
372                    f,
373                    "GET_OR_CREATE_REF [{}, block_size: {}]",
374                    hex::encode(data.address.id),
375                    data.create_block_size
376                )
377            }
378            RegularInstruction::GetOrCreateRefMut(data) => {
379                core::write!(
380                    f,
381                    "GET_OR_CREATE_REF_MUT [{}, block_size: {}]",
382                    hex::encode(data.address.id),
383                    data.create_block_size
384                )
385            }
386            RegularInstruction::RemoteExecution(block) => {
387                core::write!(
388                    f,
389                    "REMOTE_EXECUTION (length: {}, injected_slot_count: {})",
390                    block.length,
391                    block.injected_slot_count
392                )
393            }
394            RegularInstruction::AddAssign(address) => {
395                core::write!(f, "ADD_ASSIGN {}", address.0)
396            }
397            RegularInstruction::SubtractAssign(address) => {
398                core::write!(f, "SUBTRACT_ASSIGN {}", address.0)
399            }
400            RegularInstruction::MultiplyAssign(address) => {
401                core::write!(f, "MULTIPLY_ASSIGN {}", address.0)
402            }
403            RegularInstruction::DivideAssign(address) => {
404                core::write!(f, "DIVIDE_ASSIGN {}", address.0)
405            }
406            RegularInstruction::UnaryMinus => core::write!(f, "-"),
407            RegularInstruction::UnaryPlus => core::write!(f, "+"),
408            RegularInstruction::BitwiseNot => core::write!(f, "BITWISE_NOT"),
409            RegularInstruction::TypedValue => core::write!(f, "TYPED_VALUE"),
410            RegularInstruction::TypeExpression => {
411                core::write!(f, "TYPE_EXPRESSION")
412            }
413            RegularInstruction::GetPropertyIndex(uint_32_data) => {
414                core::write!(f, "GET_PROPERTY_INDEX {}", uint_32_data.0)
415            }
416            RegularInstruction::SetPropertyIndex(uint_32_data) => {
417                core::write!(f, "SET_PROPERTY_INDEX {}", uint_32_data.0)
418            }
419            RegularInstruction::GetPropertyText(short_text_data) => {
420                core::write!(f, "GET_PROPERTY_TEXT {}", short_text_data.0)
421            }
422            RegularInstruction::SetPropertyText(short_text_data) => {
423                core::write!(f, "SET_PROPERTY_TEXT {}", short_text_data.0)
424            }
425            RegularInstruction::GetPropertyDynamic => {
426                core::write!(f, "GET_PROPERTY_DYNAMIC")
427            }
428            RegularInstruction::SetPropertyDynamic => {
429                core::write!(f, "SET_PROPERTY_DYNAMIC")
430            }
431        }
432    }
433}
434
435#[derive(Clone, Debug, PartialEq)]
436pub enum TypeInstruction {
437    ImplType(ImplTypeData),
438    SharedTypeReference(TypeReferenceData),
439    LiteralText(TextData),
440    LiteralInteger(IntegerData),
441    List(ListData),
442    Range, // TODO #670: add more type instructions
443}
444
445impl Display for TypeInstruction {
446    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
447        match self {
448            TypeInstruction::LiteralText(data) => {
449                core::write!(f, "LITERAL_TEXT {}", data.0)
450            }
451            TypeInstruction::LiteralInteger(data) => {
452                core::write!(f, "LITERAL_INTEGER {}", data.0)
453            }
454            TypeInstruction::List(data) => {
455                core::write!(f, "LIST {}", data.element_count)
456            }
457            TypeInstruction::SharedTypeReference(reference_data) => {
458                core::write!(
459                    f,
460                    "TYPE_REFERENCE mutability: {:?}, address: {}",
461                    TypeMetadata::from(&reference_data.metadata),
462                    PointerAddress::from(&reference_data.address)
463                )
464            }
465            TypeInstruction::ImplType(data) => {
466                core::write!(f, "IMPL_TYPE ({} impls)", data.impl_count)
467            }
468            TypeInstruction::Range => {
469                core::write!(f, "Range type instruction")
470            }
471        }
472    }
473}
474
475#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
476#[brw(little)]
477pub struct Int8Data(pub i8);
478
479#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
480#[brw(little)]
481pub struct Int16Data(pub i16);
482
483#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
484#[brw(little)]
485pub struct Int32Data(pub i32);
486
487#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
488#[brw(little)]
489pub struct Int64Data(pub i64);
490
491#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
492#[brw(little)]
493pub struct Int128Data(pub i128);
494
495#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
496#[brw(little)]
497pub struct UInt8Data(pub u8);
498
499#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
500#[brw(little)]
501pub struct UInt16Data(pub u16);
502
503#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
504#[brw(little)]
505pub struct UInt32Data(pub u32);
506
507#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
508#[brw(little)]
509pub struct UInt64Data(pub u64);
510
511#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
512#[brw(little)]
513pub struct UInt128Data(pub u128);
514
515#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
516#[brw(little)]
517pub struct Float32Data(pub f32);
518
519#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
520#[brw(little)]
521pub struct Float64Data(pub f64);
522
523#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
524#[brw(little)]
525pub struct FloatAsInt16Data(pub i16);
526
527#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
528#[brw(little)]
529pub struct FloatAsInt32Data(pub i32);
530
531#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
532#[brw(little)]
533pub struct DecimalData(pub Decimal);
534
535#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
536#[brw(little)]
537pub struct IntegerData(pub Integer);
538
539#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
540#[brw(little)]
541pub struct ShortTextDataRaw {
542    pub length: u8,
543    #[br(count = length)]
544    pub text: Vec<u8>,
545}
546
547#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
548#[brw(little)]
549pub struct TextDataRaw {
550    pub length: u32,
551    #[br(count = length)]
552    pub text: Vec<u8>,
553}
554
555#[derive(Clone, Debug, PartialEq)]
556pub struct ShortTextData(pub String);
557
558#[derive(Clone, Debug, PartialEq)]
559pub struct TextData(pub String);
560
561#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
562#[brw(little)]
563pub struct ShortListData {
564    pub element_count: u8,
565}
566
567#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
568#[brw(little)]
569pub struct StatementsData {
570    pub statements_count: u32,
571    #[br(map = |x: u8| x != 0)]
572    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
573    pub terminated: bool,
574}
575
576#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
577#[brw(little)]
578pub struct UnboundedStatementsData {
579    #[br(map = |x: u8| x != 0)]
580    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
581    pub terminated: bool,
582}
583
584#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
585#[brw(little)]
586pub struct ShortStatementsData {
587    pub statements_count: u8,
588    #[br(map = |x: u8| x != 0)]
589    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
590    pub terminated: bool,
591}
592
593#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
594#[brw(little)]
595pub struct ListData {
596    pub element_count: u32,
597}
598
599#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
600#[brw(little)]
601pub struct ShortMapData {
602    pub element_count: u8,
603}
604
605#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
606#[brw(little)]
607pub struct MapData {
608    pub element_count: u32,
609}
610
611#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
612#[brw(little)]
613pub struct InstructionCloseAndStore {
614    pub instruction: Int8Data,
615}
616
617#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
618#[brw(little)]
619pub struct SlotAddress(pub u32);
620
621#[derive(
622    BinRead, BinWrite, Clone, Debug, PartialEq, Serialize, Deserialize,
623)]
624#[brw(little)]
625pub struct RawRemotePointerAddress {
626    pub id: [u8; 26],
627}
628impl RawRemotePointerAddress {
629    pub fn endpoint(&self) -> Result<Endpoint, EndpointParsingError> {
630        let mut endpoint = [0u8; 21];
631        endpoint.copy_from_slice(&self.id[0..21]);
632        Endpoint::from_slice(endpoint)
633    }
634}
635
636#[derive(Debug, Clone, PartialEq)]
637pub struct PointerAddressConversionError;
638
639impl TryFrom<PointerAddress> for RawRemotePointerAddress {
640    type Error = PointerAddressConversionError;
641    fn try_from(ptr: PointerAddress) -> Result<Self, Self::Error> {
642        match ptr {
643            PointerAddress::Referenced(ReferencedPointerAddress::Remote(
644                bytes,
645            )) => Ok(RawRemotePointerAddress { id: bytes }),
646            _ => Err(PointerAddressConversionError),
647        }
648    }
649}
650
651#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
652#[brw(little)]
653pub struct RawLocalPointerAddress {
654    pub id: [u8; 5],
655}
656
657#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
658#[brw(little)]
659pub struct RawInternalPointerAddress {
660    pub id: [u8; 3],
661}
662
663#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
664#[brw(little)]
665pub enum RawPointerAddress {
666    #[br(magic = 120u8)] // InstructionCode::GET_REMOTE_SHARED_REF
667    Remote(RawRemotePointerAddress),
668    #[br(magic = 121u8)] // InstructionCode::GET_INTERNAL_SHARED_REF
669    Internal(RawInternalPointerAddress),
670    #[br(magic = 122u8)] // InstructionCode::GET_LOCAL_SHARED_REF
671    Local(RawLocalPointerAddress),
672}
673
674#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
675#[brw(little)]
676pub struct GetOrCreateRemoteRefData {
677    pub address: RawRemotePointerAddress,
678    pub create_block_size: u64,
679}
680
681#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
682#[brw(little)]
683pub struct InstructionBlockData {
684    pub length: u32,
685    pub injected_slot_count: u32,
686    #[br(count = injected_slot_count)]
687    pub injected_slots: Vec<u32>,
688    #[br(count = length)]
689    pub body: Vec<u8>,
690}
691
692#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
693#[brw(little)]
694pub struct ApplyData {
695    pub arg_count: u16,
696}
697
698#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
699#[brw(little)]
700pub struct ImplTypeData {
701    pub metadata: TypeMetadataBin,
702    pub impl_count: u8,
703    #[br(count = impl_count)]
704    pub impls: Vec<RawPointerAddress>,
705}
706
707#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
708#[brw(little)]
709pub struct TypeReferenceData {
710    pub metadata: TypeMetadataBin,
711    pub address: RawPointerAddress,
712}
713
714#[bitfield]
715#[derive(BinWrite, BinRead, Clone, Copy, Debug, PartialEq)]
716#[bw(map = |&x| Self::into_bytes(x))]
717#[br(map = Self::from_bytes)]
718#[brw(little)]
719pub struct TypeMetadataBin {
720    pub reference_mutability: TypeReferenceMutabilityCode,
721    pub mutability: TypeMutabilityCode,
722    pub type_local_or_shared: TypeLocalOrShared,
723    _unused: B4,
724}
725
726impl From<&TypeMetadataBin> for TypeMetadata {
727    fn from(value: &TypeMetadataBin) -> Self {
728        match value.type_local_or_shared() {
729            TypeLocalOrShared::Local => TypeMetadata::Local {
730                mutability: (&value.mutability()).into(),
731                reference_mutability: (&value.reference_mutability()).into(),
732            },
733            TypeLocalOrShared::Shared => TypeMetadata::Shared {
734                mutability: (&value.mutability()).into(),
735                reference_mutability: (&value.reference_mutability()).into(),
736            },
737        }
738    }
739}
740
741impl From<&TypeMetadata> for TypeMetadataBin {
742    fn from(value: &TypeMetadata) -> Self {
743        match value {
744            TypeMetadata::Local {
745                mutability,
746                reference_mutability,
747            } => Self::new()
748                .with_type_local_or_shared(TypeLocalOrShared::Local)
749                .with_mutability(mutability.into())
750                .with_reference_mutability(reference_mutability.into()),
751            TypeMetadata::Shared {
752                mutability,
753                reference_mutability,
754            } => Self::new()
755                .with_type_local_or_shared(TypeLocalOrShared::Shared)
756                .with_mutability(mutability.into())
757                .with_reference_mutability(reference_mutability.into()),
758        }
759    }
760}