Skip to content

Commit fe12193

Browse files
committed
value: describe 'compatible' in null separated Compatible structure
Signed-off-by: Zhouqi Jiang <luojia@hust.edu.cn>
1 parent c75529d commit fe12193

File tree

6 files changed

+90
-6
lines changed

6 files changed

+90
-6
lines changed

examples/hifive-unmatched-a00.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ extern crate alloc;
22

33
use alloc::collections::BTreeMap;
44
use serde_derive::Deserialize;
5+
use serde_device_tree::Compatible;
56

67
static DEVICE_TREE: &'static [u8] = include_bytes!("hifive-unmatched-a00.dtb");
78

@@ -12,7 +13,7 @@ struct Tree<'a> {
1213
#[serde(rename = "#size-cells")]
1314
num_size_cells: u32,
1415
model: &'a str,
15-
compatible: &'a str,
16+
compatible: Compatible<'a>,
1617
chosen: Option<Chosen<'a>>,
1718
cpus: Cpus<'a>,
1819
}
@@ -43,7 +44,8 @@ enum MaybeCpu<'a> {
4344

4445
#[derive(Debug, Deserialize)]
4546
struct Cpu<'a> {
46-
compatible: &'a str,
47+
#[serde(borrow)]
48+
compatible: Compatible<'a>,
4749
}
4850

4951
fn main() {
@@ -52,7 +54,7 @@ fn main() {
5254
println!("#address_cells = {}", t.num_address_cells);
5355
println!("#size_cells = {}", t.num_size_cells);
5456
println!("model = {}", t.model);
55-
println!("compatible = {}", t.compatible);
57+
println!("compatible = {:?}", t.compatible);
5658
if let Some(chosen) = t.chosen {
5759
if let Some(stdout_path) = chosen.stdout_path {
5860
println!("stdout = {}", stdout_path);
@@ -64,7 +66,7 @@ fn main() {
6466
println!("cpu u_boot_dm_spl = {}", t.cpus.u_boot_dm_spl);
6567
for (cpu_name, cpu) in t.cpus.cpu {
6668
if let MaybeCpu::Cpu(cpu) = cpu {
67-
println!("cpu {}, compaible = {}", cpu_name, cpu.compatible)
69+
println!("cpu {}, compaible = {:?}", cpu_name, cpu.compatible)
6870
}
6971
}
7072
}

examples/qemu-virt.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! 这是一个 `from_raw_mut` 反序列化设备树的示例。不需要 `alloc`。
1+
//! 这是一个 `from_raw_mut` 反序列化设备树的示例。不需要 `alloc`。
22
// extern crate alloc;
33

44
// 在实际使用中,将这里的 `serde_derive::Deserialize` 改为 `serde::Deserialize`。
@@ -12,7 +12,8 @@ use serde_derive::Deserialize;
1212
// - `StrSeq`: '\0' 分隔的一组字符串,设备树中一种常见的属性类型,这个类型要求可变的内存。
1313
use serde_device_tree::{
1414
buildin::{NodeSeq, Reg, StrSeq},
15-
from_raw_mut, Dtb, DtbPtr, error::Error,
15+
error::Error,
16+
from_raw_mut, Dtb, DtbPtr,
1617
};
1718

1819
fn main() -> Result<(), Error> {

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub mod error;
2323

2424
mod common;
2525
mod de_mut;
26+
mod value;
27+
28+
pub use value::compatible::Compatible;
2629

2730
#[doc(inline)]
2831
pub use de::from_raw;

src/value/compatible.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use core::{fmt, marker::PhantomData};
2+
use serde::{de::Visitor, Deserialize};
3+
4+
/// Field representing compatability of a certain device in the tree.
5+
///
6+
/// This structure is represented in a list of string that is separated with Unicode `NUL` character.
7+
pub struct Compatible<'a> {
8+
data: &'a [u8],
9+
}
10+
11+
impl<'a> Compatible<'a> {
12+
pub fn iter(&self) -> Iter<'a> {
13+
Iter {
14+
remaining: self.data,
15+
}
16+
}
17+
}
18+
19+
impl<'de: 'a, 'a> Deserialize<'de> for Compatible<'a> {
20+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
21+
where
22+
D: serde::Deserializer<'de>,
23+
{
24+
struct StrListVisitor<'de, 'a>(PhantomData<&'de ()>, PhantomData<Compatible<'a>>);
25+
impl<'de: 'a, 'a> Visitor<'de> for StrListVisitor<'de, 'a> {
26+
type Value = Compatible<'a>;
27+
28+
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> std::fmt::Result {
29+
write!(formatter, "string list")
30+
}
31+
32+
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
33+
where
34+
E: serde::de::Error,
35+
{
36+
// TODO utf-8 check
37+
Ok(Compatible { data: v })
38+
}
39+
}
40+
deserializer.deserialize_bytes(StrListVisitor(PhantomData, PhantomData))
41+
}
42+
}
43+
44+
impl fmt::Debug for Compatible<'_> {
45+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46+
f.debug_list().entries(self.iter()).finish()
47+
}
48+
}
49+
50+
pub struct Iter<'a> {
51+
remaining: &'a [u8],
52+
}
53+
54+
impl<'a> Iterator for Iter<'a> {
55+
type Item = &'a str;
56+
57+
fn next(&mut self) -> Option<Self::Item> {
58+
if self.remaining.len() == 0 {
59+
return None;
60+
}
61+
let mut idx = 0;
62+
while let Some(byte) = self.remaining.get(idx) {
63+
if byte == &b'\0' {
64+
break;
65+
}
66+
idx += 1;
67+
}
68+
let (ans, rest) = self.remaining.split_at(idx);
69+
if let [0, ..] = rest {
70+
// skip '\0'
71+
self.remaining = &rest[1..];
72+
}
73+
Some(core::str::from_utf8(ans).unwrap())
74+
}
75+
}

src/value/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod compatible;
2+
mod tree;

src/value/tree.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// TODO reference to a device tree

0 commit comments

Comments
 (0)