Skip to content

Commit 9dc7220

Browse files
committed
rust: adt: Add adt property string iterator
This will be used to check all compatible strings in `adt_is_compatible()`. For now use it to implement ADTNode::compatible() returning the n-th compatible string on rust side and the C wrapper function adt_is_compatible_at(). Signed-off-by: Janne Grunau <[email protected]>
1 parent 3529228 commit 9dc7220

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

rust/src/adt.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,38 @@ pub struct ADTProperty {
3737
value: [u8],
3838
}
3939

40+
/// ADTPropertyStringIterator
41+
#[derive(Debug)]
42+
pub struct ADTPropertyStringIterator<'a> {
43+
value: &'a [u8],
44+
}
45+
46+
impl<'a> Iterator for ADTPropertyStringIterator<'a> {
47+
type Item = &'a str;
48+
49+
fn next(&mut self) -> Option<&'a str> {
50+
match CStr::from_bytes_until_nul(self.value) {
51+
Ok(cs) => match cs.to_str() {
52+
Ok(s) => {
53+
match self.value.iter().position(|&x| x == 0) {
54+
Some(nul) => self.value = &self.value[(nul + 1)..],
55+
None => self.value = &[],
56+
}
57+
Some(s)
58+
}
59+
Err(_) => {
60+
self.value = &[];
61+
None
62+
}
63+
},
64+
Err(_) => {
65+
self.value = &[];
66+
None
67+
}
68+
}
69+
}
70+
}
71+
4072
#[repr(C, packed(1))]
4173
pub struct ADTSegmentRanges {
4274
phys: u64,
@@ -423,6 +455,11 @@ impl ADTNode {
423455
pub fn is_compatible(&self, compatible: &str) -> Result<bool, AdtError> {
424456
Ok(self.named_prop("compatible")?.str()?.contains(compatible))
425457
}
458+
459+
pub fn compatible(&self, index: usize) -> Option<&str> {
460+
let prop = self.named_prop("compatible").ok()?;
461+
prop.str_iter().nth(index)
462+
}
426463
}
427464

428465
impl ADTProperty {
@@ -534,6 +571,12 @@ impl ADTProperty {
534571
}
535572
}
536573

574+
pub fn str_iter<'a>(&'a self) -> ADTPropertyStringIterator<'a> {
575+
ADTPropertyStringIterator {
576+
value: unsafe { core::slice::from_raw_parts(self.value.as_ptr(), self.size as usize) },
577+
}
578+
}
579+
537580
pub fn set(&mut self, val: &[u8]) -> Result<usize, AdtError> {
538581
if val.len() != self.size as usize {
539582
return Err(AdtError::BadLength);
@@ -769,6 +812,18 @@ pub unsafe extern "C" fn adt_is_compatible(
769812
.unwrap()
770813
}
771814

815+
#[no_mangle]
816+
pub unsafe extern "C" fn adt_is_compatible_at(
817+
_dt: *const c_void,
818+
offset: c_int,
819+
compat: *const c_char,
820+
index: usize,
821+
) -> bool {
822+
let strcompat: &str = unsafe { CStr::from_ptr(compat).to_str().unwrap() };
823+
let ptr: *const ADTNode = unsafe { adt.add(offset as usize) as *const ADTNode };
824+
ADTNode::from_ptr(ptr).unwrap().compatible(index).unwrap() == strcompat
825+
}
826+
772827
#[no_mangle]
773828
pub unsafe extern "C" fn adt_get_name(_dt: *const c_void, offset: c_int) -> *const c_char {
774829
let ptr: *const ADTNode = unsafe { adt.add(offset as usize) as *const ADTNode };

src/adt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ int adt_getprop_copy(const void *adt, int nodeoffset, const char *name, void *ou
5656

5757
int adt_get_reg(const void *adt, int *path, const char *prop, int idx, u64 *addr, u64 *size);
5858
bool adt_is_compatible(const void *adt, int nodeoffset, const char *compat);
59+
bool adt_is_compatible_at(const void *adt, int nodeoffset, const char *compat, size_t index);
5960

6061
#define ADT_FOREACH_CHILD(adt, node) \
6162
for (int _child_count = adt_get_child_count(adt, node); _child_count; _child_count = 0) \

0 commit comments

Comments
 (0)