Skip to main content

inc_complete/storage/
singleton.rs

1use serde::{Deserialize, ser::SerializeStruct};
2
3use super::{Computation, StorageFor};
4use crate::Cell;
5
6/// Helper to store a simple computation type which has no fields and thus
7/// does not require a map to cache each possible value.
8///
9/// Examples include `struct SourceFile;` or `struct Time;`
10pub struct SingletonStorage<K: Computation> {
11    cell: std::sync::OnceLock<Cell>,
12    key: std::sync::OnceLock<K>,
13    value: std::sync::Mutex<Option<K::Output>>,
14}
15
16impl<K: Computation> Default for SingletonStorage<K> {
17    fn default() -> Self {
18        Self {
19            cell: Default::default(),
20            value: Default::default(),
21            key: Default::default(),
22        }
23    }
24}
25
26impl<K> StorageFor<K> for SingletonStorage<K>
27where
28    K: Computation + Clone,
29    K::Output: Eq + Clone,
30{
31    fn get_cell_for_computation(&self, _: &K) -> Option<Cell> {
32        self.cell.get().copied()
33    }
34
35    fn insert_new_cell(&self, cell: Cell, key: K) {
36        assert!(
37            self.cell.set(cell).is_ok(),
38            "Overwriting previous singleton value - are you using SingleStorage<{}> with a non-singleton type?",
39            std::any::type_name::<K>()
40        );
41        let result = self.key.set(key);
42        result.unwrap_or_else(|_| panic!("insert_new_cell: cell already initialized"));
43    }
44
45    fn try_get_input(&self, cell: Cell) -> Option<K> {
46        if cell == self.cell.get().cloned()? {
47            self.key.get().cloned()
48        } else {
49            None
50        }
51    }
52
53    fn get_input(&self, _: Cell) -> K {
54        self.key.get().cloned().unwrap()
55    }
56
57    fn get_output(&self, _: Cell) -> Option<K::Output> {
58        self.value.lock().unwrap().clone()
59    }
60
61    fn update_output(&self, _: Cell, new_value: K::Output) -> bool {
62        let mut guard = self.value.lock().unwrap();
63        let changed = K::ASSUME_CHANGED || guard.as_ref().is_none_or(|value| *value != new_value);
64        *guard = Some(new_value);
65        changed
66    }
67
68    fn gc(&mut self, used_cells: &std::collections::HashSet<Cell>) {
69        if let Some(this_cell) = self.cell.get() {
70            if !used_cells.contains(this_cell) {
71                if let Ok(val) = self.value.get_mut() {
72                    *val = None;
73                }
74            }
75        }
76    }
77}
78
79impl<K> serde::Serialize for SingletonStorage<K>
80where
81    K: serde::Serialize + Computation,
82    K::Output: serde::Serialize,
83{
84    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85    where
86        S: serde::Serializer,
87    {
88        let mut s = serializer.serialize_struct("SingletonStorage", 3)?;
89        s.serialize_field("cell", &self.cell.get())?;
90        s.serialize_field("key", &self.key.get())?;
91        let guard = self.value.lock().unwrap();
92
93        // When users store unit values in a singleton, this leads to `self.value`
94        // being `Some(())` or `None` which tagless encodings can't differentiate.
95        // So we wrap in a single element tuple to tell them apart.
96        s.serialize_field("value", &guard.as_ref().map(|value| (value,)))?;
97        s.end()
98    }
99}
100
101impl<'de, K> serde::Deserialize<'de> for SingletonStorage<K>
102where
103    K: serde::Deserialize<'de> + Computation,
104    K::Output: serde::Deserialize<'de>,
105{
106    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
107    where
108        D: serde::Deserializer<'de>,
109    {
110        let wrapper: SerializeWrapper<K> = Deserialize::deserialize(deserializer)?;
111        Ok(wrapper.into_storage())
112    }
113}
114
115#[derive(Deserialize)]
116struct SerializeWrapper<K: Computation> {
117    #[serde(default)]
118    cell: Option<Cell>,
119
120    // Serde complains we need a `K: Default` without this, but that shouldn't be necessary.
121    #[serde(default = "none")]
122    key: Option<K>,
123
124    #[serde(default)]
125    #[serde(bound = "K::Output: Deserialize<'de>")]
126    value: Option<(K::Output,)>,
127}
128
129fn none<T>() -> Option<T> {
130    None
131}
132
133impl<K: Computation> SerializeWrapper<K> {
134    fn into_storage(self) -> SingletonStorage<K> {
135        let cell = match self.cell {
136            Some(cell) => std::sync::OnceLock::from(cell),
137            None => std::sync::OnceLock::new(),
138        };
139        let key = match self.key {
140            Some(key) => std::sync::OnceLock::from(key),
141            None => std::sync::OnceLock::new(),
142        };
143        let value = std::sync::Mutex::new(self.value.map(|(value,)| value));
144        SingletonStorage { cell, key, value }
145    }
146}