Skip to content

refactor(NodeSeq): support name without @ #12

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

Merged
merged 2 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
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
31 changes: 26 additions & 5 deletions src/de_mut/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ pub enum MoveResult {
Others,
}

#[derive(Clone, Copy, Debug)]
pub(super) struct MultiNodeCursor {
pub start_cursor: BodyCursor,
pub next_cursor: BodyCursor,
pub skip_cursor: BodyCursor,
#[allow(unused)]
pub node_count: u32,
}

impl<T: Type> AnyCursor<T> {
/// 移动 `n` 格。
pub fn step_n(&mut self, len: usize) {
Expand Down Expand Up @@ -147,12 +156,13 @@ impl TitleCursor {
}

/// 生成组光标。
pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> (BodyCursor, usize, BodyCursor) {
pub fn take_group_on(&self, dtb: RefDtb, name: &str) -> MultiNodeCursor {
let name_bytes = name.as_bytes();
let name_skip = align(name_bytes.len() + 1, BLOCK_LEN);
let group = AnyCursor::<Body>(self.0, PhantomData);

let mut body = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData);
let title_body = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData);
let mut body = title_body;
let mut len = 1;

let structure = &dtb.borrow().structure;
Expand All @@ -171,19 +181,30 @@ impl TitleCursor {
}
break;
}
(group, len, body)
MultiNodeCursor {
start_cursor: group,
next_cursor: body,
skip_cursor: title_body,
node_count: len,
}
}

/// 生成节点光标。
pub fn take_node_on(&self, dtb: RefDtb, name: &str) -> (BodyCursor, BodyCursor) {
pub fn take_node_on(&self, dtb: RefDtb, name: &str) -> MultiNodeCursor {
let name_bytes = name.as_bytes();
let name_skip = align(name_bytes.len() + 1, BLOCK_LEN);
let origin = AnyCursor::<Body>(self.0, PhantomData);
let node = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData);

let mut body = AnyCursor::<Body>(self.0 + 1 + name_skip, PhantomData);

body.escape_from(dtb);
(node, body)
MultiNodeCursor {
start_cursor: origin,
next_cursor: body,
skip_cursor: node,
node_count: 1,
}
}
}

Expand Down
82 changes: 50 additions & 32 deletions src/de_mut/data.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use super::{BodyCursor, Cursor};
use super::cursor::MultiNodeCursor;
use super::{BodyCursor, Cursor};
use super::{DtError, PropCursor, RefDtb, RegConfig};

use core::marker::PhantomData;
use serde::{de, Deserialize};

#[derive(Clone, Copy, Debug)]
pub(super) enum ValueCursor {
Prop(BodyCursor, PropCursor),
Body(BodyCursor),
Prop(BodyCursor, PropCursor),
Node(MultiNodeCursor),
}

