Skip to main content

macho_core/model/
load_command.rs

1use crate::format::constants::*;
2use crate::model::addr::ThinFileOffset;
3use std::fmt;
4
5#[derive(Debug, Clone)]
6/// The ParsedLoadCommand type.
7pub struct ParsedLoadCommand {
8    pub(crate) kind: LoadCommand,
9    pub(crate) file_offset: ThinFileOffset,
10    pub(crate) raw_size: u32,
11}
12
13impl ParsedLoadCommand {
14    /// Parsed command payload.
15    pub fn kind(&self) -> &LoadCommand {
16        &self.kind
17    }
18    /// Slice-relative byte offset of the command header.
19    pub const fn file_offset(&self) -> ThinFileOffset {
20        self.file_offset
21    }
22    /// Validated command size in bytes.
23    pub const fn raw_size(&self) -> u32 {
24        self.raw_size
25    }
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
29/// The LoadCommand type.
30pub enum LoadCommand {
31    /// The Segment32 variant.
32    Segment32(SegmentCommandData),
33    /// The Segment64 variant.
34    Segment64(SegmentCommandData),
35    /// The Symtab variant.
36    Symtab(SymtabData),
37    /// The Dysymtab variant.
38    Dysymtab(DysymtabData),
39    /// The DyldInfo variant.
40    DyldInfo(DyldInfoData),
41    /// The DyldInfoOnly variant.
42    DyldInfoOnly(DyldInfoData),
43    /// The DyldExportsTrie variant.
44    DyldExportsTrie(LinkeditData),
45    /// The DyldChainedFixups variant.
46    DyldChainedFixups(LinkeditData),
47    /// The Main variant.
48    Main(EntryPointData),
49    /// The Uuid variant.
50    Uuid(UuidData),
51    /// The BuildVersion variant.
52    BuildVersion(BuildVersionData),
53    /// The SourceVersion variant.
54    SourceVersion(SourceVersionData),
55    /// The VersionMinMacOS variant.
56    VersionMinMacOS(VersionMinData),
57    /// The VersionMinIOS variant.
58    VersionMinIOS(VersionMinData),
59    /// The VersionMinTvOS variant.
60    VersionMinTvOS(VersionMinData),
61    /// The VersionMinWatchOS variant.
62    VersionMinWatchOS(VersionMinData),
63    /// The IdDylib variant.
64    IdDylib(DylibData),
65    /// The LoadDylib variant.
66    LoadDylib(DylibData),
67    /// The LoadWeakDylib variant.
68    LoadWeakDylib(DylibData),
69    /// The ReexportDylib variant.
70    ReexportDylib(DylibData),
71    /// The LazyLoadDylib variant.
72    LazyLoadDylib(DylibData),
73    /// The LoadUpwardDylib variant.
74    LoadUpwardDylib(DylibData),
75    /// The Rpath variant.
76    Rpath(StringData),
77    /// The TargetTriple variant.
78    TargetTriple(StringData),
79    /// The IdDylinker variant.
80    IdDylinker(StringData),
81    /// The LoadDylinker variant.
82    LoadDylinker(StringData),
83    /// The DyldEnvironment variant.
84    DyldEnvironment(StringData),
85    /// The SubFramework variant.
86    SubFramework(StringData),
87    /// The SubUmbrella variant.
88    SubUmbrella(StringData),
89    /// The SubClient variant.
90    SubClient(StringData),
91    /// The SubLibrary variant.
92    SubLibrary(StringData),
93    /// The CodeSignature variant.
94    CodeSignature(LinkeditData),
95    /// The SegmentSplitInfo variant.
96    SegmentSplitInfo(LinkeditData),
97    /// The FunctionStarts variant.
98    FunctionStarts(LinkeditData),
99    /// The DataInCode variant.
100    DataInCode(LinkeditData),
101    /// The DylibCodeSignDrs variant.
102    DylibCodeSignDrs(LinkeditData),
103    /// The LinkerOptimizationHint variant.
104    LinkerOptimizationHint(LinkeditData),
105    /// The AtomInfo variant.
106    AtomInfo(LinkeditData),
107    /// The FunctionVariants variant.
108    FunctionVariants(LinkeditData),
109    /// The FunctionVariantFixups variant.
110    FunctionVariantFixups(LinkeditData),
111    /// The EncryptionInfo variant.
112    EncryptionInfo(EncryptionInfoData),
113    /// The EncryptionInfo64 variant.
114    EncryptionInfo64(EncryptionInfoData),
115    /// The LinkerOption variant.
116    LinkerOption(LinkerOptionData),
117    /// The Note variant.
118    Note(NoteData),
119    /// The FilesetEntry variant.
120    FilesetEntry(FilesetEntryData),
121    /// The PrebindCksum variant.
122    PrebindCksum(PrebindCksumData),
123    /// The TwolevelHints variant.
124    TwolevelHints(TwolevelHintsData),
125    /// The Routines variant.
126    Routines(RoutinesData),
127    /// The Routines64 variant.
128    Routines64(RoutinesData),
129    /// The Thread variant.
130    Thread(RawData),
131    /// The UnixThread variant.
132    UnixThread(RawData),
133    /// The PreboundDylib variant.
134    PreboundDylib(RawData),
135    /// The Ident variant.
136    Ident(RawData),
137    /// The Unknown variant.
138    Unknown(UnknownLoadCommand),
139}
140
141impl LoadCommand {
142    /// Performs name.
143    pub fn name(&self) -> &'static str {
144        match self {
145            Self::Segment32(_) => "LC_SEGMENT",
146            Self::Segment64(_) => "LC_SEGMENT_64",
147            Self::Symtab(_) => "LC_SYMTAB",
148            Self::Dysymtab(_) => "LC_DYSYMTAB",
149            Self::DyldInfo(_) => "LC_DYLD_INFO",
150            Self::DyldInfoOnly(_) => "LC_DYLD_INFO_ONLY",
151            Self::DyldExportsTrie(_) => "LC_DYLD_EXPORTS_TRIE",
152            Self::DyldChainedFixups(_) => "LC_DYLD_CHAINED_FIXUPS",
153            Self::Main(_) => "LC_MAIN",
154            Self::Uuid(_) => "LC_UUID",
155            Self::BuildVersion(_) => "LC_BUILD_VERSION",
156            Self::SourceVersion(_) => "LC_SOURCE_VERSION",
157            Self::VersionMinMacOS(_) => "LC_VERSION_MIN_MACOSX",
158            Self::VersionMinIOS(_) => "LC_VERSION_MIN_IPHONEOS",
159            Self::VersionMinTvOS(_) => "LC_VERSION_MIN_TVOS",
160            Self::VersionMinWatchOS(_) => "LC_VERSION_MIN_WATCHOS",
161            Self::IdDylib(_) => "LC_ID_DYLIB",
162            Self::LoadDylib(_) => "LC_LOAD_DYLIB",
163            Self::LoadWeakDylib(_) => "LC_LOAD_WEAK_DYLIB",
164            Self::ReexportDylib(_) => "LC_REEXPORT_DYLIB",
165            Self::LazyLoadDylib(_) => "LC_LAZY_LOAD_DYLIB",
166            Self::LoadUpwardDylib(_) => "LC_LOAD_UPWARD_DYLIB",
167            Self::Rpath(_) => "LC_RPATH",
168            Self::TargetTriple(_) => "LC_TARGET_TRIPLE",
169            Self::IdDylinker(_) => "LC_ID_DYLINKER",
170            Self::LoadDylinker(_) => "LC_LOAD_DYLINKER",
171            Self::DyldEnvironment(_) => "LC_DYLD_ENVIRONMENT",
172            Self::SubFramework(_) => "LC_SUB_FRAMEWORK",
173            Self::SubUmbrella(_) => "LC_SUB_UMBRELLA",
174            Self::SubClient(_) => "LC_SUB_CLIENT",
175            Self::SubLibrary(_) => "LC_SUB_LIBRARY",
176            Self::CodeSignature(_) => "LC_CODE_SIGNATURE",
177            Self::SegmentSplitInfo(_) => "LC_SEGMENT_SPLIT_INFO",
178            Self::FunctionStarts(_) => "LC_FUNCTION_STARTS",
179            Self::DataInCode(_) => "LC_DATA_IN_CODE",
180            Self::DylibCodeSignDrs(_) => "LC_DYLIB_CODE_SIGN_DRS",
181            Self::LinkerOptimizationHint(_) => "LC_LINKER_OPTIMIZATION_HINT",
182            Self::AtomInfo(_) => "LC_ATOM_INFO",
183            Self::FunctionVariants(_) => "LC_FUNCTION_VARIANTS",
184            Self::FunctionVariantFixups(_) => "LC_FUNCTION_VARIANT_FIXUPS",
185            Self::EncryptionInfo(_) => "LC_ENCRYPTION_INFO",
186            Self::EncryptionInfo64(_) => "LC_ENCRYPTION_INFO_64",
187            Self::LinkerOption(_) => "LC_LINKER_OPTION",
188            Self::Note(_) => "LC_NOTE",
189            Self::FilesetEntry(_) => "LC_FILESET_ENTRY",
190            Self::PrebindCksum(_) => "LC_PREBIND_CKSUM",
191            Self::TwolevelHints(_) => "LC_TWOLEVEL_HINTS",
192            Self::Routines(_) => "LC_ROUTINES",
193            Self::Routines64(_) => "LC_ROUTINES_64",
194            Self::Thread(_) => "LC_THREAD",
195            Self::UnixThread(_) => "LC_UNIXTHREAD",
196            Self::PreboundDylib(_) => "LC_PREBOUND_DYLIB",
197            Self::Ident(_) => "LC_IDENT",
198            Self::Unknown(_) => "LC_UNKNOWN",
199        }
200    }
201
202    /// Performs summary.
203    pub fn summary(&self) -> String {
204        match self {
205            Self::Segment32(d) | Self::Segment64(d) => {
206                format!("segment_index={}", d.segment_index)
207            }
208            Self::Uuid(d) => format_uuid(&d.uuid),
209            Self::BuildVersion(d) => {
210                format!("{} {}", d.platform.name(), d.minos)
211            }
212            Self::Main(d) => format!("entry_offset={:#x}", d.entry_offset),
213            Self::SourceVersion(d) => format!("{}", d.version),
214            Self::LoadDylib(d)
215            | Self::LoadWeakDylib(d)
216            | Self::ReexportDylib(d)
217            | Self::LazyLoadDylib(d)
218            | Self::LoadUpwardDylib(d)
219            | Self::IdDylib(d) => d.name.clone(),
220            Self::Rpath(d)
221            | Self::TargetTriple(d)
222            | Self::LoadDylinker(d)
223            | Self::IdDylinker(d)
224            | Self::DyldEnvironment(d)
225            | Self::SubFramework(d)
226            | Self::SubUmbrella(d)
227            | Self::SubClient(d)
228            | Self::SubLibrary(d) => d.value.clone(),
229            Self::Symtab(d) => format!("nsyms={}", d.nsyms),
230            Self::CodeSignature(d)
231            | Self::FunctionStarts(d)
232            | Self::DataInCode(d)
233            | Self::DyldExportsTrie(d)
234            | Self::DyldChainedFixups(d)
235            | Self::SegmentSplitInfo(d)
236            | Self::DylibCodeSignDrs(d)
237            | Self::LinkerOptimizationHint(d)
238            | Self::AtomInfo(d)
239            | Self::FunctionVariants(d)
240            | Self::FunctionVariantFixups(d) => {
241                format!("off={:#x} size={:#x}", d.data_offset, d.data_size)
242            }
243            Self::VersionMinMacOS(d)
244            | Self::VersionMinIOS(d)
245            | Self::VersionMinTvOS(d)
246            | Self::VersionMinWatchOS(d) => {
247                format!("{}", d.version)
248            }
249            Self::EncryptionInfo(d) | Self::EncryptionInfo64(d) => {
250                format!(
251                    "cryptoff={:#x} cryptsize={:#x} cryptid={}",
252                    d.crypt_offset, d.crypt_size, d.crypt_id
253                )
254            }
255            Self::DyldInfo(d) | Self::DyldInfoOnly(d) => {
256                format!(
257                    "rebase={:#x}+{:#x} bind={:#x}+{:#x} export={:#x}+{:#x}",
258                    d.rebase_off,
259                    d.rebase_size,
260                    d.bind_off,
261                    d.bind_size,
262                    d.export_off,
263                    d.export_size
264                )
265            }
266            Self::FilesetEntry(d) => d.entry_id.clone(),
267            Self::Note(d) => d.data_owner.clone(),
268            _ => String::new(),
269        }
270    }
271
272    /// Performs as_uuid.
273    pub fn as_uuid(&self) -> Option<&UuidData> {
274        match self {
275            Self::Uuid(d) => Some(d),
276            _ => None,
277        }
278    }
279
280    /// Performs as_build_version.
281    pub fn as_build_version(&self) -> Option<&BuildVersionData> {
282        match self {
283            Self::BuildVersion(d) => Some(d),
284            _ => None,
285        }
286    }
287
288    /// Performs as_symtab.
289    pub fn as_symtab(&self) -> Option<&SymtabData> {
290        match self {
291            Self::Symtab(d) => Some(d),
292            _ => None,
293        }
294    }
295
296    /// Performs as_dysymtab.
297    pub fn as_dysymtab(&self) -> Option<&DysymtabData> {
298        match self {
299            Self::Dysymtab(d) => Some(d),
300            _ => None,
301        }
302    }
303
304    /// Performs as_main.
305    pub fn as_main(&self) -> Option<&EntryPointData> {
306        match self {
307            Self::Main(d) => Some(d),
308            _ => None,
309        }
310    }
311
312    /// Performs as_dylib.
313    pub fn as_dylib(&self) -> Option<&DylibData> {
314        match self {
315            Self::LoadDylib(d)
316            | Self::LoadWeakDylib(d)
317            | Self::ReexportDylib(d)
318            | Self::LazyLoadDylib(d)
319            | Self::LoadUpwardDylib(d)
320            | Self::IdDylib(d) => Some(d),
321            _ => None,
322        }
323    }
324
325    /// Performs as_rpath.
326    pub fn as_rpath(&self) -> Option<&str> {
327        match self {
328            Self::Rpath(d) => Some(&d.value),
329            _ => None,
330        }
331    }
332
333    /// Performs as_segment.
334    pub fn as_segment(&self) -> Option<&SegmentCommandData> {
335        match self {
336            Self::Segment32(d) | Self::Segment64(d) => Some(d),
337            _ => None,
338        }
339    }
340
341    /// Performs as_linkedit_data.
342    pub fn as_linkedit_data(&self) -> Option<&LinkeditData> {
343        match self {
344            Self::CodeSignature(d)
345            | Self::FunctionStarts(d)
346            | Self::DataInCode(d)
347            | Self::DyldExportsTrie(d)
348            | Self::DyldChainedFixups(d)
349            | Self::SegmentSplitInfo(d)
350            | Self::DylibCodeSignDrs(d)
351            | Self::LinkerOptimizationHint(d)
352            | Self::AtomInfo(d)
353            | Self::FunctionVariants(d)
354            | Self::FunctionVariantFixups(d) => Some(d),
355            _ => None,
356        }
357    }
358}
359
360/// Performs format_uuid.
361pub fn format_uuid(uuid: &[u8; 16]) -> String {
362    format!(
363        "{:02X}{:02X}{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
364        uuid[0],
365        uuid[1],
366        uuid[2],
367        uuid[3],
368        uuid[4],
369        uuid[5],
370        uuid[6],
371        uuid[7],
372        uuid[8],
373        uuid[9],
374        uuid[10],
375        uuid[11],
376        uuid[12],
377        uuid[13],
378        uuid[14],
379        uuid[15],
380    )
381}
382
383// Data structs for each load command variant
384
385#[derive(Debug, Clone, PartialEq, Eq)]
386/// The SegmentCommandData type.
387pub struct SegmentCommandData {
388    /// The segment_index field.
389    pub segment_index: usize,
390}
391
392#[derive(Debug, Clone, PartialEq, Eq)]
393/// The SymtabData type.
394pub struct SymtabData {
395    /// The sym_offset field.
396    pub sym_offset: u32,
397    /// The nsyms field.
398    pub nsyms: u32,
399    /// The str_offset field.
400    pub str_offset: u32,
401    /// The str_size field.
402    pub str_size: u32,
403}
404
405#[derive(Debug, Clone, PartialEq, Eq)]
406/// The DysymtabData type.
407pub struct DysymtabData {
408    /// The ilocalsym field.
409    pub ilocalsym: u32,
410    /// The nlocalsym field.
411    pub nlocalsym: u32,
412    /// The iextdefsym field.
413    pub iextdefsym: u32,
414    /// The nextdefsym field.
415    pub nextdefsym: u32,
416    /// The iundefsym field.
417    pub iundefsym: u32,
418    /// The nundefsym field.
419    pub nundefsym: u32,
420    /// The tocoff field.
421    pub tocoff: u32,
422    /// The ntoc field.
423    pub ntoc: u32,
424    /// The modtaboff field.
425    pub modtaboff: u32,
426    /// The nmodtab field.
427    pub nmodtab: u32,
428    /// The extrefsymoff field.
429    pub extrefsymoff: u32,
430    /// The nextrefsyms field.
431    pub nextrefsyms: u32,
432    /// The indirectsymoff field.
433    pub indirectsymoff: u32,
434    /// The nindirectsyms field.
435    pub nindirectsyms: u32,
436    /// The extreloff field.
437    pub extreloff: u32,
438    /// The nextrel field.
439    pub nextrel: u32,
440    /// The locreloff field.
441    pub locreloff: u32,
442    /// The nlocrel field.
443    pub nlocrel: u32,
444}
445
446#[derive(Debug, Clone, PartialEq, Eq)]
447/// The DyldInfoData type.
448pub struct DyldInfoData {
449    /// The rebase_off field.
450    pub rebase_off: u32,
451    /// The rebase_size field.
452    pub rebase_size: u32,
453    /// The bind_off field.
454    pub bind_off: u32,
455    /// The bind_size field.
456    pub bind_size: u32,
457    /// The weak_bind_off field.
458    pub weak_bind_off: u32,
459    /// The weak_bind_size field.
460    pub weak_bind_size: u32,
461    /// The lazy_bind_off field.
462    pub lazy_bind_off: u32,
463    /// The lazy_bind_size field.
464    pub lazy_bind_size: u32,
465    /// The export_off field.
466    pub export_off: u32,
467    /// The export_size field.
468    pub export_size: u32,
469}
470
471#[derive(Debug, Clone, PartialEq, Eq)]
472/// The LinkeditData type.
473pub struct LinkeditData {
474    /// The data_offset field.
475    pub data_offset: u32,
476    /// The data_size field.
477    pub data_size: u32,
478}
479
480#[derive(Debug, Clone, PartialEq, Eq)]
481/// The EntryPointData type.
482pub struct EntryPointData {
483    /// The entry_offset field.
484    pub entry_offset: u64,
485    /// The stack_size field.
486    pub stack_size: u64,
487}
488
489#[derive(Debug, Clone, PartialEq, Eq)]
490/// The UuidData type.
491pub struct UuidData {
492    /// The uuid field.
493    pub uuid: [u8; 16],
494}
495
496#[derive(Debug, Clone, PartialEq, Eq)]
497/// The BuildVersionData type.
498pub struct BuildVersionData {
499    /// The platform field.
500    pub platform: Platform,
501    /// The minos field.
502    pub minos: PackedVersion,
503    /// The sdk field.
504    pub sdk: PackedVersion,
505    /// The tools field.
506    pub tools: Vec<BuildToolVersion>,
507}
508
509#[derive(Debug, Clone, PartialEq, Eq)]
510/// The BuildToolVersion type.
511pub struct BuildToolVersion {
512    /// The tool field.
513    pub tool: Tool,
514    /// The version field.
515    pub version: PackedVersion,
516}
517
518#[derive(Debug, Clone, PartialEq, Eq)]
519/// The SourceVersionData type.
520pub struct SourceVersionData {
521    /// The version field.
522    pub version: SourceVersion,
523}
524
525#[derive(Debug, Clone, PartialEq, Eq)]
526/// The VersionMinData type.
527pub struct VersionMinData {
528    /// The version field.
529    pub version: PackedVersion,
530    /// The sdk field.
531    pub sdk: PackedVersion,
532}
533
534#[derive(Debug, Clone, PartialEq, Eq)]
535/// The DylibData type.
536pub struct DylibData {
537    /// The name field.
538    pub name: String,
539    /// The timestamp field.
540    pub timestamp: u32,
541    /// The current_version field.
542    pub current_version: PackedVersion,
543    /// The compatibility_version field.
544    pub compatibility_version: PackedVersion,
545}
546
547#[derive(Debug, Clone, PartialEq, Eq)]
548/// The StringData type.
549pub struct StringData {
550    /// The value field.
551    pub value: String,
552}
553
554#[derive(Debug, Clone, PartialEq, Eq)]
555/// The EncryptionInfoData type.
556pub struct EncryptionInfoData {
557    /// The crypt_offset field.
558    pub crypt_offset: u32,
559    /// The crypt_size field.
560    pub crypt_size: u32,
561    /// The crypt_id field.
562    pub crypt_id: u32,
563}
564
565#[derive(Debug, Clone, PartialEq, Eq)]
566/// The LinkerOptionData type.
567pub struct LinkerOptionData {
568    /// The strings field.
569    pub strings: Vec<String>,
570}
571
572#[derive(Debug, Clone, PartialEq, Eq)]
573/// The NoteData type.
574pub struct NoteData {
575    /// The data_owner field.
576    pub data_owner: String,
577    /// The offset field.
578    pub offset: u64,
579    /// The size field.
580    pub size: u64,
581}
582
583#[derive(Debug, Clone, PartialEq, Eq)]
584/// The FilesetEntryData type.
585pub struct FilesetEntryData {
586    /// The vm_addr field.
587    pub vm_addr: u64,
588    /// The file_offset field.
589    pub file_offset: u64,
590    /// The entry_id field.
591    pub entry_id: String,
592}
593
594#[derive(Debug, Clone, PartialEq, Eq)]
595/// The PrebindCksumData type.
596pub struct PrebindCksumData {
597    /// The cksum field.
598    pub cksum: u32,
599}
600
601#[derive(Debug, Clone, PartialEq, Eq)]
602/// The TwolevelHintsData type.
603pub struct TwolevelHintsData {
604    /// The offset field.
605    pub offset: u32,
606    /// The nhints field.
607    pub nhints: u32,
608}
609
610#[derive(Debug, Clone, PartialEq, Eq)]
611/// The RoutinesData type.
612pub struct RoutinesData {
613    /// The init_address field.
614    pub init_address: u64,
615    /// The init_module field.
616    pub init_module: u64,
617}
618
619#[derive(Debug, Clone, PartialEq, Eq)]
620/// The RawData type.
621pub struct RawData {
622    /// The data field.
623    pub data: Vec<u8>,
624}
625
626#[derive(Debug, Clone, PartialEq, Eq)]
627/// The UnknownLoadCommand type.
628pub struct UnknownLoadCommand {
629    /// The cmd field.
630    pub cmd: u32,
631    /// The data field.
632    pub data: Vec<u8>,
633}
634
635// Version and platform types
636
637#[derive(Clone, Copy, PartialEq, Eq)]
638/// The PackedVersion type.
639pub struct PackedVersion(pub u32);
640
641impl PackedVersion {
642    /// Performs major.
643    pub fn major(self) -> u32 {
644        self.0 >> 16
645    }
646
647    /// Performs minor.
648    pub fn minor(self) -> u32 {
649        (self.0 >> 8) & 0xFF
650    }
651
652    /// Performs patch.
653    pub fn patch(self) -> u32 {
654        self.0 & 0xFF
655    }
656}
657
658impl fmt::Debug for PackedVersion {
659    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
660        write!(f, "{self}")
661    }
662}
663
664impl fmt::Display for PackedVersion {
665    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666        write!(f, "{}.{}.{}", self.major(), self.minor(), self.patch())
667    }
668}
669
670#[derive(Clone, Copy, PartialEq, Eq)]
671/// The SourceVersion type.
672pub struct SourceVersion(pub u64);
673
674impl SourceVersion {
675    /// Performs a.
676    pub fn a(self) -> u64 {
677        (self.0 >> 40) & 0xFFFFFF
678    }
679    /// Performs b.
680    pub fn b(self) -> u64 {
681        (self.0 >> 30) & 0x3FF
682    }
683    /// Performs c.
684    pub fn c(self) -> u64 {
685        (self.0 >> 20) & 0x3FF
686    }
687    /// Performs d.
688    pub fn d(self) -> u64 {
689        (self.0 >> 10) & 0x3FF
690    }
691    /// Performs e.
692    pub fn e(self) -> u64 {
693        self.0 & 0x3FF
694    }
695}
696
697impl fmt::Debug for SourceVersion {
698    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
699        write!(f, "{self}")
700    }
701}
702
703impl fmt::Display for SourceVersion {
704    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705        write!(
706            f,
707            "{}.{}.{}.{}.{}",
708            self.a(),
709            self.b(),
710            self.c(),
711            self.d(),
712            self.e()
713        )
714    }
715}
716
717#[derive(Clone, Copy, PartialEq, Eq)]
718/// The Platform type.
719pub struct Platform(pub u32);
720
721impl Platform {
722    /// Performs name.
723    pub fn name(self) -> &'static str {
724        match self.0 {
725            PLATFORM_MACOS => "macOS",
726            PLATFORM_IOS => "iOS",
727            PLATFORM_TVOS => "tvOS",
728            PLATFORM_WATCHOS => "watchOS",
729            PLATFORM_BRIDGEOS => "bridgeOS",
730            PLATFORM_MACCATALYST => "Mac Catalyst",
731            PLATFORM_IOSSIMULATOR => "iOS Simulator",
732            PLATFORM_TVOSSIMULATOR => "tvOS Simulator",
733            PLATFORM_WATCHOSSIMULATOR => "watchOS Simulator",
734            PLATFORM_DRIVERKIT => "DriverKit",
735            PLATFORM_VISIONOS => "visionOS",
736            PLATFORM_VISIONOSSIMULATOR => "visionOS Simulator",
737            PLATFORM_FIRMWARE => "Firmware",
738            PLATFORM_SEPOS => "sepOS",
739            _ => "unknown",
740        }
741    }
742}
743
744impl fmt::Debug for Platform {
745    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746        write!(f, "Platform({})", self.name())
747    }
748}
749
750impl fmt::Display for Platform {
751    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
752        write!(f, "{}", self.name())
753    }
754}
755
756#[derive(Clone, Copy, PartialEq, Eq)]
757/// The Tool type.
758pub struct Tool(pub u32);
759
760impl Tool {
761    /// Performs name.
762    pub fn name(self) -> &'static str {
763        match self.0 {
764            TOOL_CLANG => "clang",
765            TOOL_SWIFT => "swift",
766            TOOL_LD => "ld",
767            TOOL_LLD => "lld",
768            TOOL_METAL => "metal",
769            TOOL_AIRLLD => "airlld",
770            TOOL_AIRNT => "airnt",
771            TOOL_AIRNT_PLUGIN => "airnt_plugin",
772            TOOL_AIRPACK => "airpack",
773            TOOL_GPUARCHIVER => "gpuarchiver",
774            TOOL_METAL_FRAMEWORK => "metal_framework",
775            _ => "unknown",
776        }
777    }
778}
779
780impl fmt::Debug for Tool {
781    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
782        write!(f, "Tool({})", self.name())
783    }
784}