Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace clang.rs iterator with generic boxed Map<Range<>> #213

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 70 additions & 101 deletions libbindgen/src/clang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,18 +653,18 @@ impl Type {

/// If this type is a class template specialization, return its
/// template arguments. Otherwise, return None.
pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
if n >= 0 {
Some(TypeTemplateArgIterator {
x: self.x,
length: n as u32,
index: 0,
})
} else {
debug_assert_eq!(n, -1);
None
}
pub fn template_args<'a>
(&'a self)
-> Option<Box<ExactSizeIterator<Item = Type> + 'a>> {
let f_len =
move || unsafe { clang_Type_getNumTemplateArguments(self.x) };
let f = move |i| {
Type {
x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, i) },
}
};

ffi_call_index_iterator_check_positive(f_len, f)
}

/// Given that this type is a pointer type, return the type that it points
Expand Down Expand Up @@ -761,35 +761,6 @@ impl Type {
}
}

/// An iterator for a type's template arguments.
pub struct TypeTemplateArgIterator {
x: CXType,
length: u32,
index: u32,
}

impl Iterator for TypeTemplateArgIterator {
type Item = Type;
fn next(&mut self) -> Option<Type> {
if self.index < self.length {
let idx = self.index as c_int;
self.index += 1;
Some(Type {
x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
})
} else {
None
}
}
}

impl ExactSizeIterator for TypeTemplateArgIterator {
fn len(&self) -> usize {
assert!(self.index <= self.length);
(self.length - self.index) as usize
}
}

/// A `SourceLocation` is a file, line, column, and byte offset location for
/// some source text.
pub struct SourceLocation {
Expand Down Expand Up @@ -845,12 +816,16 @@ impl Comment {
}

/// Get this comment's children comment
pub fn get_children(&self) -> CommentChildrenIterator {
CommentChildrenIterator {
parent: self.x,
length: unsafe { clang_Comment_getNumChildren(self.x) },
index: 0,
}
pub fn get_children<'a>(&'a self)
-> Box<ExactSizeIterator<Item = Comment> + 'a> {
let f_len = move || unsafe { clang_Comment_getNumChildren(self.x) };
let f = move |i| {
Comment {
x: unsafe { clang_Comment_getChild(self.x, i) },
}
};

ffi_call_index_iterator(f_len, f)
}

/// Given that this comment is the start or end of an HTML tag, get its tag
Expand All @@ -860,34 +835,22 @@ impl Comment {
}

/// Given that this comment is an HTML start tag, get its attributes.
pub fn get_tag_attrs(&self) -> CommentAttributesIterator {
CommentAttributesIterator {
x: self.x,
length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
index: 0,
}
}
}

/// An iterator for a comment's children
pub struct CommentChildrenIterator {
parent: CXComment,
length: c_uint,
index: c_uint,
}
pub fn get_tag_attrs<'a>
(&'a self)
-> Box<ExactSizeIterator<Item = CommentAttribute> + 'a> {
let f_len = move || unsafe { clang_HTMLStartTag_getNumAttrs(self.x) };
let f = move |i| {
CommentAttribute {
name: unsafe {
clang_HTMLStartTag_getAttrName(self.x, i).into()
},
value: unsafe {
clang_HTMLStartTag_getAttrValue(self.x, i).into()
},
}
};

impl Iterator for CommentChildrenIterator {
type Item = Comment;
fn next(&mut self) -> Option<Comment> {
if self.index < self.length {
let idx = self.index;
self.index += 1;
Some(Comment {
x: unsafe { clang_Comment_getChild(self.parent, idx) },
})
} else {
None
}
ffi_call_index_iterator(f_len, f)
}
}

Expand All @@ -899,33 +862,6 @@ pub struct CommentAttribute {
pub value: String,
}

/// An iterator for a comment's attributes
pub struct CommentAttributesIterator {
x: CXComment,
length: c_uint,
index: c_uint,
}

impl Iterator for CommentAttributesIterator {
type Item = CommentAttribute;
fn next(&mut self) -> Option<CommentAttribute> {
if self.index < self.length {
let idx = self.index;
self.index += 1;
Some(CommentAttribute {
name: unsafe {
clang_HTMLStartTag_getAttrName(self.x, idx).into()
},
value: unsafe {
clang_HTMLStartTag_getAttrValue(self.x, idx).into()
},
})
} else {
None
}
}
}

/// A source file.
pub struct File {
x: CXFile,
Expand Down Expand Up @@ -1343,3 +1279,36 @@ impl Drop for EvalResult {
unsafe { clang_EvalResult_dispose(self.x) };
}
}

/// Provide a boxed iterator for foreign function call
/// Iterate over 0..f_len() and map using f
/// This function can be used with c_uint index
fn ffi_call_index_iterator<'a, FLen, F, T>
(f_len: FLen,
f: F)
-> Box<ExactSizeIterator<Item = T> + 'a>
where FLen: Fn() -> c_uint + 'a,
F: Fn(c_uint) -> T + 'a,
{
Box::new((0..f_len()).map(f))
}

/// Provide an option boxed iterator for foreign function call
/// Iterate over 0..f_len() and map using f
/// This function can be used with c_int index and only
/// returns an iterator if f_len() is positive.
fn ffi_call_index_iterator_check_positive<'a, FLen, F, T>
(f_len: FLen,
f: F)
-> Option<Box<ExactSizeIterator<Item = T> + 'a>>
where FLen: Fn() -> c_int + 'a,
F: Fn(c_int) -> T + 'a,
{
let len = f_len();
if len >= 0 {
Some(Box::new((0..len).map(f)))
} else {
assert_eq!(len, -1); // only expect -1 as invalid
None
}
}