#[derive(Clone, Copy)]
Expand Down Expand Up @@ -206,6 +208,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
visitor.visit_some(self)
}
}
ValueCursor::Node(_) => visitor.visit_some(self),
ValueCursor::Body(_) => visitor.visit_some(self),
}
}
Expand Down Expand Up @@ -247,25 +250,30 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
V: de::Visitor<'de>,
{
use super::{StructAccess, StructAccessType, Temp};
match self.move_on() {
Cursor::Title(c) => {
let (name, _) = c.split_on(self.dtb);
let cursor = match self.cursor {
ValueCursor::Body(cursor) => cursor,
_ => unreachable!(""),
};

let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count();
let name_bytes = &name.as_bytes()[..pre_len];
let name = unsafe { core::str::from_utf8_unchecked(name_bytes) };

visitor.visit_seq(StructAccess {
access_type: StructAccessType::Seq(name),
temp: Temp::Node(cursor, cursor),
de: self,
})
match self.cursor {
ValueCursor::Node(result) => {
let mut start_cursor = result.start_cursor;
match start_cursor.move_on(self.dtb) {
Cursor::Title(c) => {
let (name, _) = c.split_on(self.dtb);

let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count();
let name_bytes = &name.as_bytes()[..pre_len];
let name = unsafe { core::str::from_utf8_unchecked(name_bytes) };

let de = self;
de.cursor = ValueCursor::Body(start_cursor);

visitor.visit_seq(StructAccess {
access_type: StructAccessType::Seq(name),
temp: Temp::Uninit,
de,
})
}
_ => unreachable!("seq request on a none seq cursor"),
}
}
_ => unreachable!("seq request on a none seq cursor"),
_ => unreachable!("Seq request on a not-node cursor"),
}
}

Expand Down Expand Up @@ -293,14 +301,19 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
V: de::Visitor<'de>,
{
use super::{StructAccess, StructAccessType, Temp};
if let ValueCursor::Body(cursor) = self.cursor {
return visitor.visit_map(StructAccess {
match self.cursor {
ValueCursor::Node(_) => visitor.visit_map(StructAccess {
access_type: StructAccessType::Map(false),
temp: Temp::Node(cursor, cursor),
temp: Temp::Uninit,
de: self,
});
};
unreachable!("Prop -> map")
}),
ValueCursor::Body(_) => visitor.visit_map(StructAccess {
access_type: StructAccessType::Map(false),
temp: Temp::Uninit,
de: self,
}),
ValueCursor::Prop(_, _) => unreachable!("Prop -> map"),
}
}

fn deserialize_struct<V>(
Expand All @@ -313,14 +326,19 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
V: de::Visitor<'de>,
{
use super::{StructAccess, StructAccessType, Temp};
if let ValueCursor::Body(cursor) = self.cursor {
return visitor.visit_map(StructAccess {
match self.cursor {
ValueCursor::Node(_) => visitor.visit_map(StructAccess {
access_type: StructAccessType::Struct(fields),
temp: Temp::Node(cursor, cursor),
temp: Temp::Uninit,
de: self,
});
};
unreachable!("Prop -> struct {_name} {fields:?}")
}),
ValueCursor::Body(_) => visitor.visit_map(StructAccess {
access_type: StructAccessType::Struct(fields),
temp: Temp::Uninit,
de: self,
}),
ValueCursor::Prop(_, _) => unreachable!("Prop -> struct {_name}"),
}
}

fn deserialize_enum<V>(
Expand Down
14 changes: 8 additions & 6 deletions src/de_mut/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ impl<'de> Iterator for NodeIter<'de, '_> {
let dtb = self.node.dtb;
if let Cursor::Title(c) = cursor.move_on(dtb) {
let (name, _) = c.split_on(dtb);
let (node_cursor, next) = c.take_node_on(dtb, name);
let node_cursor = c.take_node_on(dtb, name);
let res = Some(Self::Item {
dtb,
reg: self.node.reg,
node: node_cursor,
node: node_cursor.skip_cursor,
name,
});
*cursor = next;
*cursor = node_cursor.next_cursor;
res
} else {
None
Expand Down Expand Up @@ -201,7 +201,8 @@ impl<'de> Deserialize<'de> for Node<'_> {
if key == "/" {
self_cursor = match value.cursor {
ValueCursor::Body(cursor) => Some(cursor),
ValueCursor::Prop(_, _) => {
ValueCursor::Node(result) => Some(result.next_cursor),
_ => {
unreachable!("root of NodeSeq shouble be body cursor")
}
};
Expand All @@ -213,11 +214,12 @@ impl<'de> Deserialize<'de> for Node<'_> {
props_start = Some(cursor);
}
}
ValueCursor::Body(cursor) => {
ValueCursor::Node(cursor) => {
if nodes_start.is_none() {
nodes_start = Some(cursor);
nodes_start = Some(cursor.start_cursor);
}
}
_ => unreachable!("unparsed(body) cursor"),
}
}

Expand Down
87 changes: 84 additions & 3 deletions src/de_mut/node_seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,19 @@ impl<'de> Iterator for NodeSeqIter<'de, '_> {
// 子节点名字
Cursor::Title(c) => {
let (full_name, _) = c.split_on(self.de.dtb);
let (node, next) = c.take_node_on(self.de.dtb, full_name);
let node_reuslt = c.take_node_on(self.de.dtb, full_name);

let (pre_name, suf_name) = full_name.split_once('@').unwrap_or((full_name, ""));
if self.seq.name != pre_name {
return None;
}

self.de.cursor = ValueCursor::Body(next);
self.de.cursor = ValueCursor::Body(node_reuslt.next_cursor);

Some(Self::Item {
dtb: self.de.dtb,
reg: self.de.reg,
body: node,
body: node_reuslt.skip_cursor,
at: suf_name,
})
}
Expand Down Expand Up @@ -173,3 +173,84 @@ impl<'de> NodeSeqItem<'de> {
.unwrap()
}
}

#[cfg(test)]
mod tests {
use crate::buildin::{NodeSeq, Reg};
use crate::{from_raw_mut, Dtb, DtbPtr};
use serde_derive::Deserialize;

const RAW_DEVICE_TREE: &[u8] = include_bytes!("../../examples/bl808.dtb");
const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len();
const RAW_DEVICE_TREE_QEMU: &[u8] = include_bytes!("../../examples/qemu-virt.dtb");
const BUFFER_SIZE_QEMU: usize = RAW_DEVICE_TREE_QEMU.len();
#[derive(Deserialize)]
pub struct Tree<'a> {
/// Memory information.
pub memory: NodeSeq<'a>,
}
/// Memory range.
#[derive(Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct Memory<'a> {
pub reg: Reg<'a>,
}
#[test]
fn test_nodeseq_without_at() {
#[repr(align(8))]
struct AlignedBuffer {
pub data: [u8; RAW_DEVICE_TREE.len()],
}
let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer {
data: [0; BUFFER_SIZE],
});
aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE);
let mut slice = aligned_data.data.to_vec();
let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap();
let dtb = Dtb::from(ptr).share();

let t: Tree = from_raw_mut(&dtb).unwrap();
assert_eq!(t.memory.len(), 1);
let range = t
.memory
.iter()
.next()
.unwrap()
.deserialize::<Memory>()
.reg
.iter()
.next()
.unwrap()
.0;
assert_eq!(range, 1342177280..1408237568);
}
#[test]
fn test_nodeseq_with_at() {
#[repr(align(8))]
struct AlignedBuffer {
pub data: [u8; RAW_DEVICE_TREE_QEMU.len()],
}
let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer {
data: [0; BUFFER_SIZE_QEMU],
});
aligned_data.data[..BUFFER_SIZE_QEMU].clone_from_slice(RAW_DEVICE_TREE_QEMU);
let mut slice = aligned_data.data.to_vec();
let ptr = DtbPtr::from_raw(slice.as_mut_ptr()).unwrap();
let dtb = Dtb::from(ptr).share();

let t: Tree = from_raw_mut(&dtb).unwrap();
assert_eq!(t.memory.len(), 1);
let range = t
.memory
.iter()
.next()
.unwrap()
.deserialize::<Memory>()
.reg
.iter()
.next()
.unwrap()
.0;
assert_eq!(range, 2147483648..6442450944);
}
}
Loading
Loading