libfdt: Add adb_subnode_with_name_len() and subnode_with_name_len()

APIs are added to create a node and its supernodes without allocating
tokenized names.

Bug: 277993056
Test: atest liblibfdt.integration_test
Change-Id: I5a43d41e0bea1e9b7d0182b98d9aa5e0c079dd2e
diff --git a/libs/libfdt/tests/api_test.rs b/libs/libfdt/tests/api_test.rs
index 65ebc4d..61503eb 100644
--- a/libs/libfdt/tests/api_test.rs
+++ b/libs/libfdt/tests/api_test.rs
@@ -17,7 +17,7 @@
 //! Integration tests of the library libfdt.
 
 use libfdt::{Fdt, FdtError, Phandle};
-use std::ffi::CStr;
+use std::ffi::{CStr, CString};
 use std::fs;
 use std::ops::Range;
 
@@ -189,3 +189,34 @@
     assert!(fdt.node_with_phandle(Phandle::new(0xFF).unwrap()).unwrap().is_none());
     assert!(fdt.node(cstr!("/node_z/node_zz")).unwrap().is_none());
 }
+
+#[test]
+fn node_add_subnode_with_namelen() {
+    let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+    data.resize(data.len() * 2, 0_u8);
+
+    let fdt = Fdt::from_mut_slice(&mut data).unwrap();
+    fdt.unpack().unwrap();
+
+    let node_path = cstr!("/node_z/node_zz");
+    let subnode_name = cstr!("123456789");
+
+    for len in 0..subnode_name.to_bytes().len() {
+        let mut node = fdt.node_mut(node_path).unwrap().unwrap();
+        assert!(node.subnode_with_namelen(subnode_name, len).unwrap().is_none());
+
+        let mut node = fdt.node_mut(node_path).unwrap().unwrap();
+        node.add_subnode_with_namelen(subnode_name, len).unwrap();
+
+        let mut node = fdt.node_mut(node_path).unwrap().unwrap();
+        assert!(node.subnode_with_namelen(subnode_name, len).unwrap().is_some());
+    }
+
+    let node_path = node_path.to_str().unwrap();
+    for len in 1..subnode_name.to_bytes().len() {
+        let name = String::from_utf8(subnode_name.to_bytes()[..len].to_vec()).unwrap();
+        let path = CString::new(format!("{node_path}/{name}")).unwrap();
+        let subnode = fdt.node(&path).unwrap().unwrap();
+        assert_eq!(subnode.name().unwrap().to_str().unwrap(), name);
+    }
+}