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}