Add more helpful Rust Configuration methods
Also switch where they're attached so they can be used with both
versions of Configuration we have in Rust.
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I944cd0fc05db460573e9df694e812bdf0f31ffd7
diff --git a/aos/configuration.rs b/aos/configuration.rs
index 479a065..a264867 100644
--- a/aos/configuration.rs
+++ b/aos/configuration.rs
@@ -1,9 +1,9 @@
-use std::path::Path;
+use std::{path::Path, ptr};
use thiserror::Error;
use aos_configuration_fbs::aos::Configuration as RustConfiguration;
-use aos_flatbuffers::{Flatbuffer, NonSizePrefixedFlatbuffer};
+use aos_flatbuffers::{transmute_table_to, NonSizePrefixedFlatbuffer};
autocxx::include_cpp! (
#include "aos/configuration.h"
@@ -19,6 +19,7 @@
block!("flatbuffers::Verifier")
generate!("aos::configuration::GetChannelForRust")
+generate!("aos::configuration::GetNodeForRust")
);
#[cxx::bridge]
@@ -39,40 +40,76 @@
}
#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
+pub enum NodeLookupError {
+ #[error("node not found")]
+ NotFound,
+}
+
+#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
pub enum ReadConfigError {
#[error("duplicate imports or invalid paths")]
ReadFailed,
}
-impl Configuration {
- pub fn get_channel(
- &self,
+impl<'a> Into<&'a Configuration> for RustConfiguration<'a> {
+ fn into(self) -> &'a Configuration {
+ unsafe { transmute_table_to(&self._tab) }
+ }
+}
+
+/// A trait with useful helper methods for a `Configuration` table. Import this trait to get these
+/// methods on both the `Configuration` struct generated by autocxx from the C++ code generated by
+/// flatbuffers, and the `Configuration` struct generated by flatbuffers in Rust.
+pub trait ConfigurationExt<'a>: Into<&'a Configuration> {
+ fn get_channel(
+ self,
name: &str,
typename: &str,
application_name: &str,
- node: &Node,
- ) -> Result<&Channel, ChannelLookupError> {
+ node: Option<&Node>,
+ ) -> Result<&'a Channel, ChannelLookupError> {
// SAFETY: All the input references are valid pointers, and we're not doing anything with
// the result yet. It doesn't store any of the input references.
let channel = unsafe {
- ffi::aos::configuration::GetChannelForRust(self, name, typename, application_name, node)
+ ffi::aos::configuration::GetChannelForRust(
+ self.into(),
+ name,
+ typename,
+ application_name,
+ node.map_or(ptr::null(), |p| p),
+ )
};
if channel.is_null() {
Err(ChannelLookupError::NotFound)
} else {
// SAFETY: We know this is a valid pointer now, and we're returning it with the lifetime
- // inherited from `configuration` which owns it.
+ // inherited from `self` which owns it.
Ok(unsafe { &*channel })
}
}
+
+ fn get_node(self, name: &str) -> Result<&'a Node, NodeLookupError> {
+ // SAFETY: All the input references are valid pointers, and we're not doing anything with
+ // the result yet. It doesn't store any of the input references.
+ let node = unsafe { ffi::aos::configuration::GetNodeForRust(self.into(), name) };
+ if node.is_null() {
+ Err(NodeLookupError::NotFound)
+ } else {
+ // SAFETY: We know this is a valid pointer now, and we're returning it with the lifetime
+ // inherited from `self` which owns it.
+ Ok(unsafe { &*node })
+ }
+ }
}
+impl<'a, T: Into<&'a Configuration>> ConfigurationExt<'a> for T {}
+
/// # Panics
///
/// `path` must be valid UTF-8.
pub fn read_config_from(
path: &Path,
-) -> Result<impl Flatbuffer<RustConfiguration<'static>>, ReadConfigError> {
+) -> Result<NonSizePrefixedFlatbuffer<RustConfiguration<'static>, Vec<u8>>, ReadConfigError> {
read_config_from_import_paths(path, &[])
}
@@ -82,7 +119,7 @@
pub fn read_config_from_import_paths(
path: &Path,
extra_import_paths: &[&Path],
-) -> Result<impl Flatbuffer<RustConfiguration<'static>>, ReadConfigError> {
+) -> Result<NonSizePrefixedFlatbuffer<RustConfiguration<'static>, Vec<u8>>, ReadConfigError> {
let extra_import_paths: Vec<_> = extra_import_paths
.iter()
.map(|p| p.to_str().expect("Paths must be UTF-8"))
@@ -103,6 +140,8 @@
mod tests {
use super::*;
+ use aos_flatbuffers::Flatbuffer;
+
#[test]
fn read_config() {
let config = read_config_from(Path::new("aos/testdata/config1.json")).unwrap();