Skip to content

Commit

Permalink
[breaking] better builder; unified lint settings
Browse files Browse the repository at this point in the history
  • Loading branch information
kadiwa4 committed Feb 12, 2024
1 parent af0a999 commit 17e4863
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 44 deletions.
19 changes: 15 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
[workspace]
members = ["deforest_derive"]

[workspace.lints.rust]
rust_2018_idioms = "warn"
macro_use_extern_crate = "warn"
meta_variable_misuse = "warn"
missing_abi = "warn"
unused_macro_rules = "warn"
unused_qualifications = "warn"

[package]
name = "deforest"
version = "0.2.0"
edition = "2021"
rust-version = "1.73"
rust-version = "1.74"
description = "efficient `#![no_std]` parser for devicetree blobs"
repository = "https://github.com/kadiwa4/deforest"
license = "MIT"
Expand All @@ -15,6 +23,9 @@ include = ["/README.md", "/src", "/examples", "/tests"]

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

[package.metadata.docs.rs]
all-features = true

[[example]]
name = "borrowed_model"
crate-type = ["lib"]
Expand All @@ -35,13 +46,13 @@ required-features = ["alloc"]
ascii = { version = "1.1.0", default-features = false }
deforest_derive = { path = "deforest_derive", version = "=0.1.0", optional = true }
fallible-iterator = { version = "0.3.0", default-features = false }
zerocopy = { version = "0.7.6", default-features = false, features = ["derive"] }
zerocopy = { version = "0.7.31", default-features = false, features = ["derive"] }

[features]
alloc = ["fallible-iterator/alloc"]
derive = ["deforest_derive"]
model = []
std = ["alloc", "fallible-iterator/std"]

[package.metadata.docs.rs]
all-features = true
[lints]
workspace = true
9 changes: 6 additions & 3 deletions deforest_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ path = "lib.rs"
proc-macro = true

[dependencies]
proc-macro2 = "1.0.54"
quote = "1.0.26"
syn = { version = "2.0.12", features = ["full"] }
proc-macro2 = "1.0.69"
quote = "1.0.28"
syn = { version = "2.0.40", features = ["full"] }

[features]

[lints]
workspace = true
6 changes: 1 addition & 5 deletions deforest_derive/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#![warn(rust_2018_idioms)]
#![warn(macro_use_extern_crate, meta_variable_misuse, missing_abi)]
#![warn(unused_lifetimes, unused_macro_rules, unused_qualifications)]

use proc_macro2::{Literal, TokenStream, TokenTree};
use quote::{quote, ToTokens};
use syn::{
Expand Down Expand Up @@ -34,7 +30,7 @@ enum ItemKind {
/// - `#[dt(child = \"<node name>\")]`
/// - `#[dt(children)]`
/// - `#[dt(children = \"<node name>\")]`
/// - `#[dt(children(rest))]
/// - `#[dt(children(rest))]`
///
/// The default item name is the field name with undescores replaced by hyphens
/// (and a `#` prepended in case the name ends with `_cells`), except
Expand Down
57 changes: 32 additions & 25 deletions src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,46 @@ use fallible_iterator::FallibleIterator;
use crate::{
blob::{self, Cursor, Devicetree, Item, Node, Property},
prop_value::{self, RegBlock},
DeserializeNode, DeserializeProperty, NodeContext, Path, PushDeserializedNode, ReserveEntry,
Result,
DeserializeNode, DeserializeProperty, Error, NodeContext, Path, PushDeserializedNode,
ReserveEntry, Result,
};

/// Starting point for constructing a [`Devicetree`] yourself.
#[derive(Clone, Default)]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct DevicetreeBuilder<'a> {
/// Defaults to 0.
pub boot_core_id: u32,
/// Defaults to an empty slice.
pub reserve_entries: &'a [ReserveEntry],
/// Mandatory.
pub struct_blob: Option<&'a [u32]>,
/// Mandatory.
pub strings_blob: Option<&'a [u8]>,
}
/// Blob of the struct block.
pub struct_blob: &'a [u32],
/// Blob of the strings block.
pub strings_blob: &'a [u8],
}

