Skip to content

Commit 59d640d

Browse files
authored
Merge pull request #13 from woshiluo/ser
feat: init serialize support
2 parents e7f9404 + 7d58543 commit 59d640d

28 files changed

+1236
-71
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ Cargo.lock
44

55
# Visual Studio Code configuration files
66
.vscode/
7+
*.dts

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ description = "A Device Tree blob serialization file format"
99
readme = "README.md"
1010
keywords = ["serde", "serialization"]
1111
categories = ["no-std", "encoding"]
12-
edition = "2021"
12+
edition = "2024"
1313

1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[dependencies]
1717
serde = { version = "1.0", default-features = false }
18+
erased-serde = "0.4"
1819

1920
[dev-dependencies]
2021
serde_derive = "1.0"

examples/qemu-virt.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ use serde_derive::Deserialize;
1111
// - `NodeSeq`: name@... 区分的一组同级同类的连续节点,这个类型要求可变的内存。
1212
// - `StrSeq`: '\0' 分隔的一组字符串,设备树中一种常见的属性类型,这个类型要求可变的内存。
1313
use serde_device_tree::{
14+
Dtb, DtbPtr,
1415
buildin::{Node, NodeSeq, Reg, StrSeq},
1516
error::Error,
16-
from_raw_mut, Dtb, DtbPtr,
17+
from_raw_mut,
1718
};
1819

1920
const RAW_DEVICE_TREE: &[u8] = include_bytes!("qemu-virt.dtb");

examples/re_encode.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use serde_device_tree::{Dtb, DtbPtr, buildin::Node, error::Error, from_raw_mut};
2+
3+
use std::io::prelude::*;
4+
5+
const RAW_DEVICE_TREE: &[u8] = include_bytes!("qemu-virt.dtb");
6+
const BUFFER_SIZE: usize = RAW_DEVICE_TREE.len();
7+
8+
#[repr(align(8))]
9+
struct AlignedBuffer {
10+
pub data: [u8; RAW_DEVICE_TREE.len()],
11+
}
12+
13+
fn main() -> Result<(), Error> {
14+
let mut aligned_data: Box<AlignedBuffer> = Box::new(AlignedBuffer {
15+
data: [0; BUFFER_SIZE],
16+
});
17+
aligned_data.data[..BUFFER_SIZE].clone_from_slice(RAW_DEVICE_TREE);
18+
let mut buf = [0u8; RAW_DEVICE_TREE.len() * 2];
19+
let mut slice = aligned_data.data.to_vec();
20+
let ptr = DtbPtr::from_raw(slice.as_mut_ptr())?;
21+
let dtb = Dtb::from(ptr).share();
22+
23+
let root: Node = from_raw_mut(&dtb).unwrap();
24+
serde_device_tree::ser::to_dtb(&root, &[], &mut buf).unwrap();
25+
26+
let mut file = std::fs::File::create("gen.dtb").unwrap();
27+
file.write_all(&buf).unwrap();
28+
29+
Ok(())
30+
}

examples/serialize.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use serde_derive::Serialize;
2+
use std::io::prelude::*;
3+
4+
const MAX_SIZE: usize = 256 + 32;
5+
6+
fn main() {
7+
#[derive(Serialize)]
8+
struct Base {
9+
pub hello: u32,
10+
pub base1: Base1,
11+
pub hello2: u32,
12+
pub base2: Base1,
13+
}
14+
#[derive(Serialize)]
15+
struct Base1 {
16+
pub hello: &'static str,
17+
}
18+
let mut buf1 = [0u8; MAX_SIZE];
19+
20+
{
21+
let new_base = Base1 { hello: "added" };
22+
let patch = serde_device_tree::ser::patch::Patch::new("/base3", &new_base as _);
23+
let list = [patch];
24+
let base = Base {
25+
hello: 0xdeedbeef,
26+
base1: Base1 {
27+
hello: "Hello, World!",
28+
},
29+
hello2: 0x11223344,
30+
base2: Base1 { hello: "Roger" },
31+
};
32+
serde_device_tree::ser::to_dtb(&base, &list, &mut buf1).unwrap();
33+
}
34+
let mut file = std::fs::File::create("gen.dtb").unwrap();
35+
file.write_all(&buf1).unwrap();
36+
}

rustfmt.toml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Use rustfmt to format code
2+
3+
edition = "2024"
4+
# Empty file.

src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(crate) struct Header {
1515
pub size_dt_struct: u32,
1616
}
1717

18-
const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED;
18+
pub const DEVICE_TREE_MAGIC: u32 = 0xD00DFEED;
1919
const U32_LEN: u32 = core::mem::size_of::<u32>() as _;
2020

2121
pub(crate) const ALIGN: usize = core::mem::align_of::<usize>();

