Skip to main content

matter_clusters/gen/
groups.rs

1//! Groups cluster (0x0004).
2//! @generated by `cargo xtask codegen` — do not edit.
3
4#![allow(
5    clippy::all,
6    clippy::pedantic,
7    dead_code,
8    unreachable_pub,
9    unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17/// Cluster ID.
18pub const CLUSTER_ID: u32 = 0x0004;
19/// Cluster revision.
20pub const CLUSTER_REVISION: u16 = 4;
21
22/// Command IDs (requests and responses).
23pub mod command_id {
24    /// `AddGroup` (request).
25    pub const ADD_GROUP: u32 = 0x00;
26    /// `AddGroupResponse` (response).
27    pub const ADD_GROUP_RESPONSE: u32 = 0x00;
28    /// `ViewGroup` (request).
29    pub const VIEW_GROUP: u32 = 0x01;
30    /// `ViewGroupResponse` (response).
31    pub const VIEW_GROUP_RESPONSE: u32 = 0x01;
32    /// `GetGroupMembership` (request).
33    pub const GET_GROUP_MEMBERSHIP: u32 = 0x02;
34    /// `GetGroupMembershipResponse` (response).
35    pub const GET_GROUP_MEMBERSHIP_RESPONSE: u32 = 0x02;
36    /// `RemoveGroup` (request).
37    pub const REMOVE_GROUP: u32 = 0x03;
38    /// `RemoveGroupResponse` (response).
39    pub const REMOVE_GROUP_RESPONSE: u32 = 0x03;
40    /// `RemoveAllGroups` (request).
41    pub const REMOVE_ALL_GROUPS: u32 = 0x04;
42    /// `AddGroupIfIdentifying` (request).
43    pub const ADD_GROUP_IF_IDENTIFYING: u32 = 0x05;
44}
45
46/// Attribute IDs (cluster-specific).
47pub mod attribute_id {
48    /// `NameSupport`.
49    pub const NAME_SUPPORT: u32 = 0x0000;
50}
51
52bitflags::bitflags! {
53    /// `Groups` feature bits (FeatureMap).
54    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
55    pub struct Feature: u32 {
56        /// GroupNames (GN).
57        const GN = 1 << 0;
58    }
59}
60
61bitflags::bitflags! {
62    /// `NameSupportBitmap` (map8).
63    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
64    pub struct NameSupportBitmap: u8 {
65        /// GroupNames.
66        const GROUP_NAMES = 1 << 7;
67    }
68}
69
70/// Decode the `NameSupport` attribute value.
71///
72/// # Errors
73/// Returns [`ClusterError`] on a type mismatch or out-of-range value.
74pub fn decode_name_support(tlv: &[u8]) -> Result<NameSupportBitmap, ClusterError> {
75    let mut r = TlvReader::new(tlv);
76    match r.next()? {
77        Some(Element::Scalar {
78            value: Value::Uint(v),
79            ..
80        }) => Ok(NameSupportBitmap::from_bits_retain(
81            u8::try_from(v).map_err(|_| ClusterError::InvalidLength("NameSupport"))?,
82        )),
83        _ => Err(ClusterError::UnexpectedType {
84            context: "NameSupport",
85        }),
86    }
87}
88
89/// Encode the `AddGroup` command request payload.
90#[must_use]
91#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
92pub fn encode_add_group(group_id: u16, group_name: &String) -> Vec<u8> {
93    let mut buf = Vec::new();
94    let mut w = TlvWriter::new(&mut buf);
95    w.start_structure(Tag::Anonymous)
96        .expect("infallible: vec writer");
97    w.put_uint(Tag::Context(0), u64::from(group_id))
98        .expect("infallible: vec writer");
99    w.put_utf8(Tag::Context(1), &group_name)
100        .expect("infallible: vec writer");
101    w.end_container().expect("infallible: vec writer");
102    buf
103}
104
105/// Decoded `AddGroupResponse` payload.
106#[derive(Clone, Debug, PartialEq)]
107#[non_exhaustive]
108pub struct AddGroupResponse {
109    /// Field Status (tag 0).
110    pub status: u8,
111    /// Field GroupId (tag 1).
112    pub group_id: u16,
113}
114
115impl AddGroupResponse {
116    /// Decode the fields of an already-opened anonymous structure
117    /// (reader positioned after the struct start; consumes to its end).
118    ///
119    /// # Errors
120    /// Returns [`ClusterError`] on a malformed structure or missing required field.
121    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
122        let mut f_status: Option<u8> = None;
123        let mut f_group_id: Option<u16> = None;
124        loop {
125            match r.next()? {
126                Some(Element::ContainerEnd) => break,
127                Some(Element::Scalar {
128                    tag: Tag::Context(0),
129                    value: Value::Uint(v),
130                }) => {
131                    f_status =
132                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
133                }
134                Some(Element::Scalar {
135                    tag: Tag::Context(1),
136                    value: Value::Uint(v),
137                }) => {
138                    f_group_id =
139                        Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("GroupId"))?)
140                }
141                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
142                Some(Element::ContainerStart { .. }) => r.skip_container()?,
143                Some(_) => {} // unknown/future scalar — skip
144            }
145        }
146        Ok(Self {
147            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
148            group_id: f_group_id.ok_or(ClusterError::MissingField("GroupId"))?,
149        })
150    }
151    /// Decode from a standalone anonymous TLV structure.
152    ///
153    /// # Errors
154    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
155    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
156        let mut r = TlvReader::new(tlv);
157        match r.next()? {
158            Some(Element::ContainerStart {
159                kind: ContainerKind::Structure,
160                ..
161            }) => {}
162            _ => {
163                return Err(ClusterError::UnexpectedType {
164                    context: "AddGroupResponse",
165                })
166            }
167        }
168        Self::decode_from(&mut r)
169    }
170}
171
172/// Encode the `ViewGroup` command request payload.
173#[must_use]
174#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
175pub fn encode_view_group(group_id: u16) -> Vec<u8> {
176    let mut buf = Vec::new();
177    let mut w = TlvWriter::new(&mut buf);
178    w.start_structure(Tag::Anonymous)
179        .expect("infallible: vec writer");
180    w.put_uint(Tag::Context(0), u64::from(group_id))
181        .expect("infallible: vec writer");
182    w.end_container().expect("infallible: vec writer");
183    buf
184}
185
186/// Decoded `ViewGroupResponse` payload.
187#[derive(Clone, Debug, PartialEq)]
188#[non_exhaustive]
189pub struct ViewGroupResponse {
190    /// Field Status (tag 0).
191    pub status: u8,
192    /// Field GroupId (tag 1).
193    pub group_id: u16,
194    /// Field GroupName (tag 2).
195    pub group_name: String,
196}
197
198impl ViewGroupResponse {
199    /// Decode the fields of an already-opened anonymous structure
200    /// (reader positioned after the struct start; consumes to its end).
201    ///
202    /// # Errors
203    /// Returns [`ClusterError`] on a malformed structure or missing required field.
204    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
205        let mut f_status: Option<u8> = None;
206        let mut f_group_id: Option<u16> = None;
207        let mut f_group_name: Option<String> = None;
208        loop {
209            match r.next()? {
210                Some(Element::ContainerEnd) => break,
211                Some(Element::Scalar {
212                    tag: Tag::Context(0),
213                    value: Value::Uint(v),
214                }) => {
215                    f_status =
216                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
217                }
218                Some(Element::Scalar {
219                    tag: Tag::Context(1),
220                    value: Value::Uint(v),
221                }) => {
222                    f_group_id =
223                        Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("GroupId"))?)
224                }
225                Some(Element::Scalar {
226                    tag: Tag::Context(2),
227                    value: Value::Utf8(v),
228                }) => f_group_name = Some(v),
229                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
230                Some(Element::ContainerStart { .. }) => r.skip_container()?,
231                Some(_) => {} // unknown/future scalar — skip
232            }
233        }
234        Ok(Self {
235            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
236            group_id: f_group_id.ok_or(ClusterError::MissingField("GroupId"))?,
237            group_name: f_group_name.ok_or(ClusterError::MissingField("GroupName"))?,
238        })
239    }
240    /// Decode from a standalone anonymous TLV structure.
241    ///
242    /// # Errors
243    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
244    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
245        let mut r = TlvReader::new(tlv);
246        match r.next()? {
247            Some(Element::ContainerStart {
248                kind: ContainerKind::Structure,
249                ..
250            }) => {}
251            _ => {
252                return Err(ClusterError::UnexpectedType {
253                    context: "ViewGroupResponse",
254                })
255            }
256        }
257        Self::decode_from(&mut r)
258    }
259}
260
261/// Encode the `GetGroupMembership` command request payload.
262#[must_use]
263#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
264pub fn encode_get_group_membership(group_list: &Vec<u16>) -> Vec<u8> {
265    let mut buf = Vec::new();
266    let mut w = TlvWriter::new(&mut buf);
267    w.start_structure(Tag::Anonymous)
268        .expect("infallible: vec writer");
269    w.start_array(Tag::Context(0))
270        .expect("infallible: vec writer");
271    for el in group_list.iter().copied() {
272        w.put_uint(Tag::Anonymous, u64::from(el))
273            .expect("infallible: vec writer");
274    }
275    w.end_container().expect("infallible: vec writer");
276    w.end_container().expect("infallible: vec writer");
277    buf
278}
279
280/// Decoded `GetGroupMembershipResponse` payload.
281#[derive(Clone, Debug, PartialEq)]
282#[non_exhaustive]
283pub struct GetGroupMembershipResponse {
284    /// Field Capacity (tag 0).
285    pub capacity: Nullable<u8>,
286    /// Field GroupList (tag 1).
287    pub group_list: Vec<u16>,
288}
289
290impl GetGroupMembershipResponse {
291    /// Decode the fields of an already-opened anonymous structure
292    /// (reader positioned after the struct start; consumes to its end).
293    ///
294    /// # Errors
295    /// Returns [`ClusterError`] on a malformed structure or missing required field.
296    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
297        let mut f_capacity: Option<Nullable<u8>> = None;
298        let mut f_group_list: Option<Vec<u16>> = None;
299        loop {
300            match r.next()? {
301                Some(Element::ContainerEnd) => break,
302                Some(Element::Scalar {
303                    tag: Tag::Context(0),
304                    value: Value::Null,
305                }) => f_capacity = Some(Nullable::Null),
306                Some(Element::Scalar {
307                    tag: Tag::Context(0),
308                    value: Value::Uint(v),
309                }) => {
310                    f_capacity = Some(Nullable::Value(
311                        u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Capacity"))?,
312                    ))
313                }
314                Some(Element::ContainerStart {
315                    tag: Tag::Context(1),
316                    kind: ContainerKind::Array,
317                }) => {
318                    let mut out = Vec::new();
319                    loop {
320                        match r.next()? {
321                            Some(Element::ContainerEnd) => break,
322                            Some(Element::Scalar {
323                                value: Value::Uint(v),
324                                ..
325                            }) => out.push(
326                                u16::try_from(v)
327                                    .map_err(|_| ClusterError::InvalidLength("GroupList"))?,
328                            ),
329                            None => {
330                                return Err(ClusterError::Tlv(
331                                    matter_codec::Error::UnclosedContainer,
332                                ))
333                            }
334                            Some(Element::ContainerStart { .. }) => r.skip_container()?,
335                            Some(_) => {} // skip unknown scalar
336                        }
337                    }
338                    f_group_list = Some(out);
339                }
340                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
341                Some(Element::ContainerStart { .. }) => r.skip_container()?,
342                Some(_) => {} // unknown/future scalar — skip
343            }
344        }
345        Ok(Self {
346            capacity: f_capacity.ok_or(ClusterError::MissingField("Capacity"))?,
347            group_list: f_group_list.ok_or(ClusterError::MissingField("GroupList"))?,
348        })
349    }
350    /// Decode from a standalone anonymous TLV structure.
351    ///
352    /// # Errors
353    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
354    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
355        let mut r = TlvReader::new(tlv);
356        match r.next()? {
357            Some(Element::ContainerStart {
358                kind: ContainerKind::Structure,
359                ..
360            }) => {}
361            _ => {
362                return Err(ClusterError::UnexpectedType {
363                    context: "GetGroupMembershipResponse",
364                })
365            }
366        }
367        Self::decode_from(&mut r)
368    }
369}
370
371/// Encode the `RemoveGroup` command request payload.
372#[must_use]
373#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
374pub fn encode_remove_group(group_id: u16) -> Vec<u8> {
375    let mut buf = Vec::new();
376    let mut w = TlvWriter::new(&mut buf);
377    w.start_structure(Tag::Anonymous)
378        .expect("infallible: vec writer");
379    w.put_uint(Tag::Context(0), u64::from(group_id))
380        .expect("infallible: vec writer");
381    w.end_container().expect("infallible: vec writer");
382    buf
383}
384
385/// Decoded `RemoveGroupResponse` payload.
386#[derive(Clone, Debug, PartialEq)]
387#[non_exhaustive]
388pub struct RemoveGroupResponse {
389    /// Field Status (tag 0).
390    pub status: u8,
391    /// Field GroupId (tag 1).
392    pub group_id: u16,
393}
394
395impl RemoveGroupResponse {
396    /// Decode the fields of an already-opened anonymous structure
397    /// (reader positioned after the struct start; consumes to its end).
398    ///
399    /// # Errors
400    /// Returns [`ClusterError`] on a malformed structure or missing required field.
401    pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
402        let mut f_status: Option<u8> = None;
403        let mut f_group_id: Option<u16> = None;
404        loop {
405            match r.next()? {
406                Some(Element::ContainerEnd) => break,
407                Some(Element::Scalar {
408                    tag: Tag::Context(0),
409                    value: Value::Uint(v),
410                }) => {
411                    f_status =
412                        Some(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Status"))?)
413                }
414                Some(Element::Scalar {
415                    tag: Tag::Context(1),
416                    value: Value::Uint(v),
417                }) => {
418                    f_group_id =
419                        Some(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("GroupId"))?)
420                }
421                None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
422                Some(Element::ContainerStart { .. }) => r.skip_container()?,
423                Some(_) => {} // unknown/future scalar — skip
424            }
425        }
426        Ok(Self {
427            status: f_status.ok_or(ClusterError::MissingField("Status"))?,
428            group_id: f_group_id.ok_or(ClusterError::MissingField("GroupId"))?,
429        })
430    }
431    /// Decode from a standalone anonymous TLV structure.
432    ///
433    /// # Errors
434    /// Returns [`ClusterError`] if the bytes are not an anonymous structure or a field is malformed.
435    pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
436        let mut r = TlvReader::new(tlv);
437        match r.next()? {
438            Some(Element::ContainerStart {
439                kind: ContainerKind::Structure,
440                ..
441            }) => {}
442            _ => {
443                return Err(ClusterError::UnexpectedType {
444                    context: "RemoveGroupResponse",
445                })
446            }
447        }
448        Self::decode_from(&mut r)
449    }
450}
451
452/// Encode the `RemoveAllGroups` command request payload.
453#[must_use]
454#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
455pub fn encode_remove_all_groups() -> Vec<u8> {
456    let mut buf = Vec::new();
457    let mut w = TlvWriter::new(&mut buf);
458    w.start_structure(Tag::Anonymous)
459        .expect("infallible: vec writer");
460    w.end_container().expect("infallible: vec writer");
461    buf
462}
463
464/// Encode the `AddGroupIfIdentifying` command request payload.
465#[must_use]
466#[allow(clippy::expect_used, clippy::missing_panics_doc)] // Vec-backed TlvWriter is infallible.
467pub fn encode_add_group_if_identifying(group_id: u16, group_name: &String) -> Vec<u8> {
468    let mut buf = Vec::new();
469    let mut w = TlvWriter::new(&mut buf);
470    w.start_structure(Tag::Anonymous)
471        .expect("infallible: vec writer");
472    w.put_uint(Tag::Context(0), u64::from(group_id))
473        .expect("infallible: vec writer");
474    w.put_utf8(Tag::Context(1), &group_name)
475        .expect("infallible: vec writer");
476    w.end_container().expect("infallible: vec writer");
477    buf
478}