Skip to content

Commit

Permalink
Merge pull request #12 from woshiluo/chosen
Browse files Browse the repository at this point in the history
refactor(NodeSeq): support name without @
  • Loading branch information
luojia65 authored Jan 17, 2025
2 parents b3597a0 + f475d24 commit e7f9404
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 67 deletions.
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

0 comments on commit e7f9404

Please sign in to comment.