Skip to content

Commit

Permalink
refactor(NodeSeq): support name without @
Browse files Browse the repository at this point in the history
Signed-off-by: Woshiluo Luo <woshiluo.luo@outlook.com>
  • Loading branch information
woshiluo committed Jan 17, 2025
1 parent c3e7264 commit 7b165d3
Show file tree
Hide file tree
Showing 7 changed files with 144 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
13 changes: 7 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,7 @@ impl<'de> Deserialize<'de> for Node<'_> {
if key == "/" {
self_cursor = match value.cursor {
ValueCursor::Body(cursor) => Some(cursor),
ValueCursor::Prop(_, _) => {
_ => {
unreachable!("root of NodeSeq shouble be body cursor")
}
};
Expand All @@ -213,11 +213,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
6 changes: 3 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.start_cursor,
at: suf_name,
})
}
Expand Down
42 changes: 22 additions & 20 deletions src/de_mut/struct_access.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::cursor::MultiNodeCursor;
use super::{BodyCursor, Cursor, PropCursor, ValueCursor, ValueDeserializer};
use crate::error::Error as DtError;
use serde::de;
Expand All @@ -21,8 +22,8 @@ pub struct StructAccess<'de, 'b> {
/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。
/// 根据状态分发值解析器。
pub enum Temp {
Node(BodyCursor, BodyCursor),
Group(BodyCursor),
Uninit,
Nodes(MultiNodeCursor),
Prop(BodyCursor, PropCursor),
}

Expand All @@ -46,6 +47,12 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> {
_ => true,
}
};
let origin_cursor = match self.de.cursor {
ValueCursor::Body(cursor) => cursor,
ValueCursor::Node(result) => result.skip_cursor,
_ => unreachable!("map access's cursor should always be body cursor"),
};
self.de.cursor = ValueCursor::Body(origin_cursor);
let name = loop {
let origin_cursor = match self.de.cursor {
ValueCursor::Body(cursor) => cursor,
Expand All @@ -59,19 +66,19 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> {
let (pre_name, _) = name.split_once('@').unwrap_or((name, ""));
// 子节点名字不带 @ 或正在解析 Node 类型
if pre_name == name || check_contains(name) {
let (node, next) = c.take_node_on(self.de.dtb, name);
self.de.cursor = ValueCursor::Body(next);
let take_result = c.take_node_on(self.de.dtb, name);
self.de.cursor = ValueCursor::Body(take_result.next_cursor);
if check_contains(name) {
self.temp = Temp::Node(origin_cursor, node);
self.temp = Temp::Nodes(take_result);
break name;
}
}
// @ 之前的部分是真正的名字,用这个名字搜索连续的一组
else {
let (group, _, next) = c.take_group_on(self.de.dtb, pre_name);
self.de.cursor = ValueCursor::Body(next);
let take_result = c.take_group_on(self.de.dtb, pre_name);
self.de.cursor = ValueCursor::Body(take_result.next_cursor);
if check_contains(pre_name) {
self.temp = Temp::Group(group);
self.temp = Temp::Nodes(take_result);
break pre_name;
}
}
Expand Down Expand Up @@ -120,30 +127,22 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> {
}
}
match self.temp {
Temp::Node(cursor, node_cursor) => {
Temp::Nodes(ref result) => {
// 键是独立节点名字,递归
match self.access_type {
StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(cursor),
cursor: ValueCursor::Node(*result),
}),
StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(node_cursor),
cursor: ValueCursor::Node(*result),
}),
_ => unreachable!(),
}
}
Temp::Group(cursor) => {
// 键是组名字,构造组反序列化器
seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(cursor),
})
}
Temp::Prop(origin_cursor, cursor) => {
// 键是属性名字,构造属性反序列化器
seed.deserialize(&mut ValueDeserializer {
Expand All @@ -152,6 +151,9 @@ impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> {
cursor: ValueCursor::Prop(origin_cursor, cursor),
})
}
Temp::Uninit => {
unreachable!("find uninited result")
}
}
}
}
Expand All @@ -168,7 +170,7 @@ impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> {
// 子节点名字
Cursor::Title(c) => {
let (name, _) = c.split_on(self.de.dtb);
let (_, next) = c.take_node_on(self.de.dtb, name);
let next = c.take_node_on(self.de.dtb, name).next_cursor;
let prev_cursor = match self.de.cursor {
ValueCursor::Body(cursor) => cursor,
_ => unreachable!(),
Expand Down
2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<'de> Node<'de> {
}
return None;
}
return self.raw_find(path);
self.raw_find(path)
}

/// use depth-first search to traversal the tree, and exec func for each node
Expand Down
Loading

0 comments on commit 7b165d3

Please sign in to comment.