mls_rs/group/
roster.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright by contributors to this project.
3// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5use crate::tree_kem::node::NodeVec;
6
7use super::*;
8
9pub use mls_rs_core::group::Member;
10
11pub(crate) fn member_from_leaf_node(leaf_node: &LeafNode, leaf_index: LeafIndex) -> Member {
12    Member::new(
13        *leaf_index,
14        leaf_node.signing_identity.clone(),
15        leaf_node.ungreased_capabilities(),
16        leaf_node.ungreased_extensions(),
17    )
18}
19
20#[cfg_attr(
21    all(feature = "ffi", not(test)),
22    safer_ffi_gen::ffi_type(clone, opaque)
23)]
24#[derive(Clone, Debug)]
25pub struct Roster<'a> {
26    pub(crate) public_tree: &'a NodeVec,
27}
28
29#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
30impl<'a> Roster<'a> {
31    /// Iterator over the current roster that lazily copies data out of the
32    /// internal group state.
33    ///
34    /// # Warning
35    ///
36    /// The indexes within this iterator do not correlate with indexes of users
37    /// within [`ReceivedMessage`] content descriptions due to the layout of
38    /// member information within a MLS group state.
39    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
40    pub fn members_iter(&self) -> impl Iterator<Item = Member> + 'a {
41        self.public_tree
42            .non_empty_leaves()
43            .map(|(index, node)| member_from_leaf_node(node, index))
44    }
45
46    /// The current set of group members. This function makes a clone of
47    /// member information from the internal group state.
48    ///
49    /// # Warning
50    ///
51    /// The indexes within this roster do not correlate with indexes of users
52    /// within [`ReceivedMessage`] content descriptions due to the layout of
53    /// member information within a MLS group state.
54    pub fn members(&self) -> Vec<Member> {
55        self.members_iter().collect()
56    }
57
58    /// Retrieve the member with given `index` within the group in time `O(1)`.
59    /// This index does correlate with indexes of users within [`ReceivedMessage`]
60    /// content descriptions.
61    pub fn member_with_index(&self, index: u32) -> Result<Member, MlsError> {
62        let index = LeafIndex::try_from(index)?;
63
64        self.public_tree
65            .borrow_as_leaf(index)
66            .map(|l| member_from_leaf_node(l, index))
67    }
68
69    /// Iterator over member's signing identities.
70    ///
71    /// # Warning
72    ///
73    /// The indexes within this iterator do not correlate with indexes of users
74    /// within [`ReceivedMessage`] content descriptions due to the layout of
75    /// member information within a MLS group state.
76    #[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen_ignore)]
77    pub fn member_identities_iter(&self) -> impl Iterator<Item = &SigningIdentity> + '_ {
78        self.public_tree
79            .non_empty_leaves()
80            .map(|(_, node)| &node.signing_identity)
81    }
82}
83
84impl TreeKemPublic {
85    pub(crate) fn roster(&self) -> Roster<'_> {
86        Roster {
87            public_tree: &self.nodes,
88        }
89    }
90}