Skip to content

Commit 9ce47b3

Browse files
authored
Merge pull request #319 from Freax13/index-idt-with-u8
implement `Index<u8>` for IDT instead of `Index<usize>` and add implementations for indexing with ranges
2 parents 37f8b0d + 6eee5a8 commit 9ce47b3

File tree

1 file changed

+65
-30
lines changed

1 file changed

+65
-30
lines changed

src/structures/idt.rs

+65-30
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use bitflags::bitflags;
2626
use core::fmt;
2727
use core::marker::PhantomData;
2828
use core::ops::Bound::{Excluded, Included, Unbounded};
29-
use core::ops::{Deref, Index, IndexMut, RangeBounds};
29+
use core::ops::{
30+
Bound, Deref, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive,
31+
RangeTo, RangeToInclusive,
32+
};
3033
use volatile::Volatile;
3134

3235
use super::gdt::SegmentSelector;
@@ -458,25 +461,21 @@ impl InterruptDescriptorTable {
458461
}
459462
}
460463

461-
/// Returns a normalized and ranged check slice range from a RangeBounds trait object
464+
/// Returns a normalized and ranged check slice range from a RangeBounds trait object.
462465
///
463-
/// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an
464-
/// exception
465-
fn condition_slice_bounds(&self, bounds: impl RangeBounds<usize>) -> (usize, usize) {
466+
/// Panics if the entry is an exception.
467+
fn condition_slice_bounds(&self, bounds: impl RangeBounds<u8>) -> (usize, usize) {
466468
let lower_idx = match bounds.start_bound() {
467-
Included(start) => *start,
468-
Excluded(start) => *start + 1,
469+
Included(start) => usize::from(*start),
470+
Excluded(start) => usize::from(*start) + 1,
469471
Unbounded => 0,
470472
};
471473
let upper_idx = match bounds.end_bound() {
472-
Included(end) => *end + 1,
473-
Excluded(end) => *end,
474+
Included(end) => usize::from(*end) + 1,
475+
Excluded(end) => usize::from(*end),
474476
Unbounded => 256,
475477
};
476478

477-
if lower_idx > 256 || upper_idx > 256 {
478-
panic!("Index out of range [{}..{}]", lower_idx, upper_idx);
479-
}
480479
if lower_idx < 32 {
481480
panic!("Cannot return slice from traps, faults, and exception handlers");
482481
}
@@ -485,34 +484,31 @@ impl InterruptDescriptorTable {
485484

486485
/// Returns slice of IDT entries with the specified range.
487486
///
488-
/// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an
489-
/// exception
487+
/// Panics if the entry is an exception.
490488
#[inline]
491-
pub fn slice(&self, bounds: impl RangeBounds<usize>) -> &[Entry<HandlerFunc>] {
489+
pub fn slice(&self, bounds: impl RangeBounds<u8>) -> &[Entry<HandlerFunc>] {
492490
let (lower_idx, upper_idx) = self.condition_slice_bounds(bounds);
493491
&self.interrupts[(lower_idx - 32)..(upper_idx - 32)]
494492
}
495493

496494
/// Returns a mutable slice of IDT entries with the specified range.
497495
///
498-
/// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an
499-
/// exception
496+
/// Panics if the entry is an exception.
500497
#[inline]
501-
pub fn slice_mut(&mut self, bounds: impl RangeBounds<usize>) -> &mut [Entry<HandlerFunc>] {
498+
pub fn slice_mut(&mut self, bounds: impl RangeBounds<u8>) -> &mut [Entry<HandlerFunc>] {
502499
let (lower_idx, upper_idx) = self.condition_slice_bounds(bounds);
503500
&mut self.interrupts[(lower_idx - 32)..(upper_idx - 32)]
504501
}
505502
}
506503

507-
impl Index<usize> for InterruptDescriptorTable {
504+
impl Index<u8> for InterruptDescriptorTable {
508505
type Output = Entry<HandlerFunc>;
509506

510507
/// Returns the IDT entry with the specified index.
511508
///
512-
/// Panics if index is outside the IDT (i.e. greater than 255) or if the entry is an
513-
/// exception that pushes an error code (use the struct fields for accessing these entries).
509+
/// Panics if the entry is an exception that pushes an error code (use the struct fields for accessing these entries).
514510
#[inline]
515-
fn index(&self, index: usize) -> &Self::Output {
511+
fn index(&self, index: u8) -> &Self::Output {
516512
match index {
517513
0 => &self.divide_error,
518514
1 => &self.debug,
@@ -526,24 +522,22 @@ impl Index<usize> for InterruptDescriptorTable {
526522
16 => &self.x87_floating_point,
527523
19 => &self.simd_floating_point,
528524
20 => &self.virtualization,
529-
i @ 32..=255 => &self.interrupts[i - 32],
525+
i @ 32..=255 => &self.interrupts[usize::from(i - 32)],
530526
i @ 15 | i @ 31 | i @ 21..=29 => panic!("entry {} is reserved", i),
531527
i @ 8 | i @ 10..=14 | i @ 17 | i @ 30 => {
532528
panic!("entry {} is an exception with error code", i)
533529
}
534530
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
535-
i => panic!("no entry with index {}", i),
536531
}
537532
}
538533
}
539534

540-
impl IndexMut<usize> for InterruptDescriptorTable {
535+
impl IndexMut<u8> for InterruptDescriptorTable {
541536
/// Returns a mutable reference to the IDT entry with the specified index.
542537
///
543-
/// Panics if index is outside the IDT (i.e. greater than 255) or if the entry is an
544-
/// exception that pushes an error code (use the struct fields for accessing these entries).
538+
/// Panics if the entry is an exception that pushes an error code (use the struct fields for accessing these entries).
545539
#[inline]
546-
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
540+
fn index_mut(&mut self, index: u8) -> &mut Self::Output {
547541
match index {
548542
0 => &mut self.divide_error,
549543
1 => &mut self.debug,
@@ -557,17 +551,58 @@ impl IndexMut<usize> for InterruptDescriptorTable {
557551
16 => &mut self.x87_floating_point,
558552
19 => &mut self.simd_floating_point,
559553
20 => &mut self.virtualization,
560-
i @ 32..=255 => &mut self.interrupts[i - 32],
554+
i @ 32..=255 => &mut self.interrupts[usize::from(i - 32)],
561555
i @ 15 | i @ 31 | i @ 21..=29 => panic!("entry {} is reserved", i),
562556
i @ 8 | i @ 10..=14 | i @ 17 | i @ 30 => {
563557
panic!("entry {} is an exception with error code", i)
564558
}
565559
i @ 18 => panic!("entry {} is an diverging exception (must not return)", i),
566-
i => panic!("no entry with index {}", i),
567560
}
568561
}
569562
}
570563

564+
macro_rules! impl_index_for_idt {
565+
($ty:ty) => {
566+
impl Index<$ty> for InterruptDescriptorTable {
567+
type Output = [Entry<HandlerFunc>];
568+
569+
/// Returns the IDT entry with the specified index.
570+
///
571+
/// Panics if index is outside the IDT (i.e. greater than 255) or if the entry is an
572+
/// exception that pushes an error code (use the struct fields for accessing these entries).
573+
#[inline]
574+
fn index(&self, index: $ty) -> &Self::Output {
575+
self.slice(index)
576+
}
577+
}
578+
579+
impl IndexMut<$ty> for InterruptDescriptorTable {
580+
/// Returns a mutable reference to the IDT entry with the specified index.
581+
///
582+
/// Panics if the entry is an exception that pushes an error code (use the struct fields for accessing these entries).
583+
#[inline]
584+
fn index_mut(&mut self, index: $ty) -> &mut Self::Output {
585+
self.slice_mut(index)
586+
}
587+
}
588+
};
589+
}
590+
591+
// this list was stolen from the list of implementors in https://doc.rust-lang.org/core/ops/trait.RangeBounds.html
592+
impl_index_for_idt!((Bound<&u8>, Bound<&u8>));
593+
impl_index_for_idt!((Bound<u8>, Bound<u8>));
594+
impl_index_for_idt!(Range<&u8>);
595+
impl_index_for_idt!(Range<u8>);
596+
impl_index_for_idt!(RangeFrom<&u8>);
597+
impl_index_for_idt!(RangeFrom<u8>);
598+
impl_index_for_idt!(RangeInclusive<&u8>);
599+
impl_index_for_idt!(RangeInclusive<u8>);
600+
impl_index_for_idt!(RangeTo<u8>);
601+
impl_index_for_idt!(RangeTo<&u8>);
602+
impl_index_for_idt!(RangeToInclusive<&u8>);
603+
impl_index_for_idt!(RangeToInclusive<u8>);
604+
impl_index_for_idt!(RangeFull);
605+
571606
/// An Interrupt Descriptor Table entry.
572607
///
573608
/// The generic parameter is some [`InterruptFn`], depending on the interrupt vector.

0 commit comments

Comments
 (0)