src/de.rs

+19-17
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,25 @@ pub unsafe fn from_raw<'de, T>(ptr: *const u8) -> Result<T>
6868
where
6969
T: de::Deserialize<'de>,
7070
{
71-
// read header
72-
if (ptr as usize) & (ALIGN - 1) != 0 {
73-
return Err(Error::unaligned(ptr as usize));
74-
}
75-
let header = &*(ptr as *const Header);
76-
header.verify()?;
77-
78-
let total_size = u32::from_be(header.total_size);
79-
let raw_data_len = (total_size - HEADER_LEN) as usize;
80-
let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len);
81-
let device_tree: &DeviceTree = &*ans_ptr;
82-
let tags = device_tree.tags();
83-
let mut d = Deserializer {
84-
tags: tags.peekable(),
85-
};
86-
let ret = T::deserialize(&mut d)?;
87-
Ok(ret)
71+
unsafe {
72+
// read header
73+
if (ptr as usize) & (ALIGN - 1) != 0 {
74+
return Err(Error::unaligned(ptr as usize));
75+
}
76+
let header = &*(ptr as *const Header);
77+
header.verify()?;
78+
79+
let total_size = u32::from_be(header.total_size);
80+
let raw_data_len = (total_size - HEADER_LEN) as usize;
81+
let ans_ptr = core::ptr::from_raw_parts(ptr, raw_data_len);
82+
let device_tree: &DeviceTree = &*ans_ptr;
83+
let tags = device_tree.tags();
84+
let mut d = Deserializer {
85+
tags: tags.peekable(),
86+
};
87+
let ret = T::deserialize(&mut d)?;
88+
Ok(ret)
89+
}
8890
}
8991

9092
#[derive(Debug)]

src/de_mut/cursor.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{DtError, RefDtb, StructureBlock, BLOCK_LEN};
1+
use super::{BLOCK_LEN, DtError, RefDtb, StructureBlock};
22
use core::marker::PhantomData;
33

44
#[derive(Clone, Copy, Debug)]
@@ -29,10 +29,10 @@ pub enum MoveResult {
2929
}
3030

3131
#[derive(Clone, Copy, Debug)]
32-
pub(super) struct MultiNodeCursor {
32+
pub(crate) struct MultiNodeCursor {
3333
pub start_cursor: BodyCursor,
34-
pub next_cursor: BodyCursor,
3534
pub skip_cursor: BodyCursor,
35+
pub data_cursor: BodyCursor,
3636
#[allow(unused)]
3737
pub node_count: u32,
3838
}
@@ -51,6 +51,7 @@ impl<T: Type> AnyCursor<T> {
5151

5252
impl BodyCursor {
5353
pub const ROOT: Self = Self(2, PhantomData);
54+
pub const STARTER: Self = Self(0, PhantomData);
5455

5556
/// 移动到下一个项目。
5657
pub fn move_on(&mut self, dtb: RefDtb) -> Cursor {
@@ -82,6 +83,7 @@ impl BodyCursor {
8283
}
8384
todo!()
8485
}
86+
8587
/// 移动指针至下一块
8688
pub fn move_next(&mut self, dtb: RefDtb) -> MoveResult {
8789
use StructureBlock as B;
@@ -183,8 +185,8 @@ impl TitleCursor {
183185
}
184186
MultiNodeCursor {
185187
start_cursor: group,
186-
next_cursor: body,
187-
skip_cursor: title_body,
188+
skip_cursor: body,
189+
data_cursor: title_body,
188190
node_count: len,
189191
}
190192
}
@@ -201,8 +203,8 @@ impl TitleCursor {
201203
body.escape_from(dtb);
202204
MultiNodeCursor {
203205
start_cursor: origin,
204-
next_cursor: body,
205-
skip_cursor: node,
206+
skip_cursor: body,
207+
data_cursor: node,
206208
node_count: 1,
207209
}
208210
}

src/de_mut/data.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
use super::cursor::MultiNodeCursor;
1+
use super::cursor::MultiNodeCursor;
22
use super::{BodyCursor, Cursor};
33
use super::{DtError, PropCursor, RefDtb, RegConfig};
44

55
use core::marker::PhantomData;
6-
use serde::{de, Deserialize};
6+
use serde::{Deserialize, de};
77

88
#[derive(Clone, Copy, Debug)]
99
pub(super) enum ValueCursor {
1010
Body(BodyCursor),
1111
Prop(BodyCursor, PropCursor),
1212
Node(MultiNodeCursor),
13+
NodeIn(MultiNodeCursor),
1314
}
1415

1516
#[derive(Clone, Copy)]
@@ -208,8 +209,9 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
208209
visitor.visit_some(self)
209210
}
210211
}
211-
ValueCursor::Node(_) => visitor.visit_some(self),
212+
ValueCursor::NodeIn(_) => visitor.visit_some(self),
212213
ValueCursor::Body(_) => visitor.visit_some(self),
214+
ValueCursor::Node(_) => unreachable!("Node to option(NodeIn instead)"),
213215
}
214216
}
215217

