Skip to main content

vantage_vista/capabilities/
set.rs

1//! [`VistaCapabilities`]: the set of capabilities a shell advertises.
2
3use std::fmt;
4
5use serde::de::{Deserializer, MapAccess, Visitor};
6use serde::ser::{SerializeMap, Serializer};
7use serde::{Deserialize, Serialize};
8
9use super::{ALL, Capability};
10
11/// The set of capabilities a shell advertises.
12///
13/// Serializes as a map from every capability's name to whether the set has
14/// it, so a reader (rhai, MCP) sees the full vocabulary. Deserializing
15/// rejects a name it doesn't know, so a typo or a retired name fails loudly
16/// instead of leaving the capability off.
17#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
18pub struct VistaCapabilities {
19    bits: u16,
20}
21
22impl VistaCapabilities {
23    /// The empty set.
24    pub fn new() -> Self {
25        Self::default()
26    }
27
28    /// This set plus `capability`.
29    pub fn with(mut self, capability: Capability) -> Self {
30        self.bits |= capability.bit();
31        self
32    }
33
34    /// This set without `capability`.
35    pub fn without(mut self, capability: Capability) -> Self {
36        self.bits &= !capability.bit();
37        self
38    }
39
40    pub fn has(&self, capability: Capability) -> bool {
41        self.bits & capability.bit() != 0
42    }
43
44    /// The capabilities in the set, in [`Capability::iter`] order.
45    pub fn iter(&self) -> impl Iterator<Item = Capability> + '_ {
46        Capability::iter().filter(|c| self.has(*c))
47    }
48}
49
50impl FromIterator<Capability> for VistaCapabilities {
51    fn from_iter<I: IntoIterator<Item = Capability>>(iter: I) -> Self {
52        iter.into_iter().fold(Self::new(), Self::with)
53    }
54}
55
56impl fmt::Debug for VistaCapabilities {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_set().entries(self.iter()).finish()
59    }
60}
61
62impl Serialize for VistaCapabilities {
63    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
64        let mut map = serializer.serialize_map(Some(ALL.len()))?;
65        for capability in Capability::iter() {
66            map.serialize_entry(capability.as_str(), &self.has(capability))?;
67        }
68        map.end()
69    }
70}
71
72impl<'de> Deserialize<'de> for VistaCapabilities {
73    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
74        struct SetVisitor;
75        impl<'de> Visitor<'de> for SetVisitor {
76            type Value = VistaCapabilities;
77            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
78                f.write_str("a map from capability name to bool")
79            }
80            fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
81                let mut set = VistaCapabilities::new();
82                while let Some((capability, on)) = map.next_entry::<Capability, bool>()? {
83                    if on {
84                        set = set.with(capability);
85                    }
86                }
87                Ok(set)
88            }
89        }
90        deserializer.deserialize_map(SetVisitor)
91    }
92}