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