Skip to content

Commit ea1ce32

Browse files
committed
rs: use lending iterator patten to ensure safety of DisasmIter
1 parent 4008842 commit ea1ce32

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

capstone-rs/benches/my_benchmark.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ fn arch_bench<T: Iterator<Item = ExtraMode>>(
2323
cs.set_detail(detail).expect("failed to set detail");
2424

2525
if iter {
26-
let iter = cs.disasm_iter(code, 0x1000).expect("failed to disassemble");
27-
for i in iter {
26+
let mut iter = cs.disasm_iter(code, 0x1000).expect("failed to disassemble");
27+
while let Some(i) = iter.next() {
2828
black_box(i);
2929
}
3030
} else {

capstone-rs/src/capstone.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -653,10 +653,34 @@ impl<'cs, 'buf> Drop for DisasmIter<'cs, 'buf> {
653653
}
654654
}
655655

656-
impl<'cs, 'buf> Iterator for DisasmIter<'cs, 'buf> {
657-
type Item = Insn<'cs>;
658-
659-
fn next(&mut self) -> Option<Self::Item> {
656+
impl<'cs, 'buf> DisasmIter<'cs, 'buf> {
657+
/// Get next instruction if available.
658+
///
659+
/// # Examples
660+
///
661+
/// ```
662+
/// # use capstone::prelude::*;
663+
/// # let cs = Capstone::new().x86().mode(arch::x86::ArchMode::Mode32).build().unwrap();
664+
/// let code = b"\x90";
665+
/// let mut iter = cs.disasm_iter(code, 0x1000).unwrap();
666+
/// while let Some(insn) = iter.next() {
667+
/// println!("{insn}");
668+
/// }
669+
/// ```
670+
///
671+
/// At most one instruction can be accessed at the same time:
672+
///
673+
/// ```compile_fail
674+
/// # use capstone::prelude::*;
675+
/// # let cs = Capstone::new().x86().mode(arch::x86::ArchMode::Mode32).build().unwrap();
676+
/// let code = b"\x90";
677+
/// let mut iter = cs.disasm_iter(code, 0x1000).unwrap();
678+
/// let insn1 = iter.next().unwrap();
679+
/// let insn2 = iter.next().unwrap();
680+
/// // fails with: cannot borrow `iter` as mutable more than once at a time
681+
/// println!("{insn1}");
682+
/// ```
683+
pub fn next<'iter>(&'iter mut self) -> Option<Insn<'iter>> {
660684
unsafe {
661685
if cs_disasm_iter(
662686
self.csh as csh,
@@ -671,9 +695,7 @@ impl<'cs, 'buf> Iterator for DisasmIter<'cs, 'buf> {
671695

672696
None
673697
}
674-
}
675698

676-
impl<'cs, 'buf> DisasmIter<'cs, 'buf> {
677699
/// Get the slice of the code yet to be disassembled
678700
///
679701
/// ```

0 commit comments

Comments
 (0)