Skip to content

Commit

Permalink
refactor: split StructAccess
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 Oct 31, 2024
1 parent b7b58c2 commit a79162f
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 196 deletions.
198 changes: 2 additions & 196 deletions src/de_mut/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod node_seq;
mod reg;
mod str_seq;
// mod r#struct;
mod struct_access;
mod structs;

const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer";
Expand All @@ -24,6 +25,7 @@ pub mod buildin {
use cursor::{BodyCursor, Cursor, PropCursor};
use data::{ValueCursor, ValueDeserializer};
use reg::RegConfig;
use struct_access::{StructAccess, StructAccessType, Temp};
use structs::{RefDtb, StructureBlock, BLOCK_LEN};

/// 从 [`RefDtb`] 反序列化一个描述设备树的 `T` 类型实例。
Expand All @@ -50,199 +52,3 @@ where
}
})
}

// For map type, we should send root item to trans dtb and reg
enum StructAccessType<'de> {
Map(bool),
Seq(&'de str),
Struct(&'static [&'static str]),
}

/// 结构体解析状态。
struct StructAccess<'de, 'b> {
access_type: StructAccessType<'de>,
temp: Temp,
de: &'b mut ValueDeserializer<'de>,
}

/// 用于跨键-值传递的临时变量。
///
/// 解析键(名字)时将确定值类型,保存 `Temp` 类型的状态。
/// 根据状态分发值解析器。
enum Temp {
Node(BodyCursor, BodyCursor),
Group(BodyCursor),
Prop(BodyCursor, PropCursor),
}

impl<'de> de::MapAccess<'de> for StructAccess<'de, '_> {
type Error = DtError;

fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: de::DeserializeSeed<'de>,
{
if let StructAccessType::Map(flag) = self.access_type {
if !flag {
return seed
.deserialize(de::value::BorrowedStrDeserializer::new("/"))
.map(Some);
}
}
let check_contains = |name: &str| -> bool {
match self.access_type {
StructAccessType::Struct(fields) => fields.contains(&name),
_ => true,
}
};
let name = loop {
let origin_cursor = match self.de.cursor {
ValueCursor::Body(cursor) => cursor,
_ => unreachable!("map access's cursor should always be body cursor"),
};
match self.de.move_on() {
// 子节点名字
Cursor::Title(c) => {
let (name, _) = c.split_on(self.de.dtb);

let pre_len = name.as_bytes().iter().take_while(|b| **b != b'@').count();
// 子节点名字不带 @ 或正在解析 Node 类型
if pre_len == name.as_bytes().len() || check_contains(name) {
let (node, next) = c.take_node_on(self.de.dtb, name);
self.de.cursor = ValueCursor::Body(next);
if check_contains(name) {
self.temp = Temp::Node(origin_cursor, node);
break name;
}
}
// @ 之前的部分是真正的名字,用这个名字搜索连续的一组
else {
let name_bytes = &name.as_bytes()[..pre_len];
let name = unsafe { core::str::from_utf8_unchecked(name_bytes) };
let (group, _, next) = c.take_group_on(self.de.dtb, name);
self.de.cursor = ValueCursor::Body(next);
if check_contains(name) {
self.temp = Temp::Group(group);
break name;
}
}
}
// 属性条目
Cursor::Prop(c) => {
let (name, next) = c.name_on(self.de.dtb);
self.de.cursor = ValueCursor::Body(next);
match name {
"#address-cells" => {
self.de.reg.address_cells = c.map_u32_on(self.de.dtb)?;
}
"#size-cells" => {
self.de.reg.size_cells = c.map_u32_on(self.de.dtb)?;
}
_ => {}
}
if check_contains(name) {
self.temp = Temp::Prop(origin_cursor, c);
break name;
}
}
// 截止符,结构体解析完成
Cursor::End => {
self.de.step_n(1);
return Ok(None);
}
}
};
seed.deserialize(de::value::BorrowedStrDeserializer::new(name))
.map(Some)
}

fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: de::DeserializeSeed<'de>,
{
if let StructAccessType::Map(ref mut flag) = self.access_type {
if !*flag {
*flag = true;
return seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: self.de.cursor,
});
}
}
match self.temp {
Temp::Node(cursor, node_cursor) => {
// 键是独立节点名字,递归
match self.access_type {
StructAccessType::Map(_) => seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(cursor),
}),
StructAccessType::Struct(_) => seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(node_cursor),
}),
_ => 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 {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Prop(origin_cursor, cursor),
})
}
}
}
}

impl<'de> de::SeqAccess<'de> for StructAccess<'de, '_> {
type Error = DtError;

fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: de::DeserializeSeed<'de>,
{
if let StructAccessType::Seq(pre_name) = self.access_type {
match self.de.move_on() {
// 子节点名字
Cursor::Title(c) => {
let (name, _) = c.split_on(self.de.dtb);
let (_, next) = c.take_node_on(self.de.dtb, name);
let prev_cursor = match self.de.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) };
if pre_name != name {
return Ok(None);
}
self.de.cursor = ValueCursor::Body(next);
seed.deserialize(&mut ValueDeserializer {
dtb: self.de.dtb,
reg: self.de.reg,
cursor: ValueCursor::Body(prev_cursor),
})
.map(Some)
}
_ => Ok(None),
}
} else {
unreachable!("SeqAccess should only be accessed by seq");
}
}
}
Loading

0 comments on commit a79162f

Please sign in to comment.