matc/clusters/codec/
joint_fabric_datastore_cluster.rs

1//! Generated Matter TLV encoders and decoders for Joint Fabric Datastore Cluster
2//! Cluster ID: 0x0752
3//! 
4//! This file is automatically generated from JointFabricDatastoreCluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct DatastoreACLEntry {
15    pub node_id: Option<u64>,
16    pub list_id: Option<u16>,
17    pub acl_entry: Option<DatastoreAccessControlEntry>,
18    pub status_entry: Option<DatastoreStatusEntry>,
19}
20
21#[derive(Debug, serde::Serialize)]
22pub struct DatastoreAccessControlEntry {
23    pub privilege: Option<u8>,
24    pub auth_mode: Option<u8>,
25    pub subjects: Option<Vec<u64>>,
26    pub targets: Option<Vec<DatastoreAccessControlTarget>>,
27}
28
29#[derive(Debug, serde::Serialize)]
30pub struct DatastoreAccessControlTarget {
31    pub cluster: Option<u32>,
32    pub endpoint: Option<u16>,
33    pub device_type: Option<u32>,
34}
35
36#[derive(Debug, serde::Serialize)]
37pub struct DatastoreAdministratorInformationEntry {
38    pub node_id: Option<u64>,
39    pub friendly_name: Option<String>,
40    pub vendor_id: Option<u16>,
41    pub icac: Option<Vec<u8>>,
42}
43
44#[derive(Debug, serde::Serialize)]
45pub struct DatastoreBindingTarget {
46    pub node: Option<u64>,
47    pub group: Option<u8>,
48    pub endpoint: Option<u16>,
49    pub cluster: Option<u32>,
50}
51
52#[derive(Debug, serde::Serialize)]
53pub struct DatastoreEndpointBindingEntry {
54    pub node_id: Option<u64>,
55    pub endpoint_id: Option<u16>,
56    pub list_id: Option<u16>,
57    pub binding: Option<DatastoreBindingTarget>,
58    pub status_entry: Option<DatastoreStatusEntry>,
59}
60
61#[derive(Debug, serde::Serialize)]
62pub struct DatastoreEndpointEntry {
63    pub endpoint_id: Option<u16>,
64    pub node_id: Option<u64>,
65    pub friendly_name: Option<String>,
66    pub status_entry: Option<DatastoreStatusEntry>,
67}
68
69#[derive(Debug, serde::Serialize)]
70pub struct DatastoreEndpointGroupIDEntry {
71    pub node_id: Option<u64>,
72    pub endpoint_id: Option<u16>,
73    pub group_id: Option<u8>,
74    pub status_entry: Option<DatastoreStatusEntry>,
75}
76
77#[derive(Debug, serde::Serialize)]
78pub struct DatastoreGroupInformationEntry {
79    pub group_id: Option<u64>,
80    pub friendly_name: Option<String>,
81    pub group_key_set_id: Option<u16>,
82    pub group_cat: Option<u16>,
83    pub group_cat_version: Option<u16>,
84    pub group_permission: Option<u8>,
85}
86
87#[derive(Debug, serde::Serialize)]
88pub struct DatastoreGroupKeySet {
89    pub group_key_set_id: Option<u16>,
90    pub group_key_security_policy: Option<u8>,
91    pub epoch_key0: Option<Vec<u8>>,
92    pub epoch_start_time0: Option<u8>,
93    pub epoch_key1: Option<Vec<u8>>,
94    pub epoch_start_time1: Option<u8>,
95    pub epoch_key2: Option<Vec<u8>>,
96    pub epoch_start_time2: Option<u8>,
97    pub group_key_multicast_policy: Option<u8>,
98}
99
100#[derive(Debug, serde::Serialize)]
101pub struct DatastoreNodeInformationEntry {
102    pub node_id: Option<u64>,
103    pub friendly_name: Option<String>,
104    pub commissioning_status_entry: Option<DatastoreStatusEntry>,
105}
106
107#[derive(Debug, serde::Serialize)]
108pub struct DatastoreNodeKeySetEntry {
109    pub node_id: Option<u64>,
110    pub group_key_set_id: Option<u16>,
111    pub status_entry: Option<DatastoreStatusEntry>,
112}
113
114#[derive(Debug, serde::Serialize)]
115pub struct DatastoreStatusEntry {
116    pub state: Option<u8>,
117    pub update_timestamp: Option<u64>,
118    pub failure_code: Option<u8>,
119}
120
121// Command encoders
122
123/// Encode AddKeySet command (0x00)
124pub fn encode_add_key_set(group_key_set: u8) -> anyhow::Result<Vec<u8>> {
125    let tlv = tlv::TlvItemEnc {
126        tag: 0,
127        value: tlv::TlvItemValueEnc::StructInvisible(vec![
128        (0, tlv::TlvItemValueEnc::UInt8(group_key_set)).into(),
129        ]),
130    };
131    Ok(tlv.encode()?)
132}
133
134/// Encode UpdateKeySet command (0x01)
135pub fn encode_update_key_set(group_key_set: u8) -> anyhow::Result<Vec<u8>> {
136    let tlv = tlv::TlvItemEnc {
137        tag: 0,
138        value: tlv::TlvItemValueEnc::StructInvisible(vec![
139        (0, tlv::TlvItemValueEnc::UInt8(group_key_set)).into(),
140        ]),
141    };
142    Ok(tlv.encode()?)
143}
144
145/// Encode RemoveKeySet command (0x02)
146pub fn encode_remove_key_set(group_key_set_id: u16) -> anyhow::Result<Vec<u8>> {
147    let tlv = tlv::TlvItemEnc {
148        tag: 0,
149        value: tlv::TlvItemValueEnc::StructInvisible(vec![
150        (0, tlv::TlvItemValueEnc::UInt16(group_key_set_id)).into(),
151        ]),
152    };
153    Ok(tlv.encode()?)
154}
155
156/// Encode AddGroup command (0x03)
157pub fn encode_add_group(group_id: u8, friendly_name: String, group_key_set_id: Option<u16>, group_cat: Option<u16>, group_cat_version: Option<u16>, group_permission: u8) -> anyhow::Result<Vec<u8>> {
158    let tlv = tlv::TlvItemEnc {
159        tag: 0,
160        value: tlv::TlvItemValueEnc::StructInvisible(vec![
161        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
162        (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
163        (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
164        (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
165        (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
166        (5, tlv::TlvItemValueEnc::UInt8(group_permission)).into(),
167        ]),
168    };
169    Ok(tlv.encode()?)
170}
171
172/// Encode UpdateGroup command (0x04)
173pub fn encode_update_group(group_id: u8, friendly_name: Option<String>, group_key_set_id: Option<u16>, group_cat: Option<u16>, group_cat_version: Option<u16>, group_permission: u8) -> anyhow::Result<Vec<u8>> {
174    let tlv = tlv::TlvItemEnc {
175        tag: 0,
176        value: tlv::TlvItemValueEnc::StructInvisible(vec![
177        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
178        (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
179        (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
180        (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
181        (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
182        (5, tlv::TlvItemValueEnc::UInt8(group_permission)).into(),
183        ]),
184    };
185    Ok(tlv.encode()?)
186}
187
188/// Encode RemoveGroup command (0x05)
189pub fn encode_remove_group(group_id: u8) -> anyhow::Result<Vec<u8>> {
190    let tlv = tlv::TlvItemEnc {
191        tag: 0,
192        value: tlv::TlvItemValueEnc::StructInvisible(vec![
193        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
194        ]),
195    };
196    Ok(tlv.encode()?)
197}
198
199/// Encode AddAdmin command (0x06)
200pub fn encode_add_admin(node_id: u64, friendly_name: String, vendor_id: u16, icac: Vec<u8>) -> anyhow::Result<Vec<u8>> {
201    let tlv = tlv::TlvItemEnc {
202        tag: 0,
203        value: tlv::TlvItemValueEnc::StructInvisible(vec![
204        (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
205        (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
206        (3, tlv::TlvItemValueEnc::UInt16(vendor_id)).into(),
207        (4, tlv::TlvItemValueEnc::OctetString(icac)).into(),
208        ]),
209    };
210    Ok(tlv.encode()?)
211}
212
213/// Encode UpdateAdmin command (0x07)
214pub fn encode_update_admin(node_id: Option<u64>, friendly_name: Option<String>, icac: Option<Vec<u8>>) -> anyhow::Result<Vec<u8>> {
215    let tlv = tlv::TlvItemEnc {
216        tag: 0,
217        value: tlv::TlvItemValueEnc::StructInvisible(vec![
218        (0, tlv::TlvItemValueEnc::UInt64(node_id.unwrap_or(0))).into(),
219        (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
220        (2, tlv::TlvItemValueEnc::OctetString(icac.unwrap_or(vec![]))).into(),
221        ]),
222    };
223    Ok(tlv.encode()?)
224}
225
226/// Encode RemoveAdmin command (0x08)
227pub fn encode_remove_admin(node_id: u64) -> anyhow::Result<Vec<u8>> {
228    let tlv = tlv::TlvItemEnc {
229        tag: 0,
230        value: tlv::TlvItemValueEnc::StructInvisible(vec![
231        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
232        ]),
233    };
234    Ok(tlv.encode()?)
235}
236
237/// Encode AddPendingNode command (0x09)
238pub fn encode_add_pending_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
239    let tlv = tlv::TlvItemEnc {
240        tag: 0,
241        value: tlv::TlvItemValueEnc::StructInvisible(vec![
242        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
243        (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
244        ]),
245    };
246    Ok(tlv.encode()?)
247}
248
249/// Encode RefreshNode command (0x0A)
250pub fn encode_refresh_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
251    let tlv = tlv::TlvItemEnc {
252        tag: 0,
253        value: tlv::TlvItemValueEnc::StructInvisible(vec![
254        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
255        ]),
256    };
257    Ok(tlv.encode()?)
258}
259
260/// Encode UpdateNode command (0x0B)
261pub fn encode_update_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
262    let tlv = tlv::TlvItemEnc {
263        tag: 0,
264        value: tlv::TlvItemValueEnc::StructInvisible(vec![
265        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
266        (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
267        ]),
268    };
269    Ok(tlv.encode()?)
270}
271
272/// Encode RemoveNode command (0x0C)
273pub fn encode_remove_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
274    let tlv = tlv::TlvItemEnc {
275        tag: 0,
276        value: tlv::TlvItemValueEnc::StructInvisible(vec![
277        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
278        ]),
279    };
280    Ok(tlv.encode()?)
281}
282
283/// Encode UpdateEndpointForNode command (0x0D)
284pub fn encode_update_endpoint_for_node(endpoint_id: u16, node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
285    let tlv = tlv::TlvItemEnc {
286        tag: 0,
287        value: tlv::TlvItemValueEnc::StructInvisible(vec![
288        (0, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
289        (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
290        (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
291        ]),
292    };
293    Ok(tlv.encode()?)
294}
295
296/// Encode AddGroupIDToEndpointForNode command (0x0E)
297pub fn encode_add_group_id_to_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
298    let tlv = tlv::TlvItemEnc {
299        tag: 0,
300        value: tlv::TlvItemValueEnc::StructInvisible(vec![
301        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
302        (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
303        (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
304        ]),
305    };
306    Ok(tlv.encode()?)
307}
308
309/// Encode RemoveGroupIDFromEndpointForNode command (0x0F)
310pub fn encode_remove_group_id_from_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
311    let tlv = tlv::TlvItemEnc {
312        tag: 0,
313        value: tlv::TlvItemValueEnc::StructInvisible(vec![
314        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
315        (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
316        (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
317        ]),
318    };
319    Ok(tlv.encode()?)
320}
321
322/// Encode AddBindingToEndpointForNode command (0x10)
323pub fn encode_add_binding_to_endpoint_for_node(node_id: u64, endpoint_id: u16, binding: u8) -> anyhow::Result<Vec<u8>> {
324    let tlv = tlv::TlvItemEnc {
325        tag: 0,
326        value: tlv::TlvItemValueEnc::StructInvisible(vec![
327        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
328        (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
329        (2, tlv::TlvItemValueEnc::UInt8(binding)).into(),
330        ]),
331    };
332    Ok(tlv.encode()?)
333}
334
335/// Encode RemoveBindingFromEndpointForNode command (0x11)
336pub fn encode_remove_binding_from_endpoint_for_node(list_id: u16, endpoint_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
337    let tlv = tlv::TlvItemEnc {
338        tag: 0,
339        value: tlv::TlvItemValueEnc::StructInvisible(vec![
340        (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
341        (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
342        (2, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
343        ]),
344    };
345    Ok(tlv.encode()?)
346}
347
348/// Encode AddACLToNode command (0x12)
349pub fn encode_add_acl_to_node(node_id: u64, acl_entry: u8) -> anyhow::Result<Vec<u8>> {
350    let tlv = tlv::TlvItemEnc {
351        tag: 0,
352        value: tlv::TlvItemValueEnc::StructInvisible(vec![
353        (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
354        (1, tlv::TlvItemValueEnc::UInt8(acl_entry)).into(),
355        ]),
356    };
357    Ok(tlv.encode()?)
358}
359
360/// Encode RemoveACLFromNode command (0x13)
361pub fn encode_remove_acl_from_node(list_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
362    let tlv = tlv::TlvItemEnc {
363        tag: 0,
364        value: tlv::TlvItemValueEnc::StructInvisible(vec![
365        (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
366        (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
367        ]),
368    };
369    Ok(tlv.encode()?)
370}
371
372// Attribute decoders
373
374/// Decode AnchorRootCA attribute (0x0000)
375pub fn decode_anchor_root_ca(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
376    if let tlv::TlvItemValue::OctetString(v) = inp {
377        Ok(v.clone())
378    } else {
379        Err(anyhow::anyhow!("Expected OctetString"))
380    }
381}
382
383/// Decode AnchorNodeID attribute (0x0001)
384pub fn decode_anchor_node_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
385    if let tlv::TlvItemValue::Int(v) = inp {
386        Ok(*v)
387    } else {
388        Err(anyhow::anyhow!("Expected Integer"))
389    }
390}
391
392/// Decode AnchorVendorID attribute (0x0002)
393pub fn decode_anchor_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
394    if let tlv::TlvItemValue::Int(v) = inp {
395        Ok(*v as u16)
396    } else {
397        Err(anyhow::anyhow!("Expected Integer"))
398    }
399}
400
401/// Decode FriendlyName attribute (0x0003)
402pub fn decode_friendly_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
403    if let tlv::TlvItemValue::String(v) = inp {
404        Ok(v.clone())
405    } else {
406        Err(anyhow::anyhow!("Expected String"))
407    }
408}
409
410/// Decode GroupKeySetList attribute (0x0004)
411pub fn decode_group_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupKeySet>> {
412    let mut res = Vec::new();
413    if let tlv::TlvItemValue::List(v) = inp {
414        for item in v {
415            res.push(DatastoreGroupKeySet {
416                group_key_set_id: item.get_int(&[0]).map(|v| v as u16),
417                group_key_security_policy: item.get_int(&[1]).map(|v| v as u8),
418                epoch_key0: item.get_octet_string_owned(&[2]),
419                epoch_start_time0: item.get_int(&[3]).map(|v| v as u8),
420                epoch_key1: item.get_octet_string_owned(&[4]),
421                epoch_start_time1: item.get_int(&[5]).map(|v| v as u8),
422                epoch_key2: item.get_octet_string_owned(&[6]),
423                epoch_start_time2: item.get_int(&[7]).map(|v| v as u8),
424                group_key_multicast_policy: item.get_int(&[8]).map(|v| v as u8),
425            });
426        }
427    }
428    Ok(res)
429}
430
431/// Decode GroupList attribute (0x0005)
432pub fn decode_group_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupInformationEntry>> {
433    let mut res = Vec::new();
434    if let tlv::TlvItemValue::List(v) = inp {
435        for item in v {
436            res.push(DatastoreGroupInformationEntry {
437                group_id: item.get_int(&[0]),
438                friendly_name: item.get_string_owned(&[1]),
439                group_key_set_id: item.get_int(&[2]).map(|v| v as u16),
440                group_cat: item.get_int(&[3]).map(|v| v as u16),
441                group_cat_version: item.get_int(&[4]).map(|v| v as u16),
442                group_permission: item.get_int(&[5]).map(|v| v as u8),
443            });
444        }
445    }
446    Ok(res)
447}
448
449/// Decode NodeList attribute (0x0006)
450pub fn decode_node_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeInformationEntry>> {
451    let mut res = Vec::new();
452    if let tlv::TlvItemValue::List(v) = inp {
453        for item in v {
454            res.push(DatastoreNodeInformationEntry {
455                node_id: item.get_int(&[1]),
456                friendly_name: item.get_string_owned(&[2]),
457                commissioning_status_entry: {
458                    if let Some(nested_tlv) = item.get(&[3]) {
459                        if let tlv::TlvItemValue::List(_) = nested_tlv {
460                            let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
461                            Some(DatastoreStatusEntry {
462                state: nested_item.get_int(&[0]).map(|v| v as u8),
463                update_timestamp: nested_item.get_int(&[1]),
464                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
465                            })
466                        } else {
467                            None
468                        }
469                    } else {
470                        None
471                    }
472                },
473            });
474        }
475    }
476    Ok(res)
477}
478
479/// Decode AdminList attribute (0x0007)
480pub fn decode_admin_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreAdministratorInformationEntry>> {
481    let mut res = Vec::new();
482    if let tlv::TlvItemValue::List(v) = inp {
483        for item in v {
484            res.push(DatastoreAdministratorInformationEntry {
485                node_id: item.get_int(&[1]),
486                friendly_name: item.get_string_owned(&[2]),
487                vendor_id: item.get_int(&[3]).map(|v| v as u16),
488                icac: item.get_octet_string_owned(&[4]),
489            });
490        }
491    }
492    Ok(res)
493}
494
495/// Decode Status attribute (0x0008)
496pub fn decode_status(inp: &tlv::TlvItemValue) -> anyhow::Result<DatastoreStatusEntry> {
497    if let tlv::TlvItemValue::List(_fields) = inp {
498        // Struct with fields
499        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
500        Ok(DatastoreStatusEntry {
501                state: item.get_int(&[0]).map(|v| v as u8),
502                update_timestamp: item.get_int(&[1]),
503                failure_code: item.get_int(&[2]).map(|v| v as u8),
504        })
505    } else {
506        Err(anyhow::anyhow!("Expected struct fields"))
507    }
508}
509
510/// Decode EndpointGroupIDList attribute (0x0009)
511pub fn decode_endpoint_group_id_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointGroupIDEntry>> {
512    let mut res = Vec::new();
513    if let tlv::TlvItemValue::List(v) = inp {
514        for item in v {
515            res.push(DatastoreEndpointGroupIDEntry {
516                node_id: item.get_int(&[0]),
517                endpoint_id: item.get_int(&[1]).map(|v| v as u16),
518                group_id: item.get_int(&[2]).map(|v| v as u8),
519                status_entry: {
520                    if let Some(nested_tlv) = item.get(&[3]) {
521                        if let tlv::TlvItemValue::List(_) = nested_tlv {
522                            let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
523                            Some(DatastoreStatusEntry {
524                state: nested_item.get_int(&[0]).map(|v| v as u8),
525                update_timestamp: nested_item.get_int(&[1]),
526                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
527                            })
528                        } else {
529                            None
530                        }
531                    } else {
532                        None
533                    }
534                },
535            });
536        }
537    }
538    Ok(res)
539}
540
541/// Decode EndpointBindingList attribute (0x000A)
542pub fn decode_endpoint_binding_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointBindingEntry>> {
543    let mut res = Vec::new();
544    if let tlv::TlvItemValue::List(v) = inp {
545        for item in v {
546            res.push(DatastoreEndpointBindingEntry {
547                node_id: item.get_int(&[0]),
548                endpoint_id: item.get_int(&[1]).map(|v| v as u16),
549                list_id: item.get_int(&[2]).map(|v| v as u16),
550                binding: {
551                    if let Some(nested_tlv) = item.get(&[3]) {
552                        if let tlv::TlvItemValue::List(_) = nested_tlv {
553                            let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
554                            Some(DatastoreBindingTarget {
555                node: nested_item.get_int(&[1]),
556                group: nested_item.get_int(&[2]).map(|v| v as u8),
557                endpoint: nested_item.get_int(&[3]).map(|v| v as u16),
558                cluster: nested_item.get_int(&[4]).map(|v| v as u32),
559                            })
560                        } else {
561                            None
562                        }
563                    } else {
564                        None
565                    }
566                },
567                status_entry: {
568                    if let Some(nested_tlv) = item.get(&[4]) {
569                        if let tlv::TlvItemValue::List(_) = nested_tlv {
570                            let nested_item = tlv::TlvItem { tag: 4, value: nested_tlv.clone() };
571                            Some(DatastoreStatusEntry {
572                state: nested_item.get_int(&[0]).map(|v| v as u8),
573                update_timestamp: nested_item.get_int(&[1]),
574                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
575                            })
576                        } else {
577                            None
578                        }
579                    } else {
580                        None
581                    }
582                },
583            });
584        }
585    }
586    Ok(res)
587}
588
589/// Decode NodeKeySetList attribute (0x000B)
590pub fn decode_node_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeKeySetEntry>> {
591    let mut res = Vec::new();
592    if let tlv::TlvItemValue::List(v) = inp {
593        for item in v {
594            res.push(DatastoreNodeKeySetEntry {
595                node_id: item.get_int(&[0]),
596                group_key_set_id: item.get_int(&[1]).map(|v| v as u16),
597                status_entry: {
598                    if let Some(nested_tlv) = item.get(&[2]) {
599                        if let tlv::TlvItemValue::List(_) = nested_tlv {
600                            let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
601                            Some(DatastoreStatusEntry {
602                state: nested_item.get_int(&[0]).map(|v| v as u8),
603                update_timestamp: nested_item.get_int(&[1]),
604                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
605                            })
606                        } else {
607                            None
608                        }
609                    } else {
610                        None
611                    }
612                },
613            });
614        }
615    }
616    Ok(res)
617}
618
619/// Decode NodeACLList attribute (0x000C)
620pub fn decode_node_acl_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreACLEntry>> {
621    let mut res = Vec::new();
622    if let tlv::TlvItemValue::List(v) = inp {
623        for item in v {
624            res.push(DatastoreACLEntry {
625                node_id: item.get_int(&[0]),
626                list_id: item.get_int(&[1]).map(|v| v as u16),
627                acl_entry: {
628                    if let Some(nested_tlv) = item.get(&[2]) {
629                        if let tlv::TlvItemValue::List(_) = nested_tlv {
630                            let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
631                            Some(DatastoreAccessControlEntry {
632                privilege: nested_item.get_int(&[1]).map(|v| v as u8),
633                auth_mode: nested_item.get_int(&[2]).map(|v| v as u8),
634                subjects: {
635                    if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[3]) {
636                        let items: Vec<u64> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v) } else { None } }).collect();
637                        Some(items)
638                    } else {
639                        None
640                    }
641                },
642                targets: {
643                    if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[4]) {
644                        let mut items = Vec::new();
645                        for list_item in l {
646                            items.push(DatastoreAccessControlTarget {
647                cluster: list_item.get_int(&[0]).map(|v| v as u32),
648                endpoint: list_item.get_int(&[1]).map(|v| v as u16),
649                device_type: list_item.get_int(&[2]).map(|v| v as u32),
650                            });
651                        }
652                        Some(items)
653                    } else {
654                        None
655                    }
656                },
657                            })
658                        } else {
659                            None
660                        }
661                    } else {
662                        None
663                    }
664                },
665                status_entry: {
666                    if let Some(nested_tlv) = item.get(&[3]) {
667                        if let tlv::TlvItemValue::List(_) = nested_tlv {
668                            let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
669                            Some(DatastoreStatusEntry {
670                state: nested_item.get_int(&[0]).map(|v| v as u8),
671                update_timestamp: nested_item.get_int(&[1]),
672                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
673                            })
674                        } else {
675                            None
676                        }
677                    } else {
678                        None
679                    }
680                },
681            });
682        }
683    }
684    Ok(res)
685}
686
687/// Decode NodeEndpointList attribute (0x000D)
688pub fn decode_node_endpoint_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointEntry>> {
689    let mut res = Vec::new();
690    if let tlv::TlvItemValue::List(v) = inp {
691        for item in v {
692            res.push(DatastoreEndpointEntry {
693                endpoint_id: item.get_int(&[0]).map(|v| v as u16),
694                node_id: item.get_int(&[1]),
695                friendly_name: item.get_string_owned(&[2]),
696                status_entry: {
697                    if let Some(nested_tlv) = item.get(&[3]) {
698                        if let tlv::TlvItemValue::List(_) = nested_tlv {
699                            let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
700                            Some(DatastoreStatusEntry {
701                state: nested_item.get_int(&[0]).map(|v| v as u8),
702                update_timestamp: nested_item.get_int(&[1]),
703                failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
704                            })
705                        } else {
706                            None
707                        }
708                    } else {
709                        None
710                    }
711                },
712            });
713        }
714    }
715    Ok(res)
716}
717
718
719// JSON dispatcher function
720
721/// Decode attribute value and return as JSON string
722/// 
723/// # Parameters
724/// * `cluster_id` - The cluster identifier
725/// * `attribute_id` - The attribute identifier
726/// * `tlv_value` - The TLV value to decode
727/// 
728/// # Returns
729/// JSON string representation of the decoded value or error
730pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
731    // Verify this is the correct cluster
732    if cluster_id != 0x0752 {
733        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0752, got {}\"}}", cluster_id);
734    }
735    
736    match attribute_id {
737        0x0000 => {
738            match decode_anchor_root_ca(tlv_value) {
739                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
740                Err(e) => format!("{{\"error\": \"{}\"}}", e),
741            }
742        }
743        0x0001 => {
744            match decode_anchor_node_id(tlv_value) {
745                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
746                Err(e) => format!("{{\"error\": \"{}\"}}", e),
747            }
748        }
749        0x0002 => {
750            match decode_anchor_vendor_id(tlv_value) {
751                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
752                Err(e) => format!("{{\"error\": \"{}\"}}", e),
753            }
754        }
755        0x0003 => {
756            match decode_friendly_name(tlv_value) {
757                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
758                Err(e) => format!("{{\"error\": \"{}\"}}", e),
759            }
760        }
761        0x0004 => {
762            match decode_group_key_set_list(tlv_value) {
763                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
764                Err(e) => format!("{{\"error\": \"{}\"}}", e),
765            }
766        }
767        0x0005 => {
768            match decode_group_list(tlv_value) {
769                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
770                Err(e) => format!("{{\"error\": \"{}\"}}", e),
771            }
772        }
773        0x0006 => {
774            match decode_node_list(tlv_value) {
775                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
776                Err(e) => format!("{{\"error\": \"{}\"}}", e),
777            }
778        }
779        0x0007 => {
780            match decode_admin_list(tlv_value) {
781                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
782                Err(e) => format!("{{\"error\": \"{}\"}}", e),
783            }
784        }
785        0x0008 => {
786            match decode_status(tlv_value) {
787                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
788                Err(e) => format!("{{\"error\": \"{}\"}}", e),
789            }
790        }
791        0x0009 => {
792            match decode_endpoint_group_id_list(tlv_value) {
793                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
794                Err(e) => format!("{{\"error\": \"{}\"}}", e),
795            }
796        }
797        0x000A => {
798            match decode_endpoint_binding_list(tlv_value) {
799                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
800                Err(e) => format!("{{\"error\": \"{}\"}}", e),
801            }
802        }
803        0x000B => {
804            match decode_node_key_set_list(tlv_value) {
805                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
806                Err(e) => format!("{{\"error\": \"{}\"}}", e),
807            }
808        }
809        0x000C => {
810            match decode_node_acl_list(tlv_value) {
811                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
812                Err(e) => format!("{{\"error\": \"{}\"}}", e),
813            }
814        }
815        0x000D => {
816            match decode_node_endpoint_list(tlv_value) {
817                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
818                Err(e) => format!("{{\"error\": \"{}\"}}", e),
819            }
820        }
821        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
822    }
823}
824
825/// Get list of all attributes supported by this cluster
826/// 
827/// # Returns
828/// Vector of tuples containing (attribute_id, attribute_name)
829pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
830    vec![
831        (0x0000, "AnchorRootCA"),
832        (0x0001, "AnchorNodeID"),
833        (0x0002, "AnchorVendorID"),
834        (0x0003, "FriendlyName"),
835        (0x0004, "GroupKeySetList"),
836        (0x0005, "GroupList"),
837        (0x0006, "NodeList"),
838        (0x0007, "AdminList"),
839        (0x0008, "Status"),
840        (0x0009, "EndpointGroupIDList"),
841        (0x000A, "EndpointBindingList"),
842        (0x000B, "NodeKeySetList"),
843        (0x000C, "NodeACLList"),
844        (0x000D, "NodeEndpointList"),
845    ]
846}
847