Skip to main content

pedant_graph/
limits.rs

1//! The configured ceilings a graph build refuses at, and the collections they
2//! address.
3
4use std::fmt;
5
6use serde::{Serialize, Serializer};
7
8/// Which graph collection a ceiling addresses.
9#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub enum GraphCollection {
11    /// The node slice.
12    Node,
13    /// The reference-record slice.
14    Reference,
15    /// The edge slice.
16    Edge,
17}
18
19impl GraphCollection {
20    /// The lower-snake-case token this collection is named by.
21    fn token(self) -> &'static str {
22        match self {
23            Self::Node => "node",
24            Self::Reference => "reference",
25            Self::Edge => "edge",
26        }
27    }
28}
29
30/// One spelling for one collection: a refusal names it exactly as the wire
31/// does, rather than in the `Debug` form of the same value.
32impl fmt::Display for GraphCollection {
33    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
34        formatter.write_str(self.token())
35    }
36}
37
38/// The wire form is that same token, so the serialized spelling and the spelling
39/// a refusal prints cannot drift apart.
40impl Serialize for GraphCollection {
41    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
42        serializer.serialize_str(self.token())
43    }
44}
45
46/// How many nodes, reference records, and edges one build may produce.
47///
48/// The default is the fixed-width identity ceiling, so the configured limit and
49/// the representable ceiling are enforced by one check rather than by two rules
50/// that can disagree. Lowering a field exercises exactly the production
51/// insertion path an ordinary build uses.
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub struct GraphLimits {
54    max_nodes: u32,
55    max_references: u32,
56    max_edges: u32,
57}
58
59impl Default for GraphLimits {
60    fn default() -> Self {
61        Self {
62            max_nodes: u32::MAX,
63            max_references: u32::MAX,
64            max_edges: u32::MAX,
65        }
66    }
67}
68
69impl GraphLimits {
70    /// Ceilings for the three bounded collections.
71    pub fn new(max_nodes: u32, max_references: u32, max_edges: u32) -> Self {
72        Self {
73            max_nodes,
74            max_references,
75            max_edges,
76        }
77    }
78
79    /// The configured node ceiling.
80    pub fn max_nodes(&self) -> u32 {
81        self.max_nodes
82    }
83
84    /// The configured reference-record ceiling.
85    pub fn max_references(&self) -> u32 {
86        self.max_references
87    }
88
89    /// The configured edge ceiling.
90    pub fn max_edges(&self) -> u32 {
91        self.max_edges
92    }
93
94    /// The ceiling one collection is bounded by.
95    pub(crate) fn ceiling(&self, collection: GraphCollection) -> u32 {
96        match collection {
97            GraphCollection::Node => self.max_nodes,
98            GraphCollection::Reference => self.max_references,
99            GraphCollection::Edge => self.max_edges,
100        }
101    }
102}