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