Skip to content

Commit

Permalink
Merge pull request #6 from YdrMaster/alpha3
Browse files Browse the repository at this point in the history
Alpha3
  • Loading branch information
YdrMaster authored Jul 19, 2022
2 parents 1c4d0c7 + e9e4b1f commit e724953
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 133 deletions.
38 changes: 35 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,56 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 未发布
## [0.2.0-alpha.3](https://github.com/YdrMaster/dtb-walker/releases/tag/0.2.0-alpha.3) - 2022-07-19

## Unreleased
### Change

- 删除 `Path`,增加 `Context` 类型集中处理所有从父节点向子节点传递的信息。

---

- Removes `Path` Type, and adds `Context` to handle all information passed from parent node to child node.

## [0.2.0-alpha.2](https://github.com/YdrMaster/dtb-walker/releases/tag/0.2.0-alpha.2) - 2022-07-15

### Fixed

- 不带过滤器构造 `Dtb` 时应该拒绝所有不合规范的情况,而不是全部接受

---

- Build `Dtb` without filter should reject all non-conformances, instead of accepting them all

### Added

-`&[u8]` 构造 `Dtb` 时也可以使用过滤器

---

- Provides a method to build `Dtb` from `&[u8]` with a filter

## [0.2.0-alpha.1](https://github.com/YdrMaster/dtb-walker/releases/tag/0.2.0-alpha.1) - 2022-07-12

### Changed

- 规范化更新日志格式
- 字符串统一使用一个封装的 `Str` 类型(包括节点名、属性名、`<string>` 类型的属性值、路径),类似于 `str` 但未检查是否符合 utf-8 编码
- 格式化 `Str` 不再自带引号
- 补全文档并禁止不写文档
- github ci 自动运行一次示例

---

- standardizes the change log
- uses an encapsulated `Str` type uniformly for strings (including node name, property name, property value of `<string>`, path), similar to `str` but not checked for utf-8 encoding
- will not add quotes when formating `Str`
- completes documentation and missing documentation is denied from now on

### Added

- github ci 会运行一次示例

---

- runs example during github ci

## [0.1.3](https://github.com/YdrMaster/dtb-walker/releases/tag/v0.1.3) - 2022-06-30
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "dtb-walker"
description = "A simple package for DTB depth-first walking."
version = "0.2.0-alpha.1"
version = "0.2.0-alpha.3"
edition = "2021"
authors = ["YdrMaster <[email protected]>"]
repository = "https://github.com/YdrMaster/dtb-walker.git"
Expand Down
98 changes: 98 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use crate::{tree_on_stack::Node, Str};
use core::fmt;

/// 遍历上下文。
pub struct Context<'a>(Node<'a, Inner<'a>>);

struct Inner<'a> {
name: Str<'a>,
cells: Cells,
}

impl Context<'_> {
pub(crate) const ROOT: Self = Context(Node::root(Inner {
name: Str(b""),
cells: Cells::DEFAULT,
}));

/// 返回路径层数。定义根节点的子节点层数为 0。
#[inline]
pub fn level(&self) -> usize {
self.0.level()
}

/// 如果这是根节点的路径则返回 `true`。
#[inline]
pub fn is_root(&self) -> bool {
self.0.is_root()
}

/// 返回路径最后一级的节点名。
#[inline]
pub fn name(&self) -> Str {
self.0.as_ref().name
}

#[inline]
pub(crate) fn cells(&self) -> Cells {
self.0.as_ref().cells
}

/// 将路径字符串格式化到 `buf` 中。
///
/// 如果返回 `Ok(n)`,表示字符串长度为 `n`(`n` 不大于 `buf.len()`)。
/// 如果返回 `Err(n)`,表示缓冲区长度无法存放整个字符串,实现保证 `n` 等于 `buf.len()`。
pub fn fmt_path(&self, buf: &mut [u8]) -> Result<usize, usize> {
self.0.fold(0, |len, inner| match buf.len() - len {
0 => Err(buf.len()),
mut rest => {
let bytes = inner.name.as_bytes();
buf[len] = b'/';
rest -= 1;
if bytes.len() > rest {
buf[len + 1..].copy_from_slice(&bytes[..rest]);
Err(buf.len())
} else {
buf[len + 1..][..bytes.len()].copy_from_slice(bytes);
Ok(len + bytes.len() + 1)
}
}
})
}
}

impl<'a> Context<'a> {
#[inline]
pub(crate) fn grow(&'a self, name: Str<'a>, cells: Cells) -> Self {
Self(self.0.grow(Inner { name, cells }))
}
}

