1#![forbid(unsafe_code)]
4
5use crate::error::ImError;
6use crate::event::{EventFilter, EventPath};
7use crate::path::attribute_path_and_append_from_value;
8pub use crate::path::{AttributePath, ReadPath};
9use crate::{
10 expect_message_struct, read_container_members, read_container_value, skip_container,
11 IM_REVISION,
12};
13use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
14
15#[must_use]
25#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn build_read_request_full(
27 attr_paths: &[ReadPath],
28 event_paths: &[EventPath],
29 event_filters: &[EventFilter],
30) -> Vec<u8> {
31 let mut buf = Vec::new();
32 let mut w = TlvWriter::new(&mut buf);
33 w.start_structure(Tag::Anonymous)
34 .expect("infallible: vec writer");
35 if !attr_paths.is_empty() {
36 w.start_array(Tag::Context(0))
37 .expect("infallible: vec writer"); for p in attr_paths {
39 w.start_list(Tag::Anonymous)
40 .expect("infallible: vec writer");
41 if let Some(ep) = p.endpoint {
42 w.put_uint(Tag::Context(2), u64::from(ep))
43 .expect("infallible: vec writer");
44 }
45 if let Some(cl) = p.cluster {
46 w.put_uint(Tag::Context(3), u64::from(cl))
47 .expect("infallible: vec writer");
48 }
49 if let Some(at) = p.attribute {
50 w.put_uint(Tag::Context(4), u64::from(at))
51 .expect("infallible: vec writer");
52 }
53 w.end_container().expect("infallible: vec writer");
54 }
55 w.end_container().expect("infallible: vec writer"); }
57 if !event_paths.is_empty() {
58 w.start_array(Tag::Context(1))
59 .expect("infallible: vec writer"); for p in event_paths {
61 p.write(&mut w).expect("infallible: vec writer");
62 }
63 w.end_container().expect("infallible: vec writer");
64 }
65 if !event_filters.is_empty() {
66 w.start_array(Tag::Context(2))
67 .expect("infallible: vec writer"); for f in event_filters {
69 f.write(&mut w).expect("infallible: vec writer");
70 }
71 w.end_container().expect("infallible: vec writer");
72 }
73 w.put_bool(Tag::Context(3), false)
74 .expect("infallible: vec writer"); w.put_uint(Tag::Context(0xFF), u64::from(IM_REVISION))
76 .expect("infallible: vec writer");
77 w.end_container().expect("infallible: vec writer");
78 buf
79}
80
81#[must_use]
89pub fn build_read_request_paths(paths: &[ReadPath]) -> Vec<u8> {
90 build_read_request_full(paths, &[], &[])
91}
92
93#[must_use]
99pub fn build_read_request(paths: &[AttributePath]) -> Vec<u8> {
100 let read_paths: Vec<ReadPath> = paths.iter().map(|&p| ReadPath::from(p)).collect();
101 build_read_request_paths(&read_paths)
102}
103
104#[derive(Clone, Debug, PartialEq)]
106#[non_exhaustive]
107pub struct ReportData {
108 pub items: Vec<AttributeReportItem>,
115 pub subscription_id: Option<u32>,
119 pub more_chunked_messages: bool,
123 pub suppress_response: bool,
126 pub events: Vec<crate::event::EventReport>,
129 pub statuses: Vec<(AttributePath, crate::status::ImStatus)>,
137}
138
139impl ReportData {
140 #[must_use]
152 pub fn new(
153 items: Vec<AttributeReportItem>,
154 subscription_id: Option<u32>,
155 more_chunked_messages: bool,
156 suppress_response: bool,
157 ) -> Self {
158 Self {
159 items,
160 subscription_id,
161 more_chunked_messages,
162 suppress_response,
163 events: Vec::new(),
164 statuses: Vec::new(),
165 }
166 }
167
168 #[must_use]
171 pub fn events(&self) -> &[crate::event::EventReport] {
172 &self.events
173 }
174
175 pub fn attributes(&self) -> impl Iterator<Item = (&AttributePath, &Value)> {
188 self.items
189 .iter()
190 .filter(|it| it.op == ReportOp::Replace)
191 .map(|it| (&it.path, &it.value))
192 }
193}
194
195#[derive(Clone, Debug, PartialEq)]
198#[non_exhaustive]
199pub struct AttributeReportItem {
200 pub path: AttributePath,
202 pub op: ReportOp,
204 pub value: Value,
206 pub data_version: Option<u32>,
208}
209
210impl AttributeReportItem {
211 #[must_use]
218 pub fn new(path: AttributePath, op: ReportOp, value: Value, data_version: Option<u32>) -> Self {
219 Self {
220 path,
221 op,
222 value,
223 data_version,
224 }
225 }
226}
227
228#[derive(Clone, Copy, Debug, PartialEq, Eq)]
230#[non_exhaustive]
231pub enum ReportOp {
232 Replace,
234 Append,
236}
237
238pub fn parse_report_data(bytes: &[u8]) -> Result<ReportData, ImError> {
251 let mut r = TlvReader::new(bytes);
252 expect_message_struct(&mut r)?;
253
254 let mut items: Vec<AttributeReportItem> = Vec::new();
255 let mut statuses: Vec<(AttributePath, crate::status::ImStatus)> = Vec::new();
256 let mut events: Vec<crate::event::EventReport> = Vec::new();
257 let mut subscription_id: Option<u32> = None;
258 let mut more_chunked_messages = false;
259 let mut suppress_response = false;
260
261 loop {
265 match r.next()? {
266 None | Some(Element::ContainerEnd) => break,
267 Some(Element::Scalar {
269 tag: Tag::Context(0),
270 value: Value::Uint(n),
271 }) => {
272 subscription_id = Some(u32::try_from(n).map_err(|_| {
273 ImError::UnexpectedValue("ReportData.subscriptionId exceeds u32")
274 })?);
275 }
276 Some(Element::ContainerStart {
278 tag: Tag::Context(1),
279 kind: ContainerKind::Array,
280 }) => parse_attribute_reports(&mut r, &mut items, &mut statuses)?,
281 Some(Element::Scalar {
283 tag: Tag::Context(3),
284 value: Value::Bool(b),
285 }) => more_chunked_messages = b,
286 Some(Element::Scalar {
288 tag: Tag::Context(4),
289 value: Value::Bool(b),
290 }) => suppress_response = b,
291 Some(Element::ContainerStart {
293 tag: Tag::Context(2),
294 kind: ContainerKind::Array,
295 }) => crate::event::parse_event_reports(&mut r, &mut events)?,
296 Some(Element::ContainerStart { .. }) => skip_container(&mut r)?,
298 Some(_) => {}
299 }
300 }
301
302 Ok(ReportData {
303 items,
304 subscription_id,
305 more_chunked_messages,
306 suppress_response,
307 events,
308 statuses,
309 })
310}
311
312enum ReportIb {
315 Data(AttributeReportItem),
316 Status(AttributePath, crate::status::ImStatus),
317 Empty,
318}
319
320fn parse_attribute_reports(
325 r: &mut TlvReader<'_>,
326 items: &mut Vec<AttributeReportItem>,
327 statuses: &mut Vec<(AttributePath, crate::status::ImStatus)>,
328) -> Result<(), ImError> {
329 loop {
330 match r.next()? {
331 None => return Err(ImError::Codec(matter_codec::Error::UnclosedContainer)),
332 Some(Element::ContainerEnd) => return Ok(()), Some(Element::ContainerStart {
334 kind: ContainerKind::Structure,
335 ..
336 }) => match parse_attribute_report_ib(r)? {
337 ReportIb::Data(item) => items.push(item),
338 ReportIb::Status(path, status) => statuses.push((path, status)),
339 ReportIb::Empty => {}
340 },
341 Some(Element::ContainerStart { .. }) => skip_container(r)?,
342 Some(_) => {}
343 }
344 }
345}
346
347fn parse_attribute_report_ib(r: &mut TlvReader<'_>) -> Result<ReportIb, ImError> {
350 let mut path = None;
351 let mut value = None;
352 let mut data_version = None;
353 let mut append = false;
354 let mut status: Option<(AttributePath, crate::status::ImStatus)> = None;
355 loop {
356 match r.next()? {
357 None => return Err(ImError::Codec(matter_codec::Error::UnclosedContainer)),
358 Some(Element::ContainerEnd) => break,
359 Some(Element::ContainerStart {
360 tag: Tag::Context(1),
361 kind: ContainerKind::Structure,
362 }) => {
363 parse_attribute_data(r, &mut path, &mut value, &mut data_version, &mut append)?;
365 }
366 Some(Element::ContainerStart {
370 tag: Tag::Context(0),
371 kind: ContainerKind::Structure,
372 }) => {
373 status = Some(crate::write::parse_attribute_status_ib(r)?);
374 }
375 Some(Element::ContainerStart { .. }) => skip_container(r)?,
377 Some(_) => {}
378 }
379 }
380 if let Some((p, s)) = status {
381 return Ok(ReportIb::Status(p, s));
382 }
383 match (path, value) {
384 (Some(p), Some(v)) => Ok(ReportIb::Data(AttributeReportItem {
385 path: p,
386 op: if append {
387 ReportOp::Append
388 } else {
389 ReportOp::Replace
390 },
391 value: v,
392 data_version,
393 })),
394 (None, None) => Ok(ReportIb::Empty), (Some(_), None) => Err(ImError::MissingField("AttributeData.Data")),
396 (None, Some(_)) => Err(ImError::MissingField("AttributeData.Path")),
397 }
398}
399
400fn parse_attribute_data(
409 r: &mut TlvReader<'_>,
410 path: &mut Option<AttributePath>,
411 value: &mut Option<Value>,
412 data_version: &mut Option<u32>,
413 append: &mut bool,
414) -> Result<(), ImError> {
415 loop {
416 match r.next()? {
417 None => return Err(ImError::Codec(matter_codec::Error::UnclosedContainer)),
418 Some(Element::ContainerEnd) => return Ok(()),
419 Some(Element::Scalar {
420 tag: Tag::Context(0),
421 value: Value::Uint(n),
422 }) => {
423 *data_version = Some(u32::try_from(n).map_err(|_| {
424 ImError::UnexpectedValue("AttributeData.DataVersion exceeds u32")
425 })?);
426 }
427 Some(Element::ContainerStart {
428 tag: Tag::Context(1),
429 kind: ContainerKind::List,
430 }) => {
431 let members = read_container_members(r)?;
432 let (p, is_append) = attribute_path_and_append_from_value(&members)?;
433 *path = Some(p);
434 *append = is_append;
435 }
436 Some(Element::Scalar {
437 tag: Tag::Context(2),
438 value: v,
439 }) => *value = Some(v),
440 Some(Element::ContainerStart {
441 tag: Tag::Context(2),
442 kind,
443 }) => *value = Some(read_container_value(r, kind)?),
444 Some(Element::ContainerStart { .. }) => skip_container(r)?,
445 Some(_) => {}
446 }
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 #![allow(clippy::unwrap_used, clippy::expect_used)]
453 use super::*;
454 use matter_codec::{ContainerKind, Element, Tag, TlvReader, Value};
455
456 #[test]
457 fn read_request_has_attribute_requests_array() {
458 let bytes = build_read_request(&[AttributePath {
459 endpoint: 0,
460 cluster: 0x0031,
461 attribute: 0xFFFC, }]);
463 let mut r = TlvReader::new(&bytes);
464 assert!(matches!(
465 r.next().unwrap(),
466 Some(Element::ContainerStart {
467 tag: Tag::Anonymous,
468 kind: ContainerKind::Structure
469 })
470 ));
471 assert!(matches!(
472 r.next().unwrap(),
473 Some(Element::ContainerStart {
474 tag: Tag::Context(0),
475 kind: ContainerKind::Array
476 })
477 ));
478 assert!(matches!(
479 r.next().unwrap(),
480 Some(Element::ContainerStart {
481 tag: Tag::Anonymous,
482 kind: ContainerKind::List
483 })
484 ));
485 assert!(matches!(
486 r.next().unwrap(),
487 Some(Element::Scalar {
488 tag: Tag::Context(2),
489 value: Value::Uint(0)
490 })
491 ));
492 assert!(matches!(
493 r.next().unwrap(),
494 Some(Element::Scalar {
495 tag: Tag::Context(3),
496 value: Value::Uint(0x0031)
497 })
498 ));
499 assert!(matches!(
500 r.next().unwrap(),
501 Some(Element::Scalar {
502 tag: Tag::Context(4),
503 value: Value::Uint(0xFFFC)
504 })
505 ));
506 }
507
508 #[test]
509 fn parses_single_attribute_value() {
510 use matter_codec::{Tag, TlvWriter};
511 let mut buf = Vec::new();
512 let mut w = TlvWriter::new(&mut buf);
513 w.start_structure(Tag::Anonymous).unwrap();
514 w.start_array(Tag::Context(1)).unwrap(); {
516 w.start_structure(Tag::Anonymous).unwrap(); w.start_structure(Tag::Context(1)).unwrap(); w.start_list(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(2), 0).unwrap();
520 w.put_uint(Tag::Context(3), 0x0031).unwrap();
521 w.put_uint(Tag::Context(4), 0xFFFC).unwrap();
522 w.end_container().unwrap();
523 w.put_uint(Tag::Context(2), 0x0001).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); }
527 w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
529 w.end_container().unwrap();
530
531 let report = parse_report_data(&buf).unwrap();
532 let attrs: Vec<_> = report.attributes().collect();
533 assert_eq!(attrs.len(), 1);
534 let (path, value) = attrs[0];
535 assert_eq!(path.endpoint, 0);
536 assert_eq!(path.cluster, 0x0031);
537 assert_eq!(path.attribute, 0xFFFC);
538 assert_eq!(*value, matter_codec::Value::Uint(0x0001));
539 }
540
541 #[test]
542 fn attribute_status_report_is_surfaced() {
543 use matter_codec::{Tag, TlvWriter};
547 let mut buf = Vec::new();
548 let mut w = TlvWriter::new(&mut buf);
549 w.start_structure(Tag::Anonymous).unwrap();
550 w.start_array(Tag::Context(1)).unwrap(); w.start_structure(Tag::Anonymous).unwrap(); w.start_structure(Tag::Context(0)).unwrap(); w.start_list(Tag::Context(0)).unwrap(); w.put_uint(Tag::Context(2), 1).unwrap(); w.put_uint(Tag::Context(3), 0x0006).unwrap(); w.put_uint(Tag::Context(4), 0x4242).unwrap(); w.end_container().unwrap(); w.start_structure(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(0), 0x86).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
565 w.end_container().unwrap();
566
567 let report = parse_report_data(&buf).unwrap();
568 assert_eq!(report.attributes().count(), 0, "no data items");
569 assert_eq!(report.statuses.len(), 1, "the status IB must be surfaced");
570 let (path, status) = &report.statuses[0];
571 assert_eq!(path.endpoint, 1);
572 assert_eq!(path.cluster, 0x0006);
573 assert_eq!(path.attribute, 0x4242);
574 assert_eq!(*status, crate::status::ImStatus::Failure(0x86));
575 }
576
577 #[test]
578 fn multi_attribute_report_accumulates_all_entries() {
579 use matter_codec::{Tag, TlvWriter};
580 let mut buf = Vec::new();
581 let mut w = TlvWriter::new(&mut buf);
582 w.start_structure(Tag::Anonymous).unwrap();
583 w.start_array(Tag::Context(1)).unwrap(); w.start_structure(Tag::Anonymous).unwrap();
587 w.start_structure(Tag::Context(1)).unwrap(); w.start_list(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(2), 0).unwrap();
590 w.put_uint(Tag::Context(3), 0x0028).unwrap();
591 w.put_uint(Tag::Context(4), 0x0000).unwrap();
592 w.end_container().unwrap();
593 w.put_uint(Tag::Context(2), 42).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.start_structure(Tag::Anonymous).unwrap();
599 w.start_structure(Tag::Context(1)).unwrap(); w.start_list(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(2), 1).unwrap();
602 w.put_uint(Tag::Context(3), 0x0006).unwrap();
603 w.put_uint(Tag::Context(4), 0x0000).unwrap();
604 w.end_container().unwrap();
605 w.put_uint(Tag::Context(2), 1).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
611 w.end_container().unwrap();
612
613 let report = parse_report_data(&buf).unwrap();
614 let attrs: Vec<_> = report.attributes().collect();
615 assert_eq!(attrs.len(), 2);
616
617 let (path0, val0) = attrs[0];
618 assert_eq!(path0.endpoint, 0);
619 assert_eq!(path0.cluster, 0x0028);
620 assert_eq!(path0.attribute, 0x0000);
621 assert_eq!(*val0, matter_codec::Value::Uint(42));
622
623 let (path1, val1) = attrs[1];
624 assert_eq!(path1.endpoint, 1);
625 assert_eq!(path1.cluster, 0x0006);
626 assert_eq!(path1.attribute, 0x0000);
627 assert_eq!(*val1, matter_codec::Value::Uint(1));
628 }
629
630 #[test]
631 fn out_of_range_endpoint_yields_unexpected_value() {
632 use crate::error::ImError;
633 use matter_codec::{Tag, TlvWriter};
634 let mut buf = Vec::new();
635 let mut w = TlvWriter::new(&mut buf);
636 w.start_structure(Tag::Anonymous).unwrap();
637 w.start_array(Tag::Context(1)).unwrap(); w.start_structure(Tag::Anonymous).unwrap(); w.start_structure(Tag::Context(1)).unwrap(); w.start_list(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(2), 0x0001_0000).unwrap(); w.put_uint(Tag::Context(3), 0x0031).unwrap();
643 w.put_uint(Tag::Context(4), 0xFFFC).unwrap();
644 w.end_container().unwrap();
645 w.put_uint(Tag::Context(2), 0x0001).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
650 w.end_container().unwrap();
651
652 let result = parse_report_data(&buf);
653 assert!(
654 matches!(result, Err(ImError::UnexpectedValue(_))),
655 "expected UnexpectedValue, got {result:?}"
656 );
657 }
658
659 #[test]
660 fn parses_more_chunked_and_suppress_response_flags() {
661 use matter_codec::{Tag, TlvWriter};
662 let mut buf = Vec::new();
664 let mut w = TlvWriter::new(&mut buf);
665 w.start_structure(Tag::Anonymous).unwrap();
666 w.start_array(Tag::Context(1)).unwrap(); w.end_container().unwrap();
668 w.put_bool(Tag::Context(3), true).unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
670 w.end_container().unwrap();
671
672 let report = parse_report_data(&buf).unwrap();
673 assert!(
674 report.more_chunked_messages,
675 "tag 3 must be read after the array"
676 );
677 assert!(!report.suppress_response);
678 }
679
680 #[test]
681 fn parses_suppress_response_after_array() {
682 use matter_codec::{Tag, TlvWriter};
683 let mut buf = Vec::new();
684 let mut w = TlvWriter::new(&mut buf);
685 w.start_structure(Tag::Anonymous).unwrap();
686 w.start_array(Tag::Context(1)).unwrap();
687 w.end_container().unwrap();
688 w.put_bool(Tag::Context(4), true).unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
690 w.end_container().unwrap();
691
692 let report = parse_report_data(&buf).unwrap();
693 assert!(report.suppress_response);
694 assert!(!report.more_chunked_messages);
695 }
696
697 #[test]
698 fn captures_data_version_and_append_op() {
699 use matter_codec::{Tag, TlvWriter};
700 let mut buf = Vec::new();
701 let mut w = TlvWriter::new(&mut buf);
702 w.start_structure(Tag::Anonymous).unwrap();
703 w.start_array(Tag::Context(1)).unwrap(); w.start_structure(Tag::Anonymous).unwrap(); w.start_structure(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(0), 7).unwrap(); w.start_list(Tag::Context(1)).unwrap(); w.put_uint(Tag::Context(2), 0).unwrap();
709 w.put_uint(Tag::Context(3), 0x1d).unwrap();
710 w.put_uint(Tag::Context(4), 0x0003).unwrap();
711 w.put_null(Tag::Context(5)).unwrap(); w.end_container().unwrap();
713 w.put_uint(Tag::Context(2), 42).unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
718 w.end_container().unwrap();
719
720 let report = parse_report_data(&buf).unwrap();
721 assert_eq!(report.items.len(), 1);
722 let it = &report.items[0];
723 assert_eq!(it.op, ReportOp::Append);
724 assert_eq!(it.data_version, Some(7));
725 assert_eq!(it.value, Value::Uint(42));
726 assert_eq!(report.attributes().count(), 0);
728 }
729
730 #[test]
734 fn attributes_view_matches_items_filtered_to_replace() {
735 use matter_codec::{Tag, TlvWriter};
736 let mut buf = Vec::new();
737 let mut w = TlvWriter::new(&mut buf);
738 w.start_structure(Tag::Anonymous).unwrap();
739 w.start_array(Tag::Context(1)).unwrap(); w.start_structure(Tag::Anonymous).unwrap();
743 w.start_structure(Tag::Context(1)).unwrap();
744 w.start_list(Tag::Context(1)).unwrap();
745 w.put_uint(Tag::Context(2), 0).unwrap();
746 w.put_uint(Tag::Context(3), 0x0028).unwrap();
747 w.put_uint(Tag::Context(4), 0x0000).unwrap();
748 w.end_container().unwrap();
749 w.put_uint(Tag::Context(2), 42).unwrap();
750 w.end_container().unwrap();
751 w.end_container().unwrap();
752
753 w.start_structure(Tag::Anonymous).unwrap();
755 w.start_structure(Tag::Context(1)).unwrap();
756 w.start_list(Tag::Context(1)).unwrap();
757 w.put_uint(Tag::Context(2), 0).unwrap();
758 w.put_uint(Tag::Context(3), 0x001d).unwrap();
759 w.put_uint(Tag::Context(4), 0x0003).unwrap();
760 w.put_null(Tag::Context(5)).unwrap(); w.end_container().unwrap();
762 w.put_uint(Tag::Context(2), 7).unwrap();
763 w.end_container().unwrap();
764 w.end_container().unwrap();
765
766 w.start_structure(Tag::Anonymous).unwrap();
768 w.start_structure(Tag::Context(1)).unwrap();
769 w.start_list(Tag::Context(1)).unwrap();
770 w.put_uint(Tag::Context(2), 1).unwrap();
771 w.put_uint(Tag::Context(3), 0x0006).unwrap();
772 w.put_uint(Tag::Context(4), 0x0000).unwrap();
773 w.end_container().unwrap();
774 w.put_bool(Tag::Context(2), true).unwrap();
775 w.end_container().unwrap();
776 w.end_container().unwrap();
777
778 w.end_container().unwrap(); w.put_uint(Tag::Context(0xFF), 11).unwrap();
780 w.end_container().unwrap();
781
782 let report = parse_report_data(&buf).unwrap();
783
784 let expected: Vec<(&AttributePath, &Value)> = report
786 .items
787 .iter()
788 .filter(|it| it.op == ReportOp::Replace)
789 .map(|it| (&it.path, &it.value))
790 .collect();
791 let got: Vec<(&AttributePath, &Value)> = report.attributes().collect();
792 assert_eq!(got, expected);
793
794 assert_eq!(got.len(), 2);
796 assert_eq!(got[0].1, &Value::Uint(42));
797 assert_eq!(got[1].1, &Value::Bool(true));
798 }
799}