Skip to content

Commit

Permalink
- add prop_value::Status
Browse files Browse the repository at this point in the history
- add an output value to `NodeContext::deserialize_node`
  • Loading branch information
kadiwa4 committed Sep 29, 2023
1 parent c4de8bf commit 27d7c8c
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 20 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion devicetree_derive/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub fn derive_deserialize_node(tokens: proc_macro::TokenStream) -> proc_macro::T

let cx_deserialize_node = |child_stmts| {
quote! {
let cursor = cx.deserialize_node(
let (_, cursor) = cx.deserialize_node(
blob_node,
|name, prop| {
match name {
Expand Down
9 changes: 5 additions & 4 deletions src/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std_alloc::{boxed::Box, vec::Vec};

use zerocopy::{AsBytes, FromBytes, FromZeroes, Ref};

use crate::{util, DeserializeNode, DeserializeProperty, NodeContext, Path, ReserveEntries};
use crate::{DeserializeNode, DeserializeProperty, NodeContext, Path, ReserveEntries};

/// Any low level, technical error caused by this crate.
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -315,7 +315,7 @@ impl Devicetree {

// Safety: bounds check was done in Self::late_checks
unsafe {
util::slice_get_with_len_unchecked(
crate::util::slice_get_with_len_unchecked(
self.blob_u32(),
offset / STRUCT_BLOCK_ALIGN,
len / STRUCT_BLOCK_ALIGN,
Expand All @@ -329,7 +329,7 @@ impl Devicetree {
let offset = u32::from_be(header.off_dt_strings) as usize;
let len = u32::from_be(header.size_dt_strings) as usize;
// Safety: bounds check was done in Self::late_checks
unsafe { util::slice_get_with_len_unchecked(self.blob_u8(), offset, len) }
unsafe { crate::util::slice_get_with_len_unchecked(self.blob_u8(), offset, len) }
}

/// Gets a node from the struct block by (loosely-matching) path.
Expand Down Expand Up @@ -426,7 +426,8 @@ impl<'dtb> Property<'dtb> {
/// # Errors
/// Fails if the string is invalid.
pub fn name(self) -> Result<&'dtb str> {
util::str_from_ascii(util::get_c_str(self.name_blob)?).ok_or(Error::InvalidString)
crate::util::str_from_ascii(crate::util::get_c_str(self.name_blob)?)
.ok_or(Error::InvalidString)
}

/// The property's value.
Expand Down
8 changes: 4 additions & 4 deletions src/blob/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use fallible_iterator::FallibleIterator;

use crate::{
blob::{self, Cursor, Devicetree, Item, Property, Token, TOKEN_SIZE},
util, Error, NodeContext, PushDeserializedNode, Result,
Error, NodeContext, PushDeserializedNode, Result,
};

/// A node of the tree structure in a [`Devicetree`] blob's struct block.
Expand All @@ -29,7 +29,7 @@ impl<'dtb> Node<'dtb> {

/// The node's name.
pub fn name(&self) -> blob::Result<&'dtb str> {
util::str_from_ascii(self.name).ok_or(blob::Error::InvalidString)
crate::util::str_from_ascii(self.name).ok_or(blob::Error::InvalidString)
}

/// The name as it would show up in a devicetree source file.
Expand All @@ -50,7 +50,7 @@ impl<'dtb> Node<'dtb> {
///
/// There cannot be more than one `@`.
pub fn split_name(&self) -> Result<(&'dtb str, Option<&'dtb str>)> {
util::split_node_name(self.name()?)
crate::util::split_node_name(self.name()?)
}

/// Cursor pointing to this node's [`Token`].
Expand Down Expand Up @@ -115,7 +115,7 @@ impl<'dtb> Node<'dtb> {
/// has to be unambiguous.
pub fn get_child(&self, name: &str) -> Result<Option<Node<'dtb>>> {
let mut iter = Children(Items::new(self, self.contents));
if util::split_node_name(name)?.1.is_some() {
if crate::util::split_node_name(name)?.1.is_some() {
iter.find(|n| Ok(n.name()? == name))
} else if let Some((candidate, (_, candidate_addr))) = (&mut iter)
.map(|n| n.split_name().map(|split| (n, split)))
Expand Down
2 changes: 2 additions & 0 deletions src/blob/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ impl<'dtb> Token<'dtb> {

/// A position inside the [`Devicetree`] blob's struct block.
///
/// You can think of this as a byte offset from the blob's start address, but it
/// is a little more complicated in reality.
/// Can be obtained from [`Node::content_cursor`] and advanced using
/// [`Devicetree::next_token`].
///
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub enum Error {
InvalidNodeName,
InvalidPath,
TooManyCells,
UnsuitableNode,
UnsuitableProperty,
}

Expand All @@ -57,6 +58,7 @@ impl Display for Error {
InvalidNodeName => "invalid node name",
InvalidPath => "invalid path",
TooManyCells => "too many cells",
UnsuitableNode => "unsuitable node",
UnsuitableProperty => "unsuitable property",
};
write!(f, "devicetree error: {description}")
Expand Down Expand Up @@ -197,7 +199,7 @@ impl<'a> NodeContext<'a> {
blob_node: &Node<'dtb>,
mut f_prop: impl FnMut(&'dtb str, Property<'dtb>) -> Result<()>,
mut f_child: impl FnMut(Node<'dtb>, Self, &mut Cursor) -> Result<()>,
) -> Result<Cursor> {
) -> Result<(Self, Cursor)> {
let mut child_cx = Self {
custom: self.custom,
..Self::default()
Expand Down Expand Up @@ -225,7 +227,7 @@ impl<'a> NodeContext<'a> {
}
}
}
Ok(items.cursor)
Ok((child_cx, items.cursor))
}
}

Expand Down
70 changes: 61 additions & 9 deletions src/prop_value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
//! Types representing property values.
use crate::{blob::Property, util, Cells, DeserializeProperty, Error, NodeContext, Result};
use core::iter::FusedIterator;
use core::{
fmt::{Display, Formatter},
iter::FusedIterator,
};

use fallible_iterator::{DoubleEndedFallibleIterator, FallibleIterator};

Expand Down Expand Up @@ -47,22 +50,71 @@ impl<'dtb> DeserializeProperty<'dtb> for SizeCells {
}
}

/// Value of `status`.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Status<'a> {
#[default]
Ok,
Disabled,
Reserved,
Fail,
FailCondition(&'a str),
}

impl<'dtb> DeserializeProperty<'dtb> for Status<'dtb> {
fn deserialize(blob_prop: Property<'dtb>, cx: NodeContext<'_>) -> Result<Self> {
<&str>::deserialize(blob_prop, cx)?.try_into()
}
}

impl<'a> TryFrom<&'a str> for Status<'a> {
type Error = Error;

fn try_from(string: &'a str) -> Result<Self, Self::Error> {
let ret = match string {
"okay" => Self::Ok,
"disabled" => Self::Disabled,
"reserved" => Self::Reserved,
"fail" => Self::Fail,
_ => Self::FailCondition(
string
.strip_prefix("fail-")
.ok_or(Error::UnsuitableProperty)?,
),
};
Ok(ret)
}
}

impl Display for Status<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match *self {
Self::Ok => f.write_str("okay"),
Self::Disabled => f.write_str("disabled"),
Self::Reserved => f.write_str("reserved"),
Self::Fail => f.write_str("fail"),
Self::FailCondition(condition) => write!(f, "fail-{condition}"),
}
}
}

/// Iterator over the strings contained in the property's value.
///
/// Fused (see [`core::iter::FusedIterator`]).
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Strings<'dtb> {
value: &'dtb [u8],
pub struct Strings<'a> {
value: &'a [u8],
}

impl<'dtb> Strings<'dtb> {
impl<'a> Strings<'a> {
/// Empty iterator. Cannot be obtained from deserializing a property.
pub const EMPTY: Self = Self { value: &[] };

/// Creates a new iterator over the strings contained in the value.
///
/// Returns `None` if the value does not end in a null byte.
pub fn new(value: &'dtb [u8]) -> Option<Self> {
pub fn new(value: &'a [u8]) -> Option<Self> {
matches!(value, [.., 0]).then_some(Self { value })
}
}
Expand All @@ -73,8 +125,8 @@ impl<'dtb> DeserializeProperty<'dtb> for Strings<'dtb> {
}
}

impl<'dtb> FallibleIterator for Strings<'dtb> {
type Item = &'dtb str;
impl<'a> FallibleIterator for Strings<'a> {
type Item = &'a str;
type Error = Error;

fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
Expand All @@ -96,7 +148,7 @@ impl<'dtb> FallibleIterator for Strings<'dtb> {
}
}

impl<'dtb> DoubleEndedFallibleIterator for Strings<'dtb> {
impl<'a> DoubleEndedFallibleIterator for Strings<'a> {
fn next_back(&mut self) -> Result<Option<Self::Item>, Self::Error> {
let [value @ .., _] = self.value else {
return Ok(None);
Expand All @@ -108,7 +160,7 @@ impl<'dtb> DoubleEndedFallibleIterator for Strings<'dtb> {
}
}

impl Default for Strings<'static> {
impl<'a> Default for Strings<'a> {
fn default() -> Self {
Self::EMPTY
}
Expand Down

0 comments on commit 27d7c8c

Please sign in to comment.