Skip to content

Commit 59630a4

Browse files
committed
Improve slice detection
1 parent 80cf7b3 commit 59630a4

File tree

9 files changed

+149
-19
lines changed

9 files changed

+149
-19
lines changed

binding-generator/src/field.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,12 @@ impl<'tu, 'ge> Field<'tu, 'ge> {
190190
}
191191

192192
pub fn slice_arg_eligibility(&self) -> SliceArgEligibility {
193-
self
194-
.type_ref()
195-
.kind()
193+
let type_ref = self.type_ref();
194+
let kind = type_ref.kind();
195+
kind
196196
.as_pointer()
197197
.filter(|inner| inner.kind().is_copy(inner.type_hint()))
198+
.or_else(|| kind.as_variable_array())
198199
.map_or(SliceArgEligibility::NotEligible, |_| {
199200
let name = self.cpp_name(CppNameStyle::Declaration);
200201
let name = name.as_ref();
@@ -214,10 +215,9 @@ impl<'tu, 'ge> Field<'tu, 'ge> {
214215
if cpp == "int" || cpp == "size_t" {
215216
let name = self.cpp_name(CppNameStyle::Declaration);
216217
name.ends_with('s') && name.contains('n') && name != "thickness" // fixme: have to exclude thickness
217-
|| name.contains("dims")
218-
|| name == "size"
219-
|| name.ends_with("Size")
220-
|| name == "len"
218+
|| ["size", "len", "argc"].contains(&name.as_ref())
219+
|| name.contains("dims")
220+
|| name.ends_with("Size")
221221
} else {
222222
false
223223
}

binding-generator/src/func/slice_arg_finder.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,84 @@ enum SliceArgFinderState {
7878
SliceArgWithPotentialMultipleFound(Vec<usize>),
7979
LenArgFound(usize),
8080
}
81+
82+
#[cfg(test)]
83+
mod test {
84+
use super::SliceArgFinder;
85+
use crate::field::{Field, FieldDesc};
86+
use crate::type_ref::{TypeRef, TypeRefDesc};
87+
88+
#[test]
89+
fn test_slice_arg_finder() {
90+
// one arg, not slice
91+
{
92+
let mut finder = SliceArgFinder::with_capacity(0);
93+
finder.feed(0, &Field::new_desc(FieldDesc::new("src", TypeRefDesc::int())));
94+
assert_eq!(finder.finish(), vec![]);
95+
}
96+
97+
// slice len after
98+
{
99+
let mut finder = SliceArgFinder::with_capacity(0);
100+
finder.feed(
101+
0,
102+
&Field::new_desc(FieldDesc::new("dims", TypeRef::new_pointer(TypeRefDesc::float()))),
103+
);
104+
finder.feed(1, &Field::new_desc(FieldDesc::new("ndims", TypeRefDesc::size_t())));
105+
assert_eq!(finder.finish(), vec![(vec![0], 1)]);
106+
}
107+
108+
// slice len first
109+
{
110+
let mut finder = SliceArgFinder::with_capacity(0);
111+
finder.feed(0, &Field::new_desc(FieldDesc::new("argc", TypeRefDesc::int())));
112+
finder.feed(
113+
1,
114+
&Field::new_desc(FieldDesc::new("argv", TypeRef::new_array(TypeRefDesc::char_ptr(), None))),
115+
);
116+
assert_eq!(finder.finish(), vec![(vec![1], 0)]);
117+
}
118+
119+
// slice name prevents eligibility
120+
{
121+
let mut finder = SliceArgFinder::with_capacity(0);
122+
finder.feed(
123+
0,
124+
&Field::new_desc(FieldDesc::new("rmsd", TypeRef::new_pointer(TypeRefDesc::float()))),
125+
);
126+
finder.feed(1, &Field::new_desc(FieldDesc::new("ndims", TypeRefDesc::size_t())));
127+
assert_eq!(finder.finish(), vec![]);
128+
}
129+
130+
// 2 slices with 1 length
131+
{
132+
let mut finder = SliceArgFinder::with_capacity(0);
133+
finder.feed(
134+
0,
135+
&Field::new_desc(FieldDesc::new("a", TypeRef::new_pointer(TypeRefDesc::float()))),
136+
);
137+
finder.feed(
138+
1,
139+
&Field::new_desc(FieldDesc::new("b", TypeRef::new_pointer(TypeRefDesc::int()))),
140+
);
141+
finder.feed(2, &Field::new_desc(FieldDesc::new("abSize", TypeRefDesc::int())));
142+
assert_eq!(finder.finish(), vec![(vec![0, 1], 2)]);
143+
}
144+
145+
// 2 sets of slices with lengths
146+
{
147+
let mut finder = SliceArgFinder::with_capacity(0);
148+
finder.feed(
149+
0,
150+
&Field::new_desc(FieldDesc::new("a", TypeRef::new_pointer(TypeRefDesc::float()))),
151+
);
152+
finder.feed(1, &Field::new_desc(FieldDesc::new("aSize", TypeRefDesc::int())));
153+
finder.feed(
154+
2,
155+
&Field::new_desc(FieldDesc::new("b", TypeRef::new_pointer(TypeRefDesc::uint64_t()))),
156+
);
157+
finder.feed(3, &Field::new_desc(FieldDesc::new("len", TypeRefDesc::int())));
158+
assert_eq!(finder.finish(), vec![(vec![0], 1), (vec![2], 3)]);
159+
}
160+
}
161+
}

binding-generator/src/type_ref/desc.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ impl<'tu, 'ge> TypeRefDesc<'tu, 'ge> {
8282
Self::try_primitive("char").expect("Static primitive type")
8383
}
8484

85+
pub fn char_ptr() -> TypeRef<'tu, 'ge> {
86+
TypeRef::new_pointer(Self::char())
87+
}
88+
89+
pub fn char_const_ptr() -> TypeRef<'tu, 'ge> {
90+
TypeRef::new_pointer(Self::char().with_inherent_constness(Constness::Const))
91+
}
92+
8593
pub fn uchar() -> TypeRef<'tu, 'ge> {
8694
Self::try_primitive("unsigned char").expect("Static primitive type")
8795
}
@@ -375,10 +383,7 @@ impl<'tu> ClangTypeExt<'tu> for Type<'tu> {
375383
let pointee_kind = pointee_typeref.kind();
376384
if pointee_kind.is_function() {
377385
pointee_kind.into_owned()
378-
} else if matches!(
379-
pointee_typeref.type_hint(),
380-
TypeRefTypeHint::Slice | TypeRefTypeHint::NullableSlice
381-
) {
386+
} else if matches!(pointee_typeref.type_hint(), TypeRefTypeHint::Slice) {
382387
TypeRefKind::Array(pointee_typeref, None)
383388
} else {
384389
TypeRefKind::Pointer(pointee_typeref)

binding-generator/src/type_ref/kind.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,3 +486,48 @@ pub enum InputOutputArrayKind {
486486
Output,
487487
InputOutput,
488488
}
489+
490+
#[cfg(test)]
491+
mod tests {
492+
use crate::type_ref::{Dir, StrEnc, StrType, TypeRef, TypeRefDesc, TypeRefTypeHint};
493+
494+
fn as_string(type_ref: TypeRef) -> Option<(Dir, StrType)> {
495+
type_ref.kind().as_string(type_ref.type_hint())
496+
}
497+
498+
#[test]
499+
fn test_as_string_char_ptr() {
500+
{
501+
let char = TypeRefDesc::char();
502+
assert_eq!(None, as_string(char));
503+
}
504+
505+
{
506+
let char_ptr = TypeRefDesc::char_ptr();
507+
assert_eq!(Some((Dir::Out, StrType::CharPtr(StrEnc::Text))), as_string(char_ptr));
508+
}
509+
510+
{
511+
let char_ptr_const = TypeRefDesc::char_const_ptr();
512+
assert_eq!(Some((Dir::In, StrType::CharPtr(StrEnc::Text))), as_string(char_ptr_const));
513+
}
514+
515+
{
516+
let char_ptr_const_slice = TypeRefDesc::char_const_ptr().with_type_hint(TypeRefTypeHint::StringAsBytes(None));
517+
assert_eq!(
518+
Some((Dir::In, StrType::CharPtr(StrEnc::Binary))),
519+
as_string(char_ptr_const_slice)
520+
);
521+
}
522+
523+
{
524+
let single_char_ptr = TypeRefDesc::char_ptr().with_type_hint(TypeRefTypeHint::CharPtrSingleChar);
525+
assert_eq!(None, as_string(single_char_ptr));
526+
}
527+
528+
{
529+
let char_array = TypeRef::new_array(TypeRefDesc::char(), None);
530+
assert_eq!(Some((Dir::In, StrType::CharPtr(StrEnc::Text))), as_string(char_array));
531+
}
532+
}
533+
}

binding-generator/src/type_ref/types.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl CppNameStyle {
199199
}
200200
}
201201

202-
#[derive(Clone, Copy, Debug)]
202+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
203203
pub enum StrType {
204204
StdString(StrEnc),
205205
CvString(StrEnc),
@@ -221,14 +221,14 @@ impl StrType {
221221
}
222222
}
223223

224-
#[derive(Clone, Copy, Debug)]
224+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
225225
pub enum StrEnc {
226226
Text,
227227
/// string with binary data, e.g. can contain 0 byte
228228
Binary,
229229
}
230230

231-
#[derive(Clone, Copy, Debug)]
231+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
232232
pub enum Dir {
233233
In,
234234
Out,

examples/create_mask.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ enum DrawingState {
3232

3333
fn main() -> Result<()> {
3434
let args: Vec<String> = env::args().collect();
35-
let (argc, argv) = (args.len() as i32, args.iter().map(|s| s.as_str()).collect::<Vec<&str>>());
35+
let argv = args.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
3636

37-
let mut parser = CommandLineParser::new(argc, &argv, "{@input | lena.jpg | input image}")?;
37+
let mut parser = CommandLineParser::new(&argv, "{@input | lena.jpg | input image}")?;
3838
parser.about("This program demonstrates using mouse events\n")?;
3939
parser.print_message()?;
4040
println!(

examples/dnn_face_detect.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ fn main() -> Result<()> {
111111
let args = env::args().collect::<Vec<_>>();
112112
let args = args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>();
113113
let parser = CommandLineParser::new(
114-
i32::try_from(args.len()).expect("Too many arguments"),
115114
&args,
116115
concat!(
117116
"{help h | | Print this message}",

examples/text_detection.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const KEYS: &str = concat!(
3333
pub fn main() -> Result<()> {
3434
let args = env::args().collect::<Vec<_>>();
3535
let args = args.iter().map(|arg| arg.as_str()).collect::<Vec<_>>();
36-
let mut parser = CommandLineParser::new(i32::try_from(args.len()).expect("Too many arguments"), &args, KEYS)?;
36+
let mut parser = CommandLineParser::new(&args, KEYS)?;
3737
parser.about(
3838
"Use this script to run TensorFlow implementation (https://github.com/argman/EAST) of \
3939
EAST: An Efficient and Accurate Scene Text Detector (https://arxiv.org/abs/1704.03155v2)",

tests/marshalling.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ fn tuple() -> Result<()> {
273273
#[test]
274274
fn string_array() -> Result<()> {
275275
let args = ["test", "-a=b"];
276-
let mut parser = CommandLineParser::new(i32::try_from(args.len())?, &args, "{a | | }")?;
276+
let parser = CommandLineParser::new(&args, "{a | | }")?;
277277
assert!(parser.has("a")?);
278278
assert_eq!("b", parser.get_str("a", true)?);
279279
Ok(())

0 commit comments

Comments
 (0)