@@ -251,7 +253,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
251253
{
252254
use super::{StructAccess, StructAccessType, Temp};
253255
match self.cursor {
254-
ValueCursor::Node(result) => {
256+
ValueCursor::NodeIn(result) => {
255257
let mut start_cursor = result.start_cursor;
256258
match start_cursor.move_on(self.dtb) {
257259
Cursor::Title(c) => {
@@ -302,7 +304,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
302304
{
303305
use super::{StructAccess, StructAccessType, Temp};
304306
match self.cursor {
305-
ValueCursor::Node(_) => visitor.visit_map(StructAccess {
307+
ValueCursor::NodeIn(_) => visitor.visit_map(StructAccess {
306308
access_type: StructAccessType::Map(false),
307309
temp: Temp::Uninit,
308310
de: self,
@@ -313,6 +315,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
313315
de: self,
314316
}),
315317
ValueCursor::Prop(_, _) => unreachable!("Prop -> map"),
318+
ValueCursor::Node(_) => unreachable!("Node -> map (Use NodeIn instead)"),
316319
}
317320
}
318321

@@ -327,7 +330,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
327330
{
328331
use super::{StructAccess, StructAccessType, Temp};
329332
match self.cursor {
330-
ValueCursor::Node(_) => visitor.visit_map(StructAccess {
333+
ValueCursor::NodeIn(_) => visitor.visit_map(StructAccess {
331334
access_type: StructAccessType::Struct(fields),
332335
temp: Temp::Uninit,
333336
de: self,
@@ -338,6 +341,7 @@ impl<'de> de::Deserializer<'de> for &mut ValueDeserializer<'de> {
338341
de: self,
339342
}),
340343
ValueCursor::Prop(_, _) => unreachable!("Prop -> struct {_name}"),
344+
ValueCursor::Node(_) => unreachable!("Node -> struct {_name} (Use NodeIn instead)"),
341345
}
342346
}
343347

src/de_mut/mod.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Deserialize device tree data to a Rust data structure,
1+
//! Deserialize device tree data to a Rust data structure,
22
//! the memory region contains dtb file should be mutable.
33
44
use crate::error::Error as DtError;
@@ -7,7 +7,7 @@ use serde::de;
77
mod cursor;
88
mod data;
99
// mod group;
10-
mod node;
10+
pub(crate) mod node;
1111
mod node_seq;
1212
mod reg;
1313
mod str_seq;
@@ -16,17 +16,20 @@ mod struct_access;
1616
mod structs;
1717

1818
const VALUE_DESERIALIZER_NAME: &str = "$serde_device_tree$de_mut$ValueDeserializer";
19+
pub(crate) const NODE_NAME: &str = "$serde_device_tree$de_mut$Node";
20+
pub(crate) const NODE_NODE_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$NodeItem";
21+
pub(crate) const NODE_PROP_ITEM_NAME: &str = "$serde_device_tree$de_mut$Node$PropItem";
1922

2023
pub use structs::{Dtb, DtbPtr};
2124
pub mod buildin {
2225
pub use super::{node::Node, node_seq::NodeSeq, reg::Reg, str_seq::StrSeq};
2326
}
2427

25-
use cursor::{BodyCursor, Cursor, PropCursor};
28+
use cursor::{BodyCursor, Cursor, MultiNodeCursor, PropCursor};
2629
use data::{ValueCursor, ValueDeserializer};
2730
use reg::RegConfig;
2831
use struct_access::{StructAccess, StructAccessType, Temp};
29-
use structs::{RefDtb, StructureBlock, BLOCK_LEN};
32+
use structs::{BLOCK_LEN, RefDtb, StructureBlock};
3033

3134
/// 从 [`RefDtb`] 反序列化一个描述设备树的 `T` 类型实例。
3235
///
@@ -41,7 +44,12 @@ where
4144
let mut d = ValueDeserializer {
4245
dtb,
4346
reg: RegConfig::DEFAULT,
44-
cursor: ValueCursor::Body(BodyCursor::ROOT),
47+
cursor: ValueCursor::NodeIn(MultiNodeCursor {
48+
start_cursor: BodyCursor::STARTER,
49+
skip_cursor: BodyCursor::ROOT, // This item will never be used.
50+
data_cursor: BodyCursor::ROOT,
51+
node_count: 1,
52+
}),
4553
};
4654
T::deserialize(&mut d).and_then(|t| {
4755
// 解析必须完成

0 commit comments

Comments
 (0)