bluejay_visibility/
cache.rs

1use crate::{DirectiveDefinition, TypeDefinition, Warden};
2use bluejay_core::definition::{prelude::*, SchemaDefinition, TypeDefinitionReference};
3use elsa::FrozenMap;
4
5pub struct Cache<'a, S: SchemaDefinition, W: Warden<SchemaDefinition = S>> {
6    warden: W,
7    inner_schema_definition: &'a S,
8    type_definitions: FrozenMap<&'a str, Box<TypeDefinition<'a, S, W>>>,
9    directive_definitions: FrozenMap<&'a str, Box<DirectiveDefinition<'a, S, W>>>,
10}
11
12impl<'a, S: SchemaDefinition, W: Warden<SchemaDefinition = S>> Cache<'a, S, W> {
13    pub fn new(warden: W, inner_schema_definition: &'a S) -> Self {
14        Self {
15            warden,
16            inner_schema_definition,
17            type_definitions: FrozenMap::new(),
18            directive_definitions: FrozenMap::new(),
19        }
20    }
21
22    pub fn warden(&self) -> &W {
23        &self.warden
24    }
25
26    pub(crate) fn inner_schema_definition(&self) -> &'a S {
27        self.inner_schema_definition
28    }
29
30    pub(crate) fn get_or_create_type_definition(
31        &'a self,
32        type_definition: TypeDefinitionReference<'a, S::TypeDefinition>,
33    ) -> Option<&'a TypeDefinition<'a, S, W>> {
34        match self.type_definitions.get(type_definition.name()) {
35            Some(existing_type_definition) => self
36                .type_definitions_equal(existing_type_definition.inner(), type_definition)
37                .then_some(existing_type_definition),
38            None => TypeDefinition::new(type_definition, self).map(|td| {
39                self.type_definitions
40                    .insert(type_definition.name(), Box::new(td))
41            }),
42        }
43    }
44
45    pub(crate) fn get_type_definition(
46        &'a self,
47        name: &str,
48    ) -> Option<&'a TypeDefinition<'a, S, W>> {
49        self.type_definitions.get(name)
50    }
51
52    pub(crate) fn get_or_create_directive_definition(
53        &'a self,
54        directive_definition: &'a S::DirectiveDefinition,
55    ) -> Option<&'a DirectiveDefinition<'a, S, W>> {
56        self.directive_definitions
57            .get(directive_definition.name())
58            .or_else(|| {
59                DirectiveDefinition::new(directive_definition, self).map(|dd| {
60                    self.directive_definitions
61                        .insert(directive_definition.name(), Box::new(dd))
62                })
63            })
64    }
65
66    pub(crate) fn get_directive_definition(
67        &'a self,
68        name: &str,
69    ) -> Option<&'a DirectiveDefinition<'a, S, W>> {
70        self.directive_definitions.get(name)
71    }
72
73    fn type_definitions_equal(
74        &self,
75        left: TypeDefinitionReference<'a, S::TypeDefinition>,
76        right: TypeDefinitionReference<'a, S::TypeDefinition>,
77    ) -> bool {
78        match (left, right) {
79            (
80                TypeDefinitionReference::BuiltinScalar(left),
81                TypeDefinitionReference::BuiltinScalar(right),
82            ) => left == right,
83            (
84                TypeDefinitionReference::CustomScalar(left),
85                TypeDefinitionReference::CustomScalar(right),
86            ) => self.warden.scalar_type_definitions_equal(left, right),
87            (TypeDefinitionReference::Enum(left), TypeDefinitionReference::Enum(right)) => {
88                self.warden.enum_type_definitions_equal(left, right)
89            }
90            (
91                TypeDefinitionReference::InputObject(left),
92                TypeDefinitionReference::InputObject(right),
93            ) => self.warden.input_object_type_definitions_equal(left, right),
94            (
95                TypeDefinitionReference::Interface(left),
96                TypeDefinitionReference::Interface(right),
97            ) => self.warden.interface_type_definitions_equal(left, right),
98            (TypeDefinitionReference::Object(left), TypeDefinitionReference::Object(right)) => {
99                self.warden.object_type_definitions_equal(left, right)
100            }
101            (TypeDefinitionReference::Union(left), TypeDefinitionReference::Union(right)) => {
102                self.warden.union_type_definitions_equal(left, right)
103            }
104            _ => false,
105        }
106    }
107}