Skip to main content

opcua_client/browser/
result.rs

1use futures::{Stream, TryStreamExt};
2use hashbrown::HashMap;
3use opcua_nodes::References;
4use opcua_types::{Error, ExpandedNodeId, LocalizedText, NodeClass, NodeId, QualifiedName};
5
6use super::BrowseResultItem;
7
8/// Simple description of a node discovered when browsing.
9#[derive(Debug)]
10pub struct NodeDescription {
11    /// Node class.
12    pub node_class: NodeClass,
13    /// Node type definition.
14    pub type_definition: ExpandedNodeId,
15    /// Node display name.
16    pub display_name: LocalizedText,
17    /// Node browse name.
18    pub browse_name: QualifiedName,
19}
20
21#[derive(Debug, Default)]
22/// Collected result of a browse operation.
23pub struct BrowserResult {
24    /// Reference map.
25    pub references: References,
26    /// Discovered nodes.
27    pub nodes: HashMap<NodeId, NodeDescription>,
28}
29
30impl BrowserResult {
31    fn new() -> Self {
32        Self::default()
33    }
34
35    pub(super) async fn build_from_browser<T: Stream<Item = Result<BrowseResultItem, Error>>>(
36        stream: T,
37    ) -> Result<Self, Error> {
38        let mut res = Self::new();
39
40        futures::pin_mut!(stream);
41        while let Some(d) = stream.try_next().await? {
42            let (parent_id, refs) = d.into_results();
43            for r in refs {
44                res.references.insert_reference(
45                    &parent_id,
46                    &r.node_id.node_id,
47                    r.reference_type_id,
48                );
49
50                res.nodes
51                    .entry(r.node_id.node_id)
52                    .or_insert_with(|| NodeDescription {
53                        node_class: r.node_class,
54                        type_definition: r.type_definition,
55                        display_name: r.display_name,
56                        browse_name: r.browse_name,
57                    });
58            }
59        }
60
61        Ok(res)
62    }
63}