diff --git a/src/structures/idt.rs b/src/structures/idt.rs index f06bbd59a..0d2b18342 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -14,7 +14,8 @@ use bit_field::BitField; use bitflags::bitflags; use core::fmt; use core::marker::PhantomData; -use core::ops::{Deref, Index, IndexMut}; +use core::ops::Bound::{Excluded, Included, Unbounded}; +use core::ops::{Deref, Index, IndexMut, RangeBounds}; /// An Interrupt Descriptor Table with 256 entries. /// @@ -442,6 +443,49 @@ impl InterruptDescriptorTable { unsafe { lidt(&ptr) }; } + + /// Returns a normalized and ranged check slice range from a RangeBounds trait object + /// + /// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an + /// exception + fn condition_slice_bounds(&self, bounds: impl RangeBounds) -> (usize, usize) { + let lower_idx = match bounds.start_bound() { + Included(start) => *start, + Excluded(start) => *start + 1, + Unbounded => 0, + }; + let upper_idx = match bounds.end_bound() { + Included(end) => *end + 1, + Excluded(end) => *end, + Unbounded => 256, + }; + + if lower_idx > 256 || upper_idx > 256 { + panic!("Index out of range [{}..{}]", lower_idx, upper_idx); + } + if lower_idx < 32 { + panic!("Cannot return slice from traps, faults, and exception handlers"); + } + (lower_idx, upper_idx) + } + + /// Returns slice of IDT entries with the specified range. + /// + /// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an + /// exception + pub fn slice(&self, bounds: impl RangeBounds) -> &[Entry] { + let (lower_idx, upper_idx) = self.condition_slice_bounds(bounds); + &self.interrupts[(lower_idx - 32)..(upper_idx - 32)] + } + + /// Returns a mutable slice of IDT entries with the specified range. + /// + /// Panics if range is outside the range of user interrupts (i.e. greater than 255) or if the entry is an + /// exception + pub fn slice_mut(&mut self, bounds: impl RangeBounds) -> &mut [Entry] { + let (lower_idx, upper_idx) = self.condition_slice_bounds(bounds); + &mut self.interrupts[(lower_idx - 32)..(upper_idx - 32)] + } } impl Index for InterruptDescriptorTable {