impl<'a> DevicetreeBuilder<'a> {
/// Constructs a new builder.
pub const fn new(struct_blob: &'a [u32], strings_blob: &'a [u8]) -> Self {
Self {
boot_core_id: 0,
reserve_entries: &[],
struct_blob,
strings_blob,
}
}

impl DevicetreeBuilder<'_> {
/// Constructs the devicetree. Returns `None` if it is too large.
pub fn build(&self) -> Option<Box<Devicetree>> {
pub fn build(&self) -> Result<Box<Devicetree>> {
const HEADER_SIZE_ALIGN_RATIO: usize = blob::HEADER_SIZE / blob::DTB_ALIGN;

let struct_blob = self.struct_blob.expect("builder has no struct blob");
let strings_blob = self.strings_blob.expect("builder has no strings blob");

let struct_offset =
blob::HEADER_SIZE + size_of_val(self.reserve_entries) + size_of::<ReserveEntry>();
let strings_offset = struct_offset + size_of_val(struct_blob);
let size = strings_offset + strings_blob.len();
let strings_offset = struct_offset + size_of_val(self.struct_blob);
let size = strings_offset + self.strings_blob.len();

let capacity = (size + blob::DTB_ALIGN - 1) / blob::DTB_ALIGN;
let size = u32::try_from(size).ok()?;
let size = u32::try_from(size).ok().ok_or(Error::DevicetreeTooLarge)?;

let mut blob: Vec<u64> = Vec::with_capacity(capacity);
blob.extend::<[u64; HEADER_SIZE_ALIGN_RATIO]>(zerocopy::transmute!(blob::Header {
Expand All @@ -56,8 +63,8 @@ impl DevicetreeBuilder<'_> {
version: 17_u32.to_be(),
last_comp_version: blob::LAST_COMPATIBLE_VERSION.to_be(),
boot_cpuid_phys: self.boot_core_id.to_be(),
size_dt_strings: (strings_blob.len() as u32).to_be(),
size_dt_struct: (size_of_val(struct_blob) as u32).to_be(),
size_dt_strings: (self.strings_blob.len() as u32).to_be(),
size_dt_struct: (size_of_val(self.struct_blob) as u32).to_be(),
}));
blob.extend(self.reserve_entries.iter().flat_map(
|e| -> [u64; blob::RESERVE_ENTRY_SIZE_ALIGN_RATIO] {
Expand All @@ -77,18 +84,18 @@ impl DevicetreeBuilder<'_> {
unsafe {
let ptr = blob.as_mut_ptr() as *mut u8;
core::ptr::copy_nonoverlapping(
struct_blob.as_ptr(),
self.struct_blob.as_ptr(),
ptr.add(struct_offset) as *mut u32,
struct_blob.len(),
self.struct_blob.len(),
);
core::ptr::copy_nonoverlapping(
strings_blob.as_ptr(),
self.strings_blob.as_ptr(),
ptr.add(strings_offset),
strings_blob.len(),
self.strings_blob.len(),
);
blob.set_len(capacity);

Some(Devicetree::from_box_unchecked(blob.into_boxed_slice()))
Ok(Devicetree::from_box_unchecked(blob.into_boxed_slice()))
}
}
}
Expand Down Expand Up @@ -215,8 +222,8 @@ impl<'dtb> DeserializeNode<'dtb> for Box<[Item<'dtb>]> {
}
}

impl<'dtb, A: DeserializeNode<'dtb>> PushDeserializedNode<'dtb> for Vec<A> {
type Node = A;
impl<'dtb, T: DeserializeNode<'dtb>> PushDeserializedNode<'dtb> for Vec<T> {
type Node = T;

fn push_node(&mut self, node: Self::Node, _cx: NodeContext<'_>) -> Result<()> {
self.push(node);
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
//! [spec]: https://www.devicetree.org/specifications
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(rust_2018_idioms)]
#![warn(macro_use_extern_crate, meta_variable_misuse, missing_abi)]
#![warn(unused_lifetimes, unused_macro_rules, unused_qualifications)]

#[cfg(feature = "alloc")]
extern crate alloc as std_alloc;
Expand Down Expand Up @@ -41,6 +38,7 @@ pub enum Error {
/// Not produced by this crate.
Unknown,
Blob(BlobError),
DevicetreeTooLarge,
IntOverflow,
InvalidDeviceType,
InvalidNodeName,
Expand All @@ -57,7 +55,8 @@ impl Display for Error {
let description = match self {
Unknown => "unknown",
Blob(err) => return Display::fmt(err, f),
IntOverflow => "int overflow",
DevicetreeTooLarge => "devicetree too large",
IntOverflow => "integer overflow",
InvalidDeviceType => "invalid device_type",
InvalidNodeName => "invalid node name",
InvalidPath => "invalid path",
Expand Down
4 changes: 1 addition & 3 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,10 @@ fn multiple_children() {
#[test]
fn build() {
let original = dt();
let mut builder = DevicetreeBuilder::default();
let mut builder = DevicetreeBuilder::new(original.struct_blob(), original.strings_blob());
builder.boot_core_id = original.boot_core_id();
let reserve_entries: Vec<_> = original.reserve_entries().unwrap().collect().unwrap();
builder.reserve_entries = &reserve_entries;
builder.struct_blob = Some(original.struct_blob());
builder.strings_blob = Some(original.strings_blob());
let clone = builder.build().unwrap();
assert_eq!(original.blob(), clone.blob());
}
Expand Down

0 comments on commit 17e4863

Please sign in to comment.