impl fmt::Display for Context<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fold((), |(), inner| {
'/'.fmt(f)?;
unsafe { inner.name.as_str_unchecked() }.fmt(f)
})
}
}

#[derive(Clone, Copy)]
pub(crate) struct Cells {
pub address: u32,
pub size: u32,
pub interrupt: u32,
}

impl Cells {
pub const DEFAULT: Self = Self {
address: 2,
size: 1,
interrupt: 1,
};

#[inline]
pub fn reg_size(&self) -> usize {
(self.address + self.size) as _
}
}
28 changes: 19 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@
#![no_std]
#![deny(warnings, unstable_features, missing_docs)] // cancel this line during developing

mod context;
mod header;
mod indent;
mod path;
mod property;
mod str;
mod structure_block;
mod tree_on_stack;
mod walker;

pub use self::str::Str;
pub use path::Path;
pub use property::{PHandle, Property, Reg, StrList};
pub mod utils {
//! 用于设备树解析、格式化的工具集。
pub use crate::indent::indent;
}
pub use context::Context;
pub use header::HeaderError;

use core::{fmt, mem, slice};
Expand All @@ -50,11 +51,11 @@ impl Dtb<'static> {
/// 如果指针指向一个有效的 DTB 首部,其中描述的整个二进制对象会被切片。
#[inline]
pub unsafe fn from_raw_parts(ptr: *const u8) -> Result<Self, HeaderError> {
(*ptr.cast::<FdtHeader>()).verify(|_| true)?;
(*ptr.cast::<FdtHeader>()).verify(|_| false)?;
Ok(Self::from_raw_parts_unchecked(ptr))
}

/// 构造设备树二进制对象。
/// 构造设备树二进制对象,并可以选择接受某些不合规范的情况
///
/// # Safety
///
Expand Down Expand Up @@ -91,13 +92,16 @@ pub enum ConvertError {
}

impl<'a> Dtb<'a> {
/// 从内存切片安全地创建设备树二进制对象。
pub fn from_slice(slice: &'a [u8]) -> Result<Self, ConvertError> {
/// 从内存切片安全地创建设备树二进制对象,可以选择接受某些不合规范的情况。
pub fn from_slice_filtered(
slice: &'a [u8],
f: impl Fn(&HeaderError) -> bool,
) -> Result<Self, ConvertError> {
if slice.len() < mem::size_of::<FdtHeader>() {
return Err(ConvertError::Truncated);
}
let header = unsafe { &*slice.as_ptr().cast::<FdtHeader>() };
match header.verify(|_| true) {
match header.verify(f) {
Ok(()) => {
let len = header.totalsize.into_u32() as usize;
if len <= slice.len() {
Expand All @@ -109,6 +113,12 @@ impl<'a> Dtb<'a> {
Err(e) => Err(ConvertError::Header(e)),
}
}

/// 从内存切片安全地创建设备树二进制对象。
#[inline]
pub fn from_slice(slice: &'a [u8]) -> Result<Self, ConvertError> {
Self::from_slice_filtered(slice, |_| false)
}
}

impl Dtb<'_> {
Expand All @@ -119,7 +129,7 @@ impl Dtb<'_> {
}

/// 遍历。
pub fn walk(&self, mut f: impl FnMut(&Path<'_>, DtbObj) -> WalkOperation) {
pub fn walk(&self, mut f: impl FnMut(&Context<'_>, DtbObj) -> WalkOperation) {
let header = self.header();
let off_struct = header.off_dt_struct.into_u32() as usize;
let len_struct = header.size_dt_struct.into_u32() as usize;
Expand All @@ -137,7 +147,7 @@ impl Dtb<'_> {
},
strings: &self.0[off_strings..][..len_strings],
}
.walk_inner(&mut f, &Path::ROOT, RegCfg::DEFAULT, false);
.walk_inner(&mut f, Some(Context::ROOT));
}

#[inline]
Expand Down
74 changes: 0 additions & 74 deletions src/path.rs

This file was deleted.

12 changes: 0 additions & 12 deletions src/property/reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,3 @@ pub(crate) struct RegCfg {
pub address_cells: u32,
pub size_cells: u32,
}

impl RegCfg {
pub const DEFAULT: Self = Self {
address_cells: 2,
size_cells: 1,
};

#[inline]
pub(crate) fn item_size(&self) -> usize {
(self.address_cells + self.size_cells) as _
}
}
Loading

0 comments on commit e724953

Please sign in to comment.