Skip to content

Commit

Permalink
add get_namespace_index to Session
Browse files Browse the repository at this point in the history
  • Loading branch information
Olivier committed Jan 2, 2025
1 parent bcdf5fc commit c8cead8
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 3 deletions.
55 changes: 53 additions & 2 deletions opcua-client/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ pub(crate) use session_trace;

use opcua_core::ResponseMessage;
use opcua_types::{
ApplicationDescription, ContextOwned, DecodingOptions, EndpointDescription, IntegerId,
NamespaceMap, NodeId, RequestHeader, ResponseHeader, StatusCode, TypeLoader, UAString,
ApplicationDescription, ContextOwned, DecodingOptions, EndpointDescription, Error, IntegerId,
NamespaceMap, NodeId, ReadValueId, RequestHeader, ResponseHeader, StatusCode,
TimestampsToReturn, TypeLoader, UAString, VariableId, Variant,
};

use crate::browser::Browser;
Expand Down Expand Up @@ -430,4 +431,54 @@ impl Session {
)),
)
}

///
/// Return namespace array from server
pub async fn read_namespace_array(&mut self) -> Result<NamespaceMap, Error> {
let nodeid: NodeId = VariableId::Server_NamespaceArray.into();
let result = self
.read(
&[ReadValueId::from(nodeid)],
TimestampsToReturn::Neither,
0.0,
)
.await
.map_err(|status_code| {
Error::new(status_code, "Reading Server namespace array failed")
})?;
if let Some(Variant::Array(array)) = &result[0].value {
let map = NamespaceMap::new_from_variant_array(&array.values);
let map_clone = map.clone();
self.set_namespaces(map);
Ok(map_clone)
} else {
Err(Error::new(
StatusCode::BadNoValue,
format!(
"Server namespace array is None. The server has an issue {:?}",
result
),
))
}
}

///
/// return index of supplied namespace url
/// by first looking at namespace cache and querying server if necessary
pub async fn get_namespace_index(&mut self, url: &str) -> Result<u16, Error> {
if let Some(idx) = self.encoding_context.read().namespaces().get_index(url) {
return Ok(idx);
};
let map = self.read_namespace_array().await?;
let idx = map.get_index(url).ok_or_else(|| {
Error::new(
StatusCode::BadNoMatch,
format!(
"Url {} not found in namespace array. Namspace array is {:?}",
url, &map
),
)
})?;
Ok(idx)
}
}
19 changes: 18 additions & 1 deletion opcua-types/src/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use hashbrown::HashMap;

use crate::{ExpandedNodeId, NodeId};
use crate::{ExpandedNodeId, NodeId, Variant};

/// Utility for handling assignment of namespaces on server startup.
#[derive(Debug, Default, Clone)]
Expand All @@ -26,6 +26,23 @@ impl NamespaceMap {
}
}

/// Create a new namespace map from a vec of variant as we get when reading
/// the namespace array from the server
pub fn new_from_variant_array(array: &[Variant]) -> Self {
let known_namespaces = array
.iter()
.enumerate()
.map(|(idx, v)| {
if let Variant::String(s) = v {
(s.value().clone().unwrap_or(String::new()), idx as u16)
} else {
(String::new(), idx as u16)
}
})
.collect();
Self { known_namespaces }
}

/// Add a new namespace, returning its index in the namespace map.
/// If the namespace is already added, its old index is returned.
pub fn add_namespace(&mut self, namespace: &str) -> u16 {
Expand Down

0 comments on commit c8cead8

Please sign in to comment.