matc/clusters/codec/
acl_cluster.rs

1//! Generated Matter TLV encoders and decoders for Access Control Cluster
2//! Cluster ID: 0x001F
3//! 
4//! This file is automatically generated from ACL-Cluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct AccessControlEntry {
15    pub privilege: Option<u8>,
16    pub auth_mode: Option<u8>,
17    pub subjects: Option<Vec<u64>>,
18    pub targets: Option<Vec<AccessControlTarget>>,
19}
20
21#[derive(Debug, serde::Serialize)]
22pub struct AccessControlExtension {
23    pub data: Option<Vec<u8>>,
24}
25
26#[derive(Debug, serde::Serialize)]
27pub struct AccessControlTarget {
28    pub cluster: Option<u32>,
29    pub endpoint: Option<u16>,
30    pub device_type: Option<u32>,
31}
32
33#[derive(Debug, serde::Serialize)]
34pub struct AccessRestrictionEntry {
35    pub endpoint: Option<u16>,
36    pub cluster: Option<u32>,
37    pub restrictions: Option<Vec<AccessRestriction>>,
38}
39
40#[derive(Debug, serde::Serialize)]
41pub struct AccessRestriction {
42    pub type_: Option<u8>,
43    pub id: Option<u32>,
44}
45
46#[derive(Debug, serde::Serialize)]
47pub struct CommissioningAccessRestrictionEntry {
48    pub endpoint: Option<u16>,
49    pub cluster: Option<u32>,
50    pub restrictions: Option<Vec<AccessRestriction>>,
51}
52
53// Command encoders
54
55/// Encode ReviewFabricRestrictions command (0x00)
56pub fn encode_review_fabric_restrictions(arl: Vec<u8>) -> anyhow::Result<Vec<u8>> {
57    let tlv = tlv::TlvItemEnc {
58        tag: 0,
59        value: tlv::TlvItemValueEnc::StructInvisible(vec![
60        (0, tlv::TlvItemValueEnc::StructAnon(arl.into_iter().map(|v| (0, tlv::TlvItemValueEnc::UInt8(v)).into()).collect())).into(),
61        ]),
62    };
63    Ok(tlv.encode()?)
64}
65
66// Attribute decoders
67
68/// Decode ACL attribute (0x0000)
69pub fn decode_acl(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<AccessControlEntry>> {
70    let mut res = Vec::new();
71    if let tlv::TlvItemValue::List(v) = inp {
72        for item in v {
73            res.push(AccessControlEntry {
74                privilege: item.get_int(&[1]).map(|v| v as u8),
75                auth_mode: item.get_int(&[2]).map(|v| v as u8),
76                subjects: {
77                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[3]) {
78                        let items: Vec<u64> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v) } else { None } }).collect();
79                        Some(items)
80                    } else {
81                        None
82                    }
83                },
84                targets: {
85                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[4]) {
86                        let mut items = Vec::new();
87                        for list_item in l {
88                            items.push(AccessControlTarget {
89                cluster: list_item.get_int(&[0]).map(|v| v as u32),
90                endpoint: list_item.get_int(&[1]).map(|v| v as u16),
91                device_type: list_item.get_int(&[2]).map(|v| v as u32),
92                            });
93                        }
94                        Some(items)
95                    } else {
96                        None
97                    }
98                },
99            });
100        }
101    }
102    Ok(res)
103}
104
105/// Decode Extension attribute (0x0001)
106pub fn decode_extension(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<AccessControlExtension>> {
107    let mut res = Vec::new();
108    if let tlv::TlvItemValue::List(v) = inp {
109        for item in v {
110            res.push(AccessControlExtension {
111                data: item.get_octet_string_owned(&[1]),
112            });
113        }
114    }
115    Ok(res)
116}
117
118/// Decode SubjectsPerAccessControlEntry attribute (0x0002)
119pub fn decode_subjects_per_access_control_entry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
120    if let tlv::TlvItemValue::Int(v) = inp {
121        Ok(*v as u16)
122    } else {
123        Err(anyhow::anyhow!("Expected Integer"))
124    }
125}
126
127/// Decode TargetsPerAccessControlEntry attribute (0x0003)
128pub fn decode_targets_per_access_control_entry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
129    if let tlv::TlvItemValue::Int(v) = inp {
130        Ok(*v as u16)
131    } else {
132        Err(anyhow::anyhow!("Expected Integer"))
133    }
134}
135
136/// Decode AccessControlEntriesPerFabric attribute (0x0004)
137pub fn decode_access_control_entries_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
138    if let tlv::TlvItemValue::Int(v) = inp {
139        Ok(*v as u16)
140    } else {
141        Err(anyhow::anyhow!("Expected Integer"))
142    }
143}
144
145/// Decode CommissioningARL attribute (0x0005)
146pub fn decode_commissioning_arl(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<CommissioningAccessRestrictionEntry>> {
147    let mut res = Vec::new();
148    if let tlv::TlvItemValue::List(v) = inp {
149        for item in v {
150            res.push(CommissioningAccessRestrictionEntry {
151                endpoint: item.get_int(&[0]).map(|v| v as u16),
152                cluster: item.get_int(&[1]).map(|v| v as u32),
153                restrictions: {
154                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[2]) {
155                        let mut items = Vec::new();
156                        for list_item in l {
157                            items.push(AccessRestriction {
158                type_: list_item.get_int(&[0]).map(|v| v as u8),
159                id: list_item.get_int(&[1]).map(|v| v as u32),
160                            });
161                        }
162                        Some(items)
163                    } else {
164                        None
165                    }
166                },
167            });
168        }
169    }
170    Ok(res)
171}
172
173/// Decode ARL attribute (0x0006)
174pub fn decode_arl(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<AccessRestrictionEntry>> {
175    let mut res = Vec::new();
176    if let tlv::TlvItemValue::List(v) = inp {
177        for item in v {
178            res.push(AccessRestrictionEntry {
179                endpoint: item.get_int(&[0]).map(|v| v as u16),
180                cluster: item.get_int(&[1]).map(|v| v as u32),
181                restrictions: {
182                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[2]) {
183                        let mut items = Vec::new();
184                        for list_item in l {
185                            items.push(AccessRestriction {
186                type_: list_item.get_int(&[0]).map(|v| v as u8),
187                id: list_item.get_int(&[1]).map(|v| v as u32),
188                            });
189                        }
190                        Some(items)
191                    } else {
192                        None
193                    }
194                },
195            });
196        }
197    }
198    Ok(res)
199}
200
201
202// JSON dispatcher function
203
204/// Decode attribute value and return as JSON string
205/// 
206/// # Parameters
207/// * `cluster_id` - The cluster identifier
208/// * `attribute_id` - The attribute identifier
209/// * `tlv_value` - The TLV value to decode
210/// 
211/// # Returns
212/// JSON string representation of the decoded value or error
213pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
214    // Verify this is the correct cluster
215    if cluster_id != 0x001F {
216        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x001F, got {}\"}}", cluster_id);
217    }
218    
219    match attribute_id {
220        0x0000 => {
221            match decode_acl(tlv_value) {
222                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
223                Err(e) => format!("{{\"error\": \"{}\"}}", e),
224            }
225        }
226        0x0001 => {
227            match decode_extension(tlv_value) {
228                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
229                Err(e) => format!("{{\"error\": \"{}\"}}", e),
230            }
231        }
232        0x0002 => {
233            match decode_subjects_per_access_control_entry(tlv_value) {
234                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
235                Err(e) => format!("{{\"error\": \"{}\"}}", e),
236            }
237        }
238        0x0003 => {
239            match decode_targets_per_access_control_entry(tlv_value) {
240                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
241                Err(e) => format!("{{\"error\": \"{}\"}}", e),
242            }
243        }
244        0x0004 => {
245            match decode_access_control_entries_per_fabric(tlv_value) {
246                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
247                Err(e) => format!("{{\"error\": \"{}\"}}", e),
248            }
249        }
250        0x0005 => {
251            match decode_commissioning_arl(tlv_value) {
252                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
253                Err(e) => format!("{{\"error\": \"{}\"}}", e),
254            }
255        }
256        0x0006 => {
257            match decode_arl(tlv_value) {
258                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
259                Err(e) => format!("{{\"error\": \"{}\"}}", e),
260            }
261        }
262        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
263    }
264}
265
266/// Get list of all attributes supported by this cluster
267/// 
268/// # Returns
269/// Vector of tuples containing (attribute_id, attribute_name)
270pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
271    vec![
272        (0x0000, "ACL"),
273        (0x0001, "Extension"),
274        (0x0002, "SubjectsPerAccessControlEntry"),
275        (0x0003, "TargetsPerAccessControlEntry"),
276        (0x0004, "AccessControlEntriesPerFabric"),
277        (0x0005, "CommissioningARL"),
278        (0x0006, "ARL"),
279    ]
280}
281