xref: /aosp_15_r20/external/crosvm/cros_fdt/src/propval.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! This module implements FDT property value conversions as defined by the device tree format.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of_val;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use crate::fdt::c_str_to_string;
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::fdt::Error;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::fdt::Result;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::fdt::SIZE_U32;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::fdt::SIZE_U64;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker /// Conversion into an FDT property value.
16*bb4ee6a4SAndroid Build Coastguard Worker ///
17*bb4ee6a4SAndroid Build Coastguard Worker /// Implementing `ToFdtPropval` for a type defines its conversion to a raw
18*bb4ee6a4SAndroid Build Coastguard Worker /// FDT property value (a byte vector).
19*bb4ee6a4SAndroid Build Coastguard Worker pub trait ToFdtPropval {
20*bb4ee6a4SAndroid Build Coastguard Worker     // Convert the type to its byte representation as an FDT property.
to_propval(self) -> Result<Vec<u8>>21*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>>;
22*bb4ee6a4SAndroid Build Coastguard Worker }
23*bb4ee6a4SAndroid Build Coastguard Worker 
24*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
u32_to_bytes(value: &[u32]) -> Vec<u8>25*bb4ee6a4SAndroid Build Coastguard Worker fn u32_to_bytes(value: &[u32]) -> Vec<u8> {
26*bb4ee6a4SAndroid Build Coastguard Worker     let mut bytes = Vec::with_capacity(size_of_val(value));
27*bb4ee6a4SAndroid Build Coastguard Worker     for val in value {
28*bb4ee6a4SAndroid Build Coastguard Worker         bytes.extend_from_slice(&val.to_be_bytes())
29*bb4ee6a4SAndroid Build Coastguard Worker     }
30*bb4ee6a4SAndroid Build Coastguard Worker     bytes
31*bb4ee6a4SAndroid Build Coastguard Worker }
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
u64_to_bytes(value: &[u64]) -> Vec<u8>34*bb4ee6a4SAndroid Build Coastguard Worker fn u64_to_bytes(value: &[u64]) -> Vec<u8> {
35*bb4ee6a4SAndroid Build Coastguard Worker     let mut bytes = Vec::with_capacity(size_of_val(value));
36*bb4ee6a4SAndroid Build Coastguard Worker     for val in value {
37*bb4ee6a4SAndroid Build Coastguard Worker         bytes.extend_from_slice(&val.to_be_bytes())
38*bb4ee6a4SAndroid Build Coastguard Worker     }
39*bb4ee6a4SAndroid Build Coastguard Worker     bytes
40*bb4ee6a4SAndroid Build Coastguard Worker }
41*bb4ee6a4SAndroid Build Coastguard Worker 
42*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for () {
to_propval(self) -> Result<Vec<u8>>43*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
44*bb4ee6a4SAndroid Build Coastguard Worker         Ok(vec![])
45*bb4ee6a4SAndroid Build Coastguard Worker     }
46*bb4ee6a4SAndroid Build Coastguard Worker }
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for &[u8] {
to_propval(self) -> Result<Vec<u8>>49*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
50*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.into())
51*bb4ee6a4SAndroid Build Coastguard Worker     }
52*bb4ee6a4SAndroid Build Coastguard Worker }
53*bb4ee6a4SAndroid Build Coastguard Worker 
54*bb4ee6a4SAndroid Build Coastguard Worker impl<const N: usize> ToFdtPropval for &[u8; N] {
to_propval(self) -> Result<Vec<u8>>55*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
56*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.to_vec())
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
60*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for Vec<u8> {
to_propval(self) -> Result<Vec<u8>>61*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
62*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self)
63*bb4ee6a4SAndroid Build Coastguard Worker     }
64*bb4ee6a4SAndroid Build Coastguard Worker }
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for u32 {
to_propval(self) -> Result<Vec<u8>>67*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
68*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u32_to_bytes(std::slice::from_ref(&self)))
69*bb4ee6a4SAndroid Build Coastguard Worker     }
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for &[u32] {
to_propval(self) -> Result<Vec<u8>>73*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
74*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u32_to_bytes(self))
75*bb4ee6a4SAndroid Build Coastguard Worker     }
76*bb4ee6a4SAndroid Build Coastguard Worker }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker impl<const N: usize> ToFdtPropval for &[u32; N] {
to_propval(self) -> Result<Vec<u8>>79*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
80*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u32_to_bytes(self))
81*bb4ee6a4SAndroid Build Coastguard Worker     }
82*bb4ee6a4SAndroid Build Coastguard Worker }
83*bb4ee6a4SAndroid Build Coastguard Worker 
84*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for Vec<u32> {
to_propval(self) -> Result<Vec<u8>>85*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
86*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u32_to_bytes(self.as_slice()))
87*bb4ee6a4SAndroid Build Coastguard Worker     }
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for u64 {
to_propval(self) -> Result<Vec<u8>>91*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
92*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u64_to_bytes(std::slice::from_ref(&self)))
93*bb4ee6a4SAndroid Build Coastguard Worker     }
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for &[u64] {
to_propval(self) -> Result<Vec<u8>>97*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
98*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u64_to_bytes(self))
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker }
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker impl<const N: usize> ToFdtPropval for &[u64; N] {
to_propval(self) -> Result<Vec<u8>>103*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
104*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u64_to_bytes(self))
105*bb4ee6a4SAndroid Build Coastguard Worker     }
106*bb4ee6a4SAndroid Build Coastguard Worker }
107*bb4ee6a4SAndroid Build Coastguard Worker 
108*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for Vec<u64> {
to_propval(self) -> Result<Vec<u8>>109*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
110*bb4ee6a4SAndroid Build Coastguard Worker         Ok(u64_to_bytes(self.as_slice()))
111*bb4ee6a4SAndroid Build Coastguard Worker     }
112*bb4ee6a4SAndroid Build Coastguard Worker }
113*bb4ee6a4SAndroid Build Coastguard Worker 
114*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
is_valid_string_property(val: &str) -> bool115*bb4ee6a4SAndroid Build Coastguard Worker fn is_valid_string_property(val: &str) -> bool {
116*bb4ee6a4SAndroid Build Coastguard Worker     // Although the devicetree spec says string properties should be printable, neither libfdt nor
117*bb4ee6a4SAndroid Build Coastguard Worker     // the kernel device tree API verify that, so only check for zero bytes.
118*bb4ee6a4SAndroid Build Coastguard Worker     !val.contains('\0')
119*bb4ee6a4SAndroid Build Coastguard Worker }
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker #[inline]
str_to_bytes<T: AsRef<str>>(value: &[T]) -> Result<Vec<u8>>122*bb4ee6a4SAndroid Build Coastguard Worker fn str_to_bytes<T: AsRef<str>>(value: &[T]) -> Result<Vec<u8>> {
123*bb4ee6a4SAndroid Build Coastguard Worker     let total_length = value.iter().map(|s| s.as_ref().len() + 1).sum();
124*bb4ee6a4SAndroid Build Coastguard Worker     let mut bytes = Vec::with_capacity(total_length);
125*bb4ee6a4SAndroid Build Coastguard Worker     for s in value {
126*bb4ee6a4SAndroid Build Coastguard Worker         let s = s.as_ref();
127*bb4ee6a4SAndroid Build Coastguard Worker         if !is_valid_string_property(s) {
128*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidString(s.to_owned()));
129*bb4ee6a4SAndroid Build Coastguard Worker         }
130*bb4ee6a4SAndroid Build Coastguard Worker         bytes.extend_from_slice(s.as_bytes());
131*bb4ee6a4SAndroid Build Coastguard Worker         bytes.push(0);
132*bb4ee6a4SAndroid Build Coastguard Worker     }
133*bb4ee6a4SAndroid Build Coastguard Worker     Ok(bytes)
134*bb4ee6a4SAndroid Build Coastguard Worker }
135*bb4ee6a4SAndroid Build Coastguard Worker 
136*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for &str {
to_propval(self) -> Result<Vec<u8>>137*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
138*bb4ee6a4SAndroid Build Coastguard Worker         str_to_bytes(std::slice::from_ref(&self))
139*bb4ee6a4SAndroid Build Coastguard Worker     }
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker 
142*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for &[&str] {
to_propval(self) -> Result<Vec<u8>>143*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
144*bb4ee6a4SAndroid Build Coastguard Worker         str_to_bytes(self)
145*bb4ee6a4SAndroid Build Coastguard Worker     }
146*bb4ee6a4SAndroid Build Coastguard Worker }
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker impl<const N: usize> ToFdtPropval for &[&str; N] {
to_propval(self) -> Result<Vec<u8>>149*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
150*bb4ee6a4SAndroid Build Coastguard Worker         str_to_bytes(self)
151*bb4ee6a4SAndroid Build Coastguard Worker     }
152*bb4ee6a4SAndroid Build Coastguard Worker }
153*bb4ee6a4SAndroid Build Coastguard Worker 
154*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for String {
to_propval(self) -> Result<Vec<u8>>155*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
156*bb4ee6a4SAndroid Build Coastguard Worker         if !is_valid_string_property(&self) {
157*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::InvalidString(self))
158*bb4ee6a4SAndroid Build Coastguard Worker         } else {
159*bb4ee6a4SAndroid Build Coastguard Worker             let mut bytes = self.into_bytes();
160*bb4ee6a4SAndroid Build Coastguard Worker             bytes.push(0);
161*bb4ee6a4SAndroid Build Coastguard Worker             Ok(bytes)
162*bb4ee6a4SAndroid Build Coastguard Worker         }
163*bb4ee6a4SAndroid Build Coastguard Worker     }
164*bb4ee6a4SAndroid Build Coastguard Worker }
165*bb4ee6a4SAndroid Build Coastguard Worker 
166*bb4ee6a4SAndroid Build Coastguard Worker impl ToFdtPropval for Vec<String> {
to_propval(self) -> Result<Vec<u8>>167*bb4ee6a4SAndroid Build Coastguard Worker     fn to_propval(self) -> Result<Vec<u8>> {
168*bb4ee6a4SAndroid Build Coastguard Worker         str_to_bytes(&self)
169*bb4ee6a4SAndroid Build Coastguard Worker     }
170*bb4ee6a4SAndroid Build Coastguard Worker }
171*bb4ee6a4SAndroid Build Coastguard Worker 
172*bb4ee6a4SAndroid Build Coastguard Worker /// Conversion from an FDT property value.
173*bb4ee6a4SAndroid Build Coastguard Worker ///
174*bb4ee6a4SAndroid Build Coastguard Worker /// Implementing `FromFdtPropval` for a type defines its construction from a raw
175*bb4ee6a4SAndroid Build Coastguard Worker /// FDT property value (a byte slice).
176*bb4ee6a4SAndroid Build Coastguard Worker pub trait FromFdtPropval {
177*bb4ee6a4SAndroid Build Coastguard Worker     // Try to convert FDT property bytes to `Self`, return `None` if impossible.
from_propval(propval: &[u8]) -> Option<Self> where Self: Sized178*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self>
179*bb4ee6a4SAndroid Build Coastguard Worker     where
180*bb4ee6a4SAndroid Build Coastguard Worker         Self: Sized;
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker 
183*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for () {
from_propval(propval: &[u8]) -> Option<Self>184*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
185*bb4ee6a4SAndroid Build Coastguard Worker         propval.is_empty().then_some(())
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker 
189*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for Vec<u8> {
from_propval(propval: &[u8]) -> Option<Self>190*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
191*bb4ee6a4SAndroid Build Coastguard Worker         Some(propval.into())
192*bb4ee6a4SAndroid Build Coastguard Worker     }
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker 
195*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for u32 {
from_propval(propval: &[u8]) -> Option<Self>196*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
197*bb4ee6a4SAndroid Build Coastguard Worker         if propval.len() == SIZE_U32 {
198*bb4ee6a4SAndroid Build Coastguard Worker             Some(u32::from_be_bytes(propval.try_into().unwrap()))
199*bb4ee6a4SAndroid Build Coastguard Worker         } else {
200*bb4ee6a4SAndroid Build Coastguard Worker             None
201*bb4ee6a4SAndroid Build Coastguard Worker         }
202*bb4ee6a4SAndroid Build Coastguard Worker     }
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker 
205*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for Vec<u32> {
from_propval(propval: &[u8]) -> Option<Self>206*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
207*bb4ee6a4SAndroid Build Coastguard Worker         if propval.len() % SIZE_U32 != 0 {
208*bb4ee6a4SAndroid Build Coastguard Worker             None
209*bb4ee6a4SAndroid Build Coastguard Worker         } else {
210*bb4ee6a4SAndroid Build Coastguard Worker             Some(
211*bb4ee6a4SAndroid Build Coastguard Worker                 propval
212*bb4ee6a4SAndroid Build Coastguard Worker                     .chunks(SIZE_U32)
213*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|v| u32::from_be_bytes(v.try_into().unwrap()))
214*bb4ee6a4SAndroid Build Coastguard Worker                     .collect(),
215*bb4ee6a4SAndroid Build Coastguard Worker             )
216*bb4ee6a4SAndroid Build Coastguard Worker         }
217*bb4ee6a4SAndroid Build Coastguard Worker     }
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for u64 {
from_propval(propval: &[u8]) -> Option<Self>221*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
222*bb4ee6a4SAndroid Build Coastguard Worker         if propval.len() == SIZE_U64 {
223*bb4ee6a4SAndroid Build Coastguard Worker             Some(u64::from_be_bytes(propval.try_into().unwrap()))
224*bb4ee6a4SAndroid Build Coastguard Worker         } else {
225*bb4ee6a4SAndroid Build Coastguard Worker             None
226*bb4ee6a4SAndroid Build Coastguard Worker         }
227*bb4ee6a4SAndroid Build Coastguard Worker     }
228*bb4ee6a4SAndroid Build Coastguard Worker }
229*bb4ee6a4SAndroid Build Coastguard Worker 
230*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for Vec<u64> {
from_propval(propval: &[u8]) -> Option<Self>231*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
232*bb4ee6a4SAndroid Build Coastguard Worker         if propval.len() % SIZE_U64 != 0 {
233*bb4ee6a4SAndroid Build Coastguard Worker             None
234*bb4ee6a4SAndroid Build Coastguard Worker         } else {
235*bb4ee6a4SAndroid Build Coastguard Worker             Some(
236*bb4ee6a4SAndroid Build Coastguard Worker                 propval
237*bb4ee6a4SAndroid Build Coastguard Worker                     .chunks(SIZE_U64)
238*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|v| u64::from_be_bytes(v.try_into().unwrap()))
239*bb4ee6a4SAndroid Build Coastguard Worker                     .collect(),
240*bb4ee6a4SAndroid Build Coastguard Worker             )
241*bb4ee6a4SAndroid Build Coastguard Worker         }
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker }
244*bb4ee6a4SAndroid Build Coastguard Worker 
245*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for String {
from_propval(propval: &[u8]) -> Option<Self>246*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
247*bb4ee6a4SAndroid Build Coastguard Worker         c_str_to_string(propval)
248*bb4ee6a4SAndroid Build Coastguard Worker     }
249*bb4ee6a4SAndroid Build Coastguard Worker }
250*bb4ee6a4SAndroid Build Coastguard Worker 
251*bb4ee6a4SAndroid Build Coastguard Worker impl FromFdtPropval for Vec<String> {
from_propval(propval: &[u8]) -> Option<Self>252*bb4ee6a4SAndroid Build Coastguard Worker     fn from_propval(propval: &[u8]) -> Option<Self> {
253*bb4ee6a4SAndroid Build Coastguard Worker         if Some(&0) == propval.last() {
254*bb4ee6a4SAndroid Build Coastguard Worker             Some(
255*bb4ee6a4SAndroid Build Coastguard Worker                 propval
256*bb4ee6a4SAndroid Build Coastguard Worker                     .split(|&b| b == 0u8)
257*bb4ee6a4SAndroid Build Coastguard Worker                     .take_while(|s| !s.is_empty())
258*bb4ee6a4SAndroid Build Coastguard Worker                     .filter_map(|b| String::from_utf8(b.into()).ok())
259*bb4ee6a4SAndroid Build Coastguard Worker                     .collect(),
260*bb4ee6a4SAndroid Build Coastguard Worker             )
261*bb4ee6a4SAndroid Build Coastguard Worker         } else {
262*bb4ee6a4SAndroid Build Coastguard Worker             None
263*bb4ee6a4SAndroid Build Coastguard Worker         }
264*bb4ee6a4SAndroid Build Coastguard Worker     }
265*bb4ee6a4SAndroid Build Coastguard Worker }
266*bb4ee6a4SAndroid Build Coastguard Worker 
267*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
268*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
269*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
270*bb4ee6a4SAndroid Build Coastguard Worker 
271*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
fdt_as_propval()272*bb4ee6a4SAndroid Build Coastguard Worker     fn fdt_as_propval() {
273*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(().to_propval().unwrap(), []);
274*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([0u8, 1u8, 2u8].to_propval().unwrap(), [0u8, 1u8, 2u8]);
275*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(0x1u32.to_propval().unwrap(), [0u8, 0, 0, 1]);
276*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
277*bb4ee6a4SAndroid Build Coastguard Worker             0x12345678u32.to_propval().unwrap(),
278*bb4ee6a4SAndroid Build Coastguard Worker             [0x12u8, 0x34, 0x56, 0x78]
279*bb4ee6a4SAndroid Build Coastguard Worker         );
280*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
281*bb4ee6a4SAndroid Build Coastguard Worker             0x12345678ABCDu64.to_propval().unwrap(),
282*bb4ee6a4SAndroid Build Coastguard Worker             [0x00u8, 0x00, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD]
283*bb4ee6a4SAndroid Build Coastguard Worker         );
284*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
285*bb4ee6a4SAndroid Build Coastguard Worker             [0x1u32, 0xABCDu32].to_propval().unwrap(),
286*bb4ee6a4SAndroid Build Coastguard Worker             [0x00u8, 0x00, 0x00, 0x01, 0x00, 0x00, 0xAB, 0xCD]
287*bb4ee6a4SAndroid Build Coastguard Worker         );
288*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
289*bb4ee6a4SAndroid Build Coastguard Worker             [0x1u64, 0xABCD00000000u64].to_propval().unwrap(),
290*bb4ee6a4SAndroid Build Coastguard Worker             [
291*bb4ee6a4SAndroid Build Coastguard Worker                 0x00u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xAB, 0xCD, 0x00,
292*bb4ee6a4SAndroid Build Coastguard Worker                 0x00, 0x00, 0x00,
293*bb4ee6a4SAndroid Build Coastguard Worker             ]
294*bb4ee6a4SAndroid Build Coastguard Worker         );
295*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
296*bb4ee6a4SAndroid Build Coastguard Worker             "abc def".to_propval().unwrap(),
297*bb4ee6a4SAndroid Build Coastguard Worker             [0x61u8, 0x62, 0x63, 0x20, 0x64, 0x65, 0x66, 0x00,]
298*bb4ee6a4SAndroid Build Coastguard Worker         );
299*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
300*bb4ee6a4SAndroid Build Coastguard Worker             ["abc def", "ghi jkl", "mno pqr"].to_propval().unwrap(),
301*bb4ee6a4SAndroid Build Coastguard Worker             [
302*bb4ee6a4SAndroid Build Coastguard Worker                 0x61u8, 0x62, 0x63, 0x20, 0x64, 0x65, 0x66, 0x00, 0x67u8, 0x68, 0x69, 0x20, 0x6A,
303*bb4ee6a4SAndroid Build Coastguard Worker                 0x6B, 0x6C, 0x00, 0x6Du8, 0x6E, 0x6F, 0x20, 0x70, 0x71, 0x72, 0x00,
304*bb4ee6a4SAndroid Build Coastguard Worker             ]
305*bb4ee6a4SAndroid Build Coastguard Worker         );
306*bb4ee6a4SAndroid Build Coastguard Worker         "abc\0def".to_propval().expect_err("invalid string");
307*bb4ee6a4SAndroid Build Coastguard Worker     }
308*bb4ee6a4SAndroid Build Coastguard Worker 
309*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
fdt_from_propval()310*bb4ee6a4SAndroid Build Coastguard Worker     fn fdt_from_propval() {
311*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(Vec::<u8>::from_propval(&[]).unwrap(), []);
312*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(u32::from_propval(&[0, 0, 0, 1]).unwrap(), 1u32);
313*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
314*bb4ee6a4SAndroid Build Coastguard Worker             u32::from_propval(&[0x12u8, 0x34, 0x56, 0x78]).unwrap(),
315*bb4ee6a4SAndroid Build Coastguard Worker             0x12345678u32
316*bb4ee6a4SAndroid Build Coastguard Worker         );
317*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
318*bb4ee6a4SAndroid Build Coastguard Worker             u64::from_propval(&[0x00u8, 0x00, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD]).unwrap(),
319*bb4ee6a4SAndroid Build Coastguard Worker             0x12345678ABCDu64
320*bb4ee6a4SAndroid Build Coastguard Worker         );
321*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
322*bb4ee6a4SAndroid Build Coastguard Worker             Vec::<u32>::from_propval(&[0x00u8, 0x00, 0x00, 0x01, 0x00, 0x00, 0xAB, 0xCD]).unwrap(),
323*bb4ee6a4SAndroid Build Coastguard Worker             [0x1u32, 0xABCDu32]
324*bb4ee6a4SAndroid Build Coastguard Worker         );
325*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
326*bb4ee6a4SAndroid Build Coastguard Worker             Vec::<u64>::from_propval(&[
327*bb4ee6a4SAndroid Build Coastguard Worker                 0x00u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xAB, 0xCD, 0x00,
328*bb4ee6a4SAndroid Build Coastguard Worker                 0x00, 0x00, 0x00
329*bb4ee6a4SAndroid Build Coastguard Worker             ])
330*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap(),
331*bb4ee6a4SAndroid Build Coastguard Worker             [0x1u64, 0xABCD00000000u64]
332*bb4ee6a4SAndroid Build Coastguard Worker         );
333*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
334*bb4ee6a4SAndroid Build Coastguard Worker             String::from_propval(&[0x61u8, 0x62, 0x63, 0x20, 0x64, 0x65, 0x66, 0x00]).unwrap(),
335*bb4ee6a4SAndroid Build Coastguard Worker             "abc def"
336*bb4ee6a4SAndroid Build Coastguard Worker         );
337*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
338*bb4ee6a4SAndroid Build Coastguard Worker             Vec::<String>::from_propval(&[
339*bb4ee6a4SAndroid Build Coastguard Worker                 0x61u8, 0x62, 0x63, 0x20, 0x64, 0x65, 0x66, 0x00, 0x67u8, 0x68, 0x69, 0x20, 0x6A,
340*bb4ee6a4SAndroid Build Coastguard Worker                 0x6B, 0x6C, 0x00, 0x6Du8, 0x6E, 0x6F, 0x20, 0x70, 0x71, 0x72, 0x00,
341*bb4ee6a4SAndroid Build Coastguard Worker             ])
342*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap(),
343*bb4ee6a4SAndroid Build Coastguard Worker             ["abc def", "ghi jkl", "mno pqr"],
344*bb4ee6a4SAndroid Build Coastguard Worker         );
345*bb4ee6a4SAndroid Build Coastguard Worker 
346*bb4ee6a4SAndroid Build Coastguard Worker         assert!(Vec::<String>::from_propval(&[
347*bb4ee6a4SAndroid Build Coastguard Worker             0x61u8, 0x62, 0x63, 0x20, 0x64, 0x65, 0x66, 0x00, 0x67u8, 0x68,
348*bb4ee6a4SAndroid Build Coastguard Worker         ])
349*bb4ee6a4SAndroid Build Coastguard Worker         .is_none());
350*bb4ee6a4SAndroid Build Coastguard Worker         assert!(String::from_propval(&[0x61u8, 0x62, 0x63]).is_none());
351*bb4ee6a4SAndroid Build Coastguard Worker         assert!(u32::from_propval(&[0x61u8, 0x62]).is_none());
352*bb4ee6a4SAndroid Build Coastguard Worker         assert!(u64::from_propval(&[0x61u8, 0x62, 0x61u8, 0x62, 0x61u8, 0x62]).is_none());
353*bb4ee6a4SAndroid Build Coastguard Worker     }
354*bb4ee6a4SAndroid Build Coastguard Worker }
355