authorgravatar for ybham6@gmail.comfifty-six <ybham6@gmail.com> 2022-01-14 08:53:56-05:00
committergravatar for ybham6@gmail.comfifty-six <ybham6@gmail.com> 2022-01-14 08:58:30-05:00
logdab4c63684ca951049fb8e8f6b2415857eb6652b
treebf0fe9fddfe684f2368b429ae0ae704233b3a7c6
parenta2a2601da577dd424ea585da0449288a439871fe

std/os/uefi: Refactor getDevicePath()

Uses comptime loops over the types instead of writing out a large switch.

1 files changed, 34 insertions(+), 61 deletions(-)

lib/std/os/uefi/protocols/device_path_protocol.zig+34-61
...@@ -72,66 +72,39 @@ pub const DevicePathProtocol = packed struct {...@@ -72,66 +72,39 @@ pub const DevicePathProtocol = packed struct {
72 }72 }
7373
74 pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {74 pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {
75 return switch (self.type) {75 inline for (@typeInfo(DevicePath).Union.fields) |ufield| {
76 .Hardware => blk: {76 const enum_value = std.meta.stringToEnum(DevicePathType, ufield.name);
77 const hardware: ?HardwareDevicePath = switch (@intToEnum(HardwareDevicePath.Subtype, self.subtype)) {77
78 .Pci => .{ .Pci = @ptrCast(*const HardwareDevicePath.PciDevicePath, self) },78 // Got the associated union type for self.type, now
79 .PcCard => .{ .PcCard = @ptrCast(*const HardwareDevicePath.PcCardDevicePath, self) },79 // we need to initialize it and its subtype
80 .MemoryMapped => .{ .MemoryMapped = @ptrCast(*const HardwareDevicePath.MemoryMappedDevicePath, self) },80 if (self.type == enum_value) {
81 .Vendor => .{ .Vendor = @ptrCast(*const HardwareDevicePath.VendorDevicePath, self) },81 var subtype = self.initSubtype(ufield.field_type);
82 .Controller => .{ .Controller = @ptrCast(*const HardwareDevicePath.ControllerDevicePath, self) },82
83 .Bmc => .{ .Bmc = @ptrCast(*const HardwareDevicePath.BmcDevicePath, self) },83 if (subtype) |sb| {
84 _ => null,84 // e.g. return .{ .Hardware = .{ .Pci = @ptrCast(...) } }
85 };85 return @unionInit(DevicePath, ufield.name, sb);
86 break :blk if (hardware) |h| .{ .Hardware = h } else null;86 }
87 },87 }
88 .Acpi => blk: {88 }
89 const acpi: ?AcpiDevicePath = switch (@intToEnum(AcpiDevicePath.Subtype, self.subtype)) {89
90 .Acpi => .{ .Acpi = @ptrCast(*const AcpiDevicePath.BaseAcpiDevicePath, self) },90 return null;
91 .ExpandedAcpi => .{ .ExpandedAcpi = @ptrCast(*const AcpiDevicePath.ExpandedAcpiDevicePath, self) },91 }
92 .Adr => .{ .Adr = @ptrCast(*const AcpiDevicePath.AdrDevicePath, self) },92
93 _ => null,93 pub fn initSubtype(self: *const DevicePathProtocol, comptime TUnion: type) ?TUnion {
94 };94 const type_info = @typeInfo(TUnion).Union;
95 break :blk if (acpi) |a| .{ .Acpi = a } else null;95 const TTag = type_info.tag_type.?;
96 },96
97 .Messaging => blk: {97 inline for (type_info.fields) |subtype| {
98 const messaging: ?MessagingDevicePath = switch (@intToEnum(MessagingDevicePath.Subtype, self.subtype)) {98 // The tag names match the union names, so just grab that off the enum
99 else => null, // TODO99 const tag_val: u8 = @enumToInt(@field(TTag, subtype.name));
100 };100
101 break :blk if (messaging) |m| .{ .Messaging = m } else null;101 if (self.subtype == tag_val) {
102 },102 // e.g. expr = .{ .Pci = @ptrCast(...) }
103 .Media => blk: {103 return @unionInit(TUnion, subtype.name, @ptrCast(subtype.field_type, self));
104 const media: ?MediaDevicePath = switch (@intToEnum(MediaDevicePath.Subtype, self.subtype)) {104 }
105 .HardDrive => .{ .HardDrive = @ptrCast(*const MediaDevicePath.HardDriveDevicePath, self) },105 }
106 .Cdrom => .{ .Cdrom = @ptrCast(*const MediaDevicePath.CdromDevicePath, self) },106
107 .Vendor => .{ .Vendor = @ptrCast(*const MediaDevicePath.VendorDevicePath, self) },107 return null;
108 .FilePath => .{ .FilePath = @ptrCast(*const MediaDevicePath.FilePathDevicePath, self) },
109 .MediaProtocol => .{ .MediaProtocol = @ptrCast(*const MediaDevicePath.MediaProtocolDevicePath, self) },
110 .PiwgFirmwareFile => .{ .PiwgFirmwareFile = @ptrCast(*const MediaDevicePath.PiwgFirmwareFileDevicePath, self) },
111 .PiwgFirmwareVolume => .{ .PiwgFirmwareVolume = @ptrCast(*const MediaDevicePath.PiwgFirmwareVolumeDevicePath, self) },
112 .RelativeOffsetRange => .{ .RelativeOffsetRange = @ptrCast(*const MediaDevicePath.RelativeOffsetRangeDevicePath, self) },
113 .RamDisk => .{ .RamDisk = @ptrCast(*const MediaDevicePath.RamDiskDevicePath, self) },
114 _ => null,
115 };
116 break :blk if (media) |m| .{ .Media = m } else null;
117 },
118 .BiosBootSpecification => blk: {
119 const bbs: ?BiosBootSpecificationDevicePath = switch (@intToEnum(BiosBootSpecificationDevicePath.Subtype, self.subtype)) {
120 .BBS101 => .{ .BBS101 = @ptrCast(*const BiosBootSpecificationDevicePath.BBS101DevicePath, self) },
121 _ => null,
122 };
123 break :blk if (bbs) |b| .{ .BiosBootSpecification = b } else null;
124 },
125 .End => blk: {
126 const end: ?EndDevicePath = switch (@intToEnum(EndDevicePath.Subtype, self.subtype)) {
127 .EndEntire => .{ .EndEntire = @ptrCast(*const EndDevicePath.EndEntireDevicePath, self) },
128 .EndThisInstance => .{ .EndThisInstance = @ptrCast(*const EndDevicePath.EndThisInstanceDevicePath, self) },
129 _ => null,
130 };
131 break :blk if (end) |e| .{ .End = e } else null;
132 },
133 _ => null,
134 };
135 }108 }
136};109};
137110
...@@ -268,7 +241,7 @@ pub const MessagingDevicePath = union(Subtype) {...@@ -268,7 +241,7 @@ pub const MessagingDevicePath = union(Subtype) {
268 Atapi: *const AtapiDevicePath,241 Atapi: *const AtapiDevicePath,
269 Scsi: *const ScsiDevicePath,242 Scsi: *const ScsiDevicePath,
270 FibreChannel: *const FibreChannelDevicePath,243 FibreChannel: *const FibreChannelDevicePath,
271 FibreChannelEx: FibreChannelExDevicePath,244 FibreChannelEx: *const FibreChannelExDevicePath,
272 @"1394": *const F1394DevicePath,245 @"1394": *const F1394DevicePath,
273 Usb: *const UsbDevicePath,246 Usb: *const UsbDevicePath,
274 Sata: *const SataDevicePath,247 Sata: *const SataDevicePath,