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 {
7272 }
7373
7474 pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {
75 return switch (self.type) {
76 .Hardware => blk: {
77 const hardware: ?HardwareDevicePath = switch (@intToEnum(HardwareDevicePath.Subtype, self.subtype)) {
78 .Pci => .{ .Pci = @ptrCast(*const HardwareDevicePath.PciDevicePath, self) },
79 .PcCard => .{ .PcCard = @ptrCast(*const HardwareDevicePath.PcCardDevicePath, self) },
80 .MemoryMapped => .{ .MemoryMapped = @ptrCast(*const HardwareDevicePath.MemoryMappedDevicePath, self) },
81 .Vendor => .{ .Vendor = @ptrCast(*const HardwareDevicePath.VendorDevicePath, self) },
82 .Controller => .{ .Controller = @ptrCast(*const HardwareDevicePath.ControllerDevicePath, self) },
83 .Bmc => .{ .Bmc = @ptrCast(*const HardwareDevicePath.BmcDevicePath, self) },
84 _ => null,
85 };
86 break :blk if (hardware) |h| .{ .Hardware = h } else null;
87 },
88 .Acpi => blk: {
89 const acpi: ?AcpiDevicePath = switch (@intToEnum(AcpiDevicePath.Subtype, self.subtype)) {
90 .Acpi => .{ .Acpi = @ptrCast(*const AcpiDevicePath.BaseAcpiDevicePath, self) },
91 .ExpandedAcpi => .{ .ExpandedAcpi = @ptrCast(*const AcpiDevicePath.ExpandedAcpiDevicePath, self) },
92 .Adr => .{ .Adr = @ptrCast(*const AcpiDevicePath.AdrDevicePath, self) },
93 _ => null,
94 };
95 break :blk if (acpi) |a| .{ .Acpi = a } else null;
96 },
97 .Messaging => blk: {
98 const messaging: ?MessagingDevicePath = switch (@intToEnum(MessagingDevicePath.Subtype, self.subtype)) {
99 else => null, // TODO
100 };
101 break :blk if (messaging) |m| .{ .Messaging = m } else null;
102 },
103 .Media => blk: {
104 const media: ?MediaDevicePath = switch (@intToEnum(MediaDevicePath.Subtype, self.subtype)) {
105 .HardDrive => .{ .HardDrive = @ptrCast(*const MediaDevicePath.HardDriveDevicePath, self) },
106 .Cdrom => .{ .Cdrom = @ptrCast(*const MediaDevicePath.CdromDevicePath, self) },
107 .Vendor => .{ .Vendor = @ptrCast(*const MediaDevicePath.VendorDevicePath, self) },
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 };
75 inline for (@typeInfo(DevicePath).Union.fields) |ufield| {
76 const enum_value = std.meta.stringToEnum(DevicePathType, ufield.name);
77
78 // Got the associated union type for self.type, now
79 // we need to initialize it and its subtype
80 if (self.type == enum_value) {
81 var subtype = self.initSubtype(ufield.field_type);
82
83 if (subtype) |sb| {
84 // e.g. return .{ .Hardware = .{ .Pci = @ptrCast(...) } }
85 return @unionInit(DevicePath, ufield.name, sb);
86 }
87 }
88 }
89
90 return null;
91 }
92
93 pub fn initSubtype(self: *const DevicePathProtocol, comptime TUnion: type) ?TUnion {
94 const type_info = @typeInfo(TUnion).Union;
95 const TTag = type_info.tag_type.?;
96
97 inline for (type_info.fields) |subtype| {
98 // The tag names match the union names, so just grab that off the enum
99 const tag_val: u8 = @enumToInt(@field(TTag, subtype.name));
100
101 if (self.subtype == tag_val) {
102 // e.g. expr = .{ .Pci = @ptrCast(...) }
103 return @unionInit(TUnion, subtype.name, @ptrCast(subtype.field_type, self));
104 }
105 }
106
107 return null;
135108 }
136109};
137110
......@@ -268,7 +241,7 @@ pub const MessagingDevicePath = union(Subtype) {
268241 Atapi: *const AtapiDevicePath,
269242 Scsi: *const ScsiDevicePath,
270243 FibreChannel: *const FibreChannelDevicePath,
271 FibreChannelEx: FibreChannelExDevicePath,
244 FibreChannelEx: *const FibreChannelExDevicePath,
272245 @"1394": *const F1394DevicePath,
273246 Usb: *const UsbDevicePath,
274247 Sata: *const SataDevicePath,