1#![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
17pub const CLUSTER_ID: u32 = 0x001F;
19pub const CLUSTER_REVISION: u16 = 2;
21
22pub mod command_id {
24 pub const REVIEW_FABRIC_RESTRICTIONS: u32 = 0x00;
26 pub const REVIEW_FABRIC_RESTRICTIONS_RESPONSE: u32 = 0x01;
28}
29
30pub mod attribute_id {
32 pub const ACL: u32 = 0x0000;
34 pub const EXTENSION: u32 = 0x0001;
36 pub const SUBJECTS_PER_ACCESS_CONTROL_ENTRY: u32 = 0x0002;
38 pub const TARGETS_PER_ACCESS_CONTROL_ENTRY: u32 = 0x0003;
40 pub const ACCESS_CONTROL_ENTRIES_PER_FABRIC: u32 = 0x0004;
42 pub const COMMISSIONING_ARL: u32 = 0x0005;
44 pub const ARL: u32 = 0x0006;
46}
47
48bitflags::bitflags! {
49 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
51 pub struct Feature: u32 {
52 const EXTS = 1 << 0;
54 const MNGD = 1 << 1;
56 }
57}
58
59#[derive(Copy, Clone, Debug, PartialEq, Eq)]
61pub enum AccessControlEntryAuthModeEnum {
62 Pase,
64 Case,
66 Group,
68 Unknown(u8),
70}
71
72impl AccessControlEntryAuthModeEnum {
73 #[must_use]
75 pub fn from_raw(v: u8) -> Self {
76 match v {
77 1 => Self::Pase,
78 2 => Self::Case,
79 3 => Self::Group,
80 other => Self::Unknown(other),
81 }
82 }
83 #[must_use]
85 pub fn to_raw(self) -> u8 {
86 match self {
87 Self::Pase => 1,
88 Self::Case => 2,
89 Self::Group => 3,
90 Self::Unknown(v) => v,
91 }
92 }
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97pub enum AccessControlEntryPrivilegeEnum {
98 View,
100 ProxyView,
102 Operate,
104 Manage,
106 Administer,
108 Unknown(u8),
110}
111
112impl AccessControlEntryPrivilegeEnum {
113 #[must_use]
115 pub fn from_raw(v: u8) -> Self {
116 match v {
117 1 => Self::View,
118 2 => Self::ProxyView,
119 3 => Self::Operate,
120 4 => Self::Manage,
121 5 => Self::Administer,
122 other => Self::Unknown(other),
123 }
124 }
125 #[must_use]
127 pub fn to_raw(self) -> u8 {
128 match self {
129 Self::View => 1,
130 Self::ProxyView => 2,
131 Self::Operate => 3,
132 Self::Manage => 4,
133 Self::Administer => 5,
134 Self::Unknown(v) => v,
135 }
136 }
137}
138
139#[derive(Clone, Debug, PartialEq)]
141#[non_exhaustive]
142pub struct AccessControlEntryStruct {
143 pub privilege: AccessControlEntryPrivilegeEnum,
145 pub auth_mode: AccessControlEntryAuthModeEnum,
147 pub subjects: Nullable<Vec<u64>>,
149 pub targets: Nullable<Vec<AccessControlTargetStruct>>,
151 pub fabric_index: u8,
153}
154
155#[derive(Clone, Debug, PartialEq)]
157#[non_exhaustive]
158pub struct AccessControlExtensionStruct {
159 pub data: Vec<u8>,
161 pub fabric_index: u8,
163}
164
165#[derive(Clone, Debug, PartialEq)]
167#[non_exhaustive]
168pub struct AccessControlTargetStruct {
169 pub cluster: Nullable<u32>,
171 pub endpoint: Nullable<u16>,
173 pub device_type: Nullable<u32>,
175}
176
177#[derive(Clone, Debug, PartialEq)]
179#[non_exhaustive]
180pub struct AccessRestrictionEntryStruct {
181 pub endpoint: u16,
183 pub cluster: u32,
185 pub restrictions: Vec<AccessRestrictionStruct>,
187 pub fabric_index: u8,
189}
190
191#[derive(Clone, Debug, PartialEq)]
193pub struct AccessRestrictionStruct {
194 pub r#type: AccessRestrictionTypeEnum,
196 pub id: Nullable<u32>,
198}
199
200#[derive(Copy, Clone, Debug, PartialEq, Eq)]
202pub enum AccessRestrictionTypeEnum {
203 AttributeAccessForbidden,
205 AttributeWriteForbidden,
207 CommandForbidden,
209 EventForbidden,
211 Unknown(u8),
213}
214
215impl AccessRestrictionTypeEnum {
216 #[must_use]
218 pub fn from_raw(v: u8) -> Self {
219 match v {
220 0 => Self::AttributeAccessForbidden,
221 1 => Self::AttributeWriteForbidden,
222 2 => Self::CommandForbidden,
223 3 => Self::EventForbidden,
224 other => Self::Unknown(other),
225 }
226 }
227 #[must_use]
229 pub fn to_raw(self) -> u8 {
230 match self {
231 Self::AttributeAccessForbidden => 0,
232 Self::AttributeWriteForbidden => 1,
233 Self::CommandForbidden => 2,
234 Self::EventForbidden => 3,
235 Self::Unknown(v) => v,
236 }
237 }
238}
239
240#[derive(Copy, Clone, Debug, PartialEq, Eq)]
242pub enum ChangeTypeEnum {
243 Changed,
245 Added,
247 Removed,
249 Unknown(u8),
251}
252
253impl ChangeTypeEnum {
254 #[must_use]
256 pub fn from_raw(v: u8) -> Self {
257 match v {
258 0 => Self::Changed,
259 1 => Self::Added,
260 2 => Self::Removed,
261 other => Self::Unknown(other),
262 }
263 }
264 #[must_use]
266 pub fn to_raw(self) -> u8 {
267 match self {
268 Self::Changed => 0,
269 Self::Added => 1,
270 Self::Removed => 2,
271 Self::Unknown(v) => v,
272 }
273 }
274}
275
276#[derive(Clone, Debug, PartialEq)]
278pub struct CommissioningAccessRestrictionEntryStruct {
279 pub endpoint: u16,
281 pub cluster: u32,
283 pub restrictions: Vec<AccessRestrictionStruct>,
285}
286
287impl AccessControlEntryStruct {
288 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
294 let mut f_privilege: Option<AccessControlEntryPrivilegeEnum> = None;
295 let mut f_auth_mode: Option<AccessControlEntryAuthModeEnum> = None;
296 let mut f_subjects: Option<Nullable<Vec<u64>>> = None;
297 let mut f_targets: Option<Nullable<Vec<AccessControlTargetStruct>>> = None;
298 let mut f_fabric_index: Option<u8> = None;
299 loop {
300 match r.next()? {
301 Some(Element::ContainerEnd) => break,
302 Some(Element::Scalar {
303 tag: Tag::Context(1),
304 value: Value::Uint(v),
305 }) => {
306 f_privilege = Some(AccessControlEntryPrivilegeEnum::from_raw(
307 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Privilege"))?,
308 ))
309 }
310 Some(Element::Scalar {
311 tag: Tag::Context(2),
312 value: Value::Uint(v),
313 }) => {
314 f_auth_mode = Some(AccessControlEntryAuthModeEnum::from_raw(
315 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("AuthMode"))?,
316 ))
317 }
318 Some(Element::Scalar {
319 tag: Tag::Context(3),
320 value: Value::Null,
321 }) => f_subjects = Some(Nullable::Null),
322 Some(Element::ContainerStart {
323 tag: Tag::Context(3),
324 kind: ContainerKind::Array,
325 }) => {
326 let mut out = Vec::new();
327 loop {
328 match r.next()? {
329 Some(Element::ContainerEnd) => break,
330 Some(Element::Scalar {
331 value: Value::Uint(v),
332 ..
333 }) => out.push(
334 u64::try_from(v)
335 .map_err(|_| ClusterError::InvalidLength("Subjects"))?,
336 ),
337 None => {
338 return Err(ClusterError::Tlv(
339 matter_codec::Error::UnclosedContainer,
340 ))
341 }
342 Some(Element::ContainerStart { .. }) => r.skip_container()?,
343 Some(_) => {} }
345 }
346 f_subjects = Some(Nullable::Value(out));
347 }
348 Some(Element::Scalar {
349 tag: Tag::Context(4),
350 value: Value::Null,
351 }) => f_targets = Some(Nullable::Null),
352 Some(Element::ContainerStart {
353 tag: Tag::Context(4),
354 kind: ContainerKind::Array,
355 }) => {
356 let mut out = Vec::new();
357 loop {
358 match r.next()? {
359 Some(Element::ContainerEnd) => break,
360 Some(Element::ContainerStart {
361 kind: ContainerKind::Structure,
362 ..
363 }) => {
364 out.push(AccessControlTargetStruct::decode_from(r)?);
365 }
366 None => {
367 return Err(ClusterError::Tlv(
368 matter_codec::Error::UnclosedContainer,
369 ))
370 }
371 Some(Element::ContainerStart { .. }) => r.skip_container()?,
372 Some(_) => {} }
374 }
375 f_targets = Some(Nullable::Value(out));
376 }
377 Some(Element::Scalar {
378 tag: Tag::Context(254),
379 value: Value::Uint(v),
380 }) => {
381 f_fabric_index = Some(
382 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
383 )
384 }
385 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
386 Some(Element::ContainerStart { .. }) => r.skip_container()?,
387 Some(_) => {} }
389 }
390 Ok(Self {
391 privilege: f_privilege.ok_or(ClusterError::MissingField("Privilege"))?,
392 auth_mode: f_auth_mode.ok_or(ClusterError::MissingField("AuthMode"))?,
393 subjects: f_subjects.ok_or(ClusterError::MissingField("Subjects"))?,
394 targets: f_targets.ok_or(ClusterError::MissingField("Targets"))?,
395 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
396 })
397 }
398 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
403 let mut r = TlvReader::new(tlv);
404 match r.next()? {
405 Some(Element::ContainerStart {
406 kind: ContainerKind::Structure,
407 ..
408 }) => {}
409 _ => {
410 return Err(ClusterError::UnexpectedType {
411 context: "AccessControlEntryStruct",
412 })
413 }
414 }
415 Self::decode_from(&mut r)
416 }
417}
418
419impl AccessControlExtensionStruct {
420 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
426 let mut f_data: Option<Vec<u8>> = None;
427 let mut f_fabric_index: Option<u8> = None;
428 loop {
429 match r.next()? {
430 Some(Element::ContainerEnd) => break,
431 Some(Element::Scalar {
432 tag: Tag::Context(1),
433 value: Value::Bytes(v),
434 }) => f_data = Some(v),
435 Some(Element::Scalar {
436 tag: Tag::Context(254),
437 value: Value::Uint(v),
438 }) => {
439 f_fabric_index = Some(
440 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
441 )
442 }
443 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
444 Some(Element::ContainerStart { .. }) => r.skip_container()?,
445 Some(_) => {} }
447 }
448 Ok(Self {
449 data: f_data.ok_or(ClusterError::MissingField("Data"))?,
450 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
451 })
452 }
453 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
458 let mut r = TlvReader::new(tlv);
459 match r.next()? {
460 Some(Element::ContainerStart {
461 kind: ContainerKind::Structure,
462 ..
463 }) => {}
464 _ => {
465 return Err(ClusterError::UnexpectedType {
466 context: "AccessControlExtensionStruct",
467 })
468 }
469 }
470 Self::decode_from(&mut r)
471 }
472 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
475 w.put_bytes(Tag::Context(1), &self.data)
476 .expect("infallible: vec writer");
477 w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
478 .expect("infallible: vec writer");
479 }
480 #[must_use]
482 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
484 let mut buf = Vec::new();
485 let mut w = TlvWriter::new(&mut buf);
486 w.start_structure(Tag::Anonymous)
487 .expect("infallible: vec writer");
488 self.write_fields(&mut w);
489 w.end_container().expect("infallible: vec writer");
490 buf
491 }
492}
493
494impl AccessControlTargetStruct {
495 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
501 let mut f_cluster: Option<Nullable<u32>> = None;
502 let mut f_endpoint: Option<Nullable<u16>> = None;
503 let mut f_device_type: Option<Nullable<u32>> = None;
504 loop {
505 match r.next()? {
506 Some(Element::ContainerEnd) => break,
507 Some(Element::Scalar {
508 tag: Tag::Context(0),
509 value: Value::Null,
510 }) => f_cluster = Some(Nullable::Null),
511 Some(Element::Scalar {
512 tag: Tag::Context(0),
513 value: Value::Uint(v),
514 }) => {
515 f_cluster = Some(Nullable::Value(
516 u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Cluster"))?,
517 ))
518 }
519 Some(Element::Scalar {
520 tag: Tag::Context(1),
521 value: Value::Null,
522 }) => f_endpoint = Some(Nullable::Null),
523 Some(Element::Scalar {
524 tag: Tag::Context(1),
525 value: Value::Uint(v),
526 }) => {
527 f_endpoint = Some(Nullable::Value(
528 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Endpoint"))?,
529 ))
530 }
531 Some(Element::Scalar {
532 tag: Tag::Context(2),
533 value: Value::Null,
534 }) => f_device_type = Some(Nullable::Null),
535 Some(Element::Scalar {
536 tag: Tag::Context(2),
537 value: Value::Uint(v),
538 }) => {
539 f_device_type = Some(Nullable::Value(
540 u32::try_from(v).map_err(|_| ClusterError::InvalidLength("DeviceType"))?,
541 ))
542 }
543 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
544 Some(Element::ContainerStart { .. }) => r.skip_container()?,
545 Some(_) => {} }
547 }
548 Ok(Self {
549 cluster: f_cluster.ok_or(ClusterError::MissingField("Cluster"))?,
550 endpoint: f_endpoint.ok_or(ClusterError::MissingField("Endpoint"))?,
551 device_type: f_device_type.ok_or(ClusterError::MissingField("DeviceType"))?,
552 })
553 }
554 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
559 let mut r = TlvReader::new(tlv);
560 match r.next()? {
561 Some(Element::ContainerStart {
562 kind: ContainerKind::Structure,
563 ..
564 }) => {}
565 _ => {
566 return Err(ClusterError::UnexpectedType {
567 context: "AccessControlTargetStruct",
568 })
569 }
570 }
571 Self::decode_from(&mut r)
572 }
573 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
576 match &self.cluster {
577 Nullable::Null => w.put_null(Tag::Context(0)).expect("infallible: vec writer"),
578 Nullable::Value(cluster) => {
579 w.put_uint(Tag::Context(0), u64::from(*cluster))
580 .expect("infallible: vec writer");
581 }
582 }
583 match &self.endpoint {
584 Nullable::Null => w.put_null(Tag::Context(1)).expect("infallible: vec writer"),
585 Nullable::Value(endpoint) => {
586 w.put_uint(Tag::Context(1), u64::from(*endpoint))
587 .expect("infallible: vec writer");
588 }
589 }
590 match &self.device_type {
591 Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
592 Nullable::Value(device_type) => {
593 w.put_uint(Tag::Context(2), u64::from(*device_type))
594 .expect("infallible: vec writer");
595 }
596 }
597 }
598 #[must_use]
600 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
602 let mut buf = Vec::new();
603 let mut w = TlvWriter::new(&mut buf);
604 w.start_structure(Tag::Anonymous)
605 .expect("infallible: vec writer");
606 self.write_fields(&mut w);
607 w.end_container().expect("infallible: vec writer");
608 buf
609 }
610}
611
612impl AccessRestrictionEntryStruct {
613 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
619 let mut f_endpoint: Option<u16> = None;
620 let mut f_cluster: Option<u32> = None;
621 let mut f_restrictions: Option<Vec<AccessRestrictionStruct>> = None;
622 let mut f_fabric_index: Option<u8> = None;
623 loop {
624 match r.next()? {
625 Some(Element::ContainerEnd) => break,
626 Some(Element::Scalar {
627 tag: Tag::Context(0),
628 value: Value::Uint(v),
629 }) => {
630 f_endpoint = Some(
631 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Endpoint"))?,
632 )
633 }
634 Some(Element::Scalar {
635 tag: Tag::Context(1),
636 value: Value::Uint(v),
637 }) => {
638 f_cluster =
639 Some(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Cluster"))?)
640 }
641 Some(Element::ContainerStart {
642 tag: Tag::Context(2),
643 kind: ContainerKind::Array,
644 }) => {
645 let mut out = Vec::new();
646 loop {
647 match r.next()? {
648 Some(Element::ContainerEnd) => break,
649 Some(Element::ContainerStart {
650 kind: ContainerKind::Structure,
651 ..
652 }) => {
653 out.push(AccessRestrictionStruct::decode_from(r)?);
654 }
655 None => {
656 return Err(ClusterError::Tlv(
657 matter_codec::Error::UnclosedContainer,
658 ))
659 }
660 Some(Element::ContainerStart { .. }) => r.skip_container()?,
661 Some(_) => {} }
663 }
664 f_restrictions = Some(out);
665 }
666 Some(Element::Scalar {
667 tag: Tag::Context(254),
668 value: Value::Uint(v),
669 }) => {
670 f_fabric_index = Some(
671 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
672 )
673 }
674 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
675 Some(Element::ContainerStart { .. }) => r.skip_container()?,
676 Some(_) => {} }
678 }
679 Ok(Self {
680 endpoint: f_endpoint.ok_or(ClusterError::MissingField("Endpoint"))?,
681 cluster: f_cluster.ok_or(ClusterError::MissingField("Cluster"))?,
682 restrictions: f_restrictions.ok_or(ClusterError::MissingField("Restrictions"))?,
683 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
684 })
685 }
686 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
691 let mut r = TlvReader::new(tlv);
692 match r.next()? {
693 Some(Element::ContainerStart {
694 kind: ContainerKind::Structure,
695 ..
696 }) => {}
697 _ => {
698 return Err(ClusterError::UnexpectedType {
699 context: "AccessRestrictionEntryStruct",
700 })
701 }
702 }
703 Self::decode_from(&mut r)
704 }
705}
706
707impl AccessRestrictionStruct {
708 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
714 let mut f_type: Option<AccessRestrictionTypeEnum> = None;
715 let mut f_id: Option<Nullable<u32>> = None;
716 loop {
717 match r.next()? {
718 Some(Element::ContainerEnd) => break,
719 Some(Element::Scalar {
720 tag: Tag::Context(0),
721 value: Value::Uint(v),
722 }) => {
723 f_type = Some(AccessRestrictionTypeEnum::from_raw(
724 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("Type"))?,
725 ))
726 }
727 Some(Element::Scalar {
728 tag: Tag::Context(1),
729 value: Value::Null,
730 }) => f_id = Some(Nullable::Null),
731 Some(Element::Scalar {
732 tag: Tag::Context(1),
733 value: Value::Uint(v),
734 }) => {
735 f_id = Some(Nullable::Value(
736 u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Id"))?,
737 ))
738 }
739 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
740 Some(Element::ContainerStart { .. }) => r.skip_container()?,
741 Some(_) => {} }
743 }
744 Ok(Self {
745 r#type: f_type.ok_or(ClusterError::MissingField("Type"))?,
746 id: f_id.ok_or(ClusterError::MissingField("Id"))?,
747 })
748 }
749 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
754 let mut r = TlvReader::new(tlv);
755 match r.next()? {
756 Some(Element::ContainerStart {
757 kind: ContainerKind::Structure,
758 ..
759 }) => {}
760 _ => {
761 return Err(ClusterError::UnexpectedType {
762 context: "AccessRestrictionStruct",
763 })
764 }
765 }
766 Self::decode_from(&mut r)
767 }
768 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
771 w.put_uint(Tag::Context(0), u64::from(self.r#type.to_raw()))
772 .expect("infallible: vec writer");
773 match &self.id {
774 Nullable::Null => w.put_null(Tag::Context(1)).expect("infallible: vec writer"),
775 Nullable::Value(id) => {
776 w.put_uint(Tag::Context(1), u64::from(*id))
777 .expect("infallible: vec writer");
778 }
779 }
780 }
781 #[must_use]
783 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
785 let mut buf = Vec::new();
786 let mut w = TlvWriter::new(&mut buf);
787 w.start_structure(Tag::Anonymous)
788 .expect("infallible: vec writer");
789 self.write_fields(&mut w);
790 w.end_container().expect("infallible: vec writer");
791 buf
792 }
793}
794
795impl CommissioningAccessRestrictionEntryStruct {
796 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
802 let mut f_endpoint: Option<u16> = None;
803 let mut f_cluster: Option<u32> = None;
804 let mut f_restrictions: Option<Vec<AccessRestrictionStruct>> = None;
805 loop {
806 match r.next()? {
807 Some(Element::ContainerEnd) => break,
808 Some(Element::Scalar {
809 tag: Tag::Context(0),
810 value: Value::Uint(v),
811 }) => {
812 f_endpoint = Some(
813 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Endpoint"))?,
814 )
815 }
816 Some(Element::Scalar {
817 tag: Tag::Context(1),
818 value: Value::Uint(v),
819 }) => {
820 f_cluster =
821 Some(u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Cluster"))?)
822 }
823 Some(Element::ContainerStart {
824 tag: Tag::Context(2),
825 kind: ContainerKind::Array,
826 }) => {
827 let mut out = Vec::new();
828 loop {
829 match r.next()? {
830 Some(Element::ContainerEnd) => break,
831 Some(Element::ContainerStart {
832 kind: ContainerKind::Structure,
833 ..
834 }) => {
835 out.push(AccessRestrictionStruct::decode_from(r)?);
836 }
837 None => {
838 return Err(ClusterError::Tlv(
839 matter_codec::Error::UnclosedContainer,
840 ))
841 }
842 Some(Element::ContainerStart { .. }) => r.skip_container()?,
843 Some(_) => {} }
845 }
846 f_restrictions = Some(out);
847 }
848 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
849 Some(Element::ContainerStart { .. }) => r.skip_container()?,
850 Some(_) => {} }
852 }
853 Ok(Self {
854 endpoint: f_endpoint.ok_or(ClusterError::MissingField("Endpoint"))?,
855 cluster: f_cluster.ok_or(ClusterError::MissingField("Cluster"))?,
856 restrictions: f_restrictions.ok_or(ClusterError::MissingField("Restrictions"))?,
857 })
858 }
859 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
864 let mut r = TlvReader::new(tlv);
865 match r.next()? {
866 Some(Element::ContainerStart {
867 kind: ContainerKind::Structure,
868 ..
869 }) => {}
870 _ => {
871 return Err(ClusterError::UnexpectedType {
872 context: "CommissioningAccessRestrictionEntryStruct",
873 })
874 }
875 }
876 Self::decode_from(&mut r)
877 }
878 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
881 w.put_uint(Tag::Context(0), u64::from(self.endpoint))
882 .expect("infallible: vec writer");
883 w.put_uint(Tag::Context(1), u64::from(self.cluster))
884 .expect("infallible: vec writer");
885 w.start_array(Tag::Context(2))
886 .expect("infallible: vec writer");
887 for el in &self.restrictions {
888 w.start_structure(Tag::Anonymous)
889 .expect("infallible: vec writer");
890 el.write_fields(w);
891 w.end_container().expect("infallible: vec writer");
892 }
893 w.end_container().expect("infallible: vec writer");
894 }
895 #[must_use]
897 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
899 let mut buf = Vec::new();
900 let mut w = TlvWriter::new(&mut buf);
901 w.start_structure(Tag::Anonymous)
902 .expect("infallible: vec writer");
903 self.write_fields(&mut w);
904 w.end_container().expect("infallible: vec writer");
905 buf
906 }
907}
908
909pub fn decode_acl(tlv: &[u8]) -> Result<Vec<AccessControlEntryStruct>, ClusterError> {
914 let mut r = TlvReader::new(tlv);
915 match r.next()? {
916 Some(Element::ContainerStart {
917 kind: ContainerKind::Array,
918 ..
919 }) => {}
920 _ => return Err(ClusterError::UnexpectedType { context: "Acl" }),
921 }
922 let r = &mut r;
923 let mut out = Vec::new();
924 loop {
925 match r.next()? {
926 Some(Element::ContainerEnd) => break,
927 Some(Element::ContainerStart {
928 kind: ContainerKind::Structure,
929 ..
930 }) => {
931 out.push(AccessControlEntryStruct::decode_from(r)?);
932 }
933 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
934 Some(Element::ContainerStart { .. }) => r.skip_container()?,
935 Some(_) => {} }
937 }
938 Ok(out)
939}
940
941pub fn decode_extension(tlv: &[u8]) -> Result<Vec<AccessControlExtensionStruct>, ClusterError> {
946 let mut r = TlvReader::new(tlv);
947 match r.next()? {
948 Some(Element::ContainerStart {
949 kind: ContainerKind::Array,
950 ..
951 }) => {}
952 _ => {
953 return Err(ClusterError::UnexpectedType {
954 context: "Extension",
955 })
956 }
957 }
958 let r = &mut r;
959 let mut out = Vec::new();
960 loop {
961 match r.next()? {
962 Some(Element::ContainerEnd) => break,
963 Some(Element::ContainerStart {
964 kind: ContainerKind::Structure,
965 ..
966 }) => {
967 out.push(AccessControlExtensionStruct::decode_from(r)?);
968 }
969 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
970 Some(Element::ContainerStart { .. }) => r.skip_container()?,
971 Some(_) => {} }
973 }
974 Ok(out)
975}
976
977pub fn decode_subjects_per_access_control_entry(tlv: &[u8]) -> Result<u16, ClusterError> {
982 let mut r = TlvReader::new(tlv);
983 match r.next()? {
984 Some(Element::Scalar {
985 value: Value::Uint(v),
986 ..
987 }) => Ok(u16::try_from(v)
988 .map_err(|_| ClusterError::InvalidLength("SubjectsPerAccessControlEntry"))?),
989 _ => Err(ClusterError::UnexpectedType {
990 context: "SubjectsPerAccessControlEntry",
991 }),
992 }
993}
994
995pub fn decode_targets_per_access_control_entry(tlv: &[u8]) -> Result<u16, ClusterError> {
1000 let mut r = TlvReader::new(tlv);
1001 match r.next()? {
1002 Some(Element::Scalar {
1003 value: Value::Uint(v),
1004 ..
1005 }) => Ok(u16::try_from(v)
1006 .map_err(|_| ClusterError::InvalidLength("TargetsPerAccessControlEntry"))?),
1007 _ => Err(ClusterError::UnexpectedType {
1008 context: "TargetsPerAccessControlEntry",
1009 }),
1010 }
1011}
1012
1013pub fn decode_access_control_entries_per_fabric(tlv: &[u8]) -> Result<u16, ClusterError> {
1018 let mut r = TlvReader::new(tlv);
1019 match r.next()? {
1020 Some(Element::Scalar {
1021 value: Value::Uint(v),
1022 ..
1023 }) => Ok(u16::try_from(v)
1024 .map_err(|_| ClusterError::InvalidLength("AccessControlEntriesPerFabric"))?),
1025 _ => Err(ClusterError::UnexpectedType {
1026 context: "AccessControlEntriesPerFabric",
1027 }),
1028 }
1029}
1030
1031pub fn decode_commissioning_arl(
1036 tlv: &[u8],
1037) -> Result<Vec<CommissioningAccessRestrictionEntryStruct>, ClusterError> {
1038 let mut r = TlvReader::new(tlv);
1039 match r.next()? {
1040 Some(Element::ContainerStart {
1041 kind: ContainerKind::Array,
1042 ..
1043 }) => {}
1044 _ => {
1045 return Err(ClusterError::UnexpectedType {
1046 context: "CommissioningArl",
1047 })
1048 }
1049 }
1050 let r = &mut r;
1051 let mut out = Vec::new();
1052 loop {
1053 match r.next()? {
1054 Some(Element::ContainerEnd) => break,
1055 Some(Element::ContainerStart {
1056 kind: ContainerKind::Structure,
1057 ..
1058 }) => {
1059 out.push(CommissioningAccessRestrictionEntryStruct::decode_from(r)?);
1060 }
1061 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1062 Some(Element::ContainerStart { .. }) => r.skip_container()?,
1063 Some(_) => {} }
1065 }
1066 Ok(out)
1067}
1068
1069pub fn decode_arl(tlv: &[u8]) -> Result<Vec<AccessRestrictionEntryStruct>, ClusterError> {
1074 let mut r = TlvReader::new(tlv);
1075 match r.next()? {
1076 Some(Element::ContainerStart {
1077 kind: ContainerKind::Array,
1078 ..
1079 }) => {}
1080 _ => return Err(ClusterError::UnexpectedType { context: "Arl" }),
1081 }
1082 let r = &mut r;
1083 let mut out = Vec::new();
1084 loop {
1085 match r.next()? {
1086 Some(Element::ContainerEnd) => break,
1087 Some(Element::ContainerStart {
1088 kind: ContainerKind::Structure,
1089 ..
1090 }) => {
1091 out.push(AccessRestrictionEntryStruct::decode_from(r)?);
1092 }
1093 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1094 Some(Element::ContainerStart { .. }) => r.skip_container()?,
1095 Some(_) => {} }
1097 }
1098 Ok(out)
1099}
1100
1101#[must_use]
1103#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_review_fabric_restrictions(
1105 arl: &Vec<CommissioningAccessRestrictionEntryStruct>,
1106) -> Vec<u8> {
1107 let mut buf = Vec::new();
1108 let mut w = TlvWriter::new(&mut buf);
1109 w.start_structure(Tag::Anonymous)
1110 .expect("infallible: vec writer");
1111 w.start_array(Tag::Context(0))
1112 .expect("infallible: vec writer");
1113 for el in arl.iter() {
1114 w.start_structure(Tag::Anonymous)
1115 .expect("infallible: vec writer");
1116 el.write_fields(&mut w);
1117 w.end_container().expect("infallible: vec writer");
1118 }
1119 w.end_container().expect("infallible: vec writer");
1120 w.end_container().expect("infallible: vec writer");
1121 buf
1122}
1123
1124#[derive(Clone, Debug, PartialEq)]
1126#[non_exhaustive]
1127pub struct ReviewFabricRestrictionsResponse {
1128 pub token: u64,
1130}
1131
1132impl ReviewFabricRestrictionsResponse {
1133 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1139 let mut f_token: Option<u64> = None;
1140 loop {
1141 match r.next()? {
1142 Some(Element::ContainerEnd) => break,
1143 Some(Element::Scalar {
1144 tag: Tag::Context(0),
1145 value: Value::Uint(v),
1146 }) => {
1147 f_token =
1148 Some(u64::try_from(v).map_err(|_| ClusterError::InvalidLength("Token"))?)
1149 }
1150 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1151 Some(Element::ContainerStart { .. }) => r.skip_container()?,
1152 Some(_) => {} }
1154 }
1155 Ok(Self {
1156 token: f_token.ok_or(ClusterError::MissingField("Token"))?,
1157 })
1158 }
1159 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1164 let mut r = TlvReader::new(tlv);
1165 match r.next()? {
1166 Some(Element::ContainerStart {
1167 kind: ContainerKind::Structure,
1168 ..
1169 }) => {}
1170 _ => {
1171 return Err(ClusterError::UnexpectedType {
1172 context: "ReviewFabricRestrictionsResponse",
1173 })
1174 }
1175 }
1176 Self::decode_from(&mut r)
1177 }
1178}