Skip to main content

ts_nodecapability/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4extern crate alloc;
5
6use alloc::{collections::BTreeMap, vec::Vec};
7
8/// A map of node capabilities to their optional values. It is valid for a capability to have
9/// `None` as a value; such capabilities can be tested for by using the
10/// [`Map::contains_key`] method.
11///
12/// See [`NodeCap`] for more information on keys.
13pub type Map<'a> = BTreeMap<NodeCap<'a>, Values<'a>>;
14
15/// Represents a capability granted to a node.
16///
17/// All capabilities must be a URL like `https://tailscale.com/cap/file-sharing`, or a
18/// well-known capability name like `funnel`. The latter is only allowed for
19/// Tailscale-defined capabilities.
20///
21/// Unlike `PeerCapability` (`ts_peercap`), [`NodeCap`] is not in context of a peer
22/// and is granted to the node itself. These are also referred to as "Node Attributes" in
23/// the ACL policy file.
24pub type NodeCap<'a> = &'a str;
25
26// TODO(npry): NodeCapability -> enum covering special caps w/ catchall, associated consts
27//              for well-known URL caps
28
29cfg_if::cfg_if! {
30    if #[cfg(feature = "serde")] {
31        /// The type of the entry in a [`Values`].
32        ///
33        /// Defined as a type alias to allow switching based on serde support.
34        pub type Value<'a> = &'a serde_json::value::RawValue;
35    } else {
36        /// The type of the entry in a [`Values`].
37        ///
38        /// Defined as a type alias to allow switching based on serde support.
39        pub type Value<'a> = &'a str;
40    }
41}
42
43/// The types of values that can be associated with a single [`NodeCap`] in a
44/// [`Map`].
45#[derive(Clone, Debug)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub struct Values<'a>(
48    #[cfg_attr(
49        feature = "serde",
50        serde(borrow, deserialize_with = "deserialize_nodecap")
51    )]
52    pub Vec<Value<'a>>,
53);
54
55#[cfg(feature = "serde")]
56fn deserialize_nodecap<'a, 'de, D>(
57    deserializer: D,
58) -> Result<Vec<&'a serde_json::value::RawValue>, D::Error>
59where
60    'de: 'a,
61    D: serde::Deserializer<'de>,
62{
63    use serde::Deserialize;
64
65    let val = <Option<Vec<&'a serde_json::value::RawValue>>>::deserialize(deserializer)?
66        .unwrap_or_else(Vec::new);
67
68    Ok(val)
69}