sppparse/
sparse_ref_raw_inline.rs

1use super::*;
2
3/// ## An owned dynamic ref
4///
5/// [SparseRefRawInline](SparseRefRawInline) will render dynamically the pointed value.
6///
7/// The mains differences with the other pointers is that [SparseRefRawInline](SparseRefRawInline) will
8/// not render nested pointer. It's a simple, single depth, pointer. It's also not a selector.
9/// The type pointed _MUST_ be a string, a valid pointer and the pointed value must match the `S` type.
10///
11/// It uses a [SparseState](crate::SparseState) to render itself in order to limit the IO calls
12/// at a minimum. It will deserialize into the desired type.
13///
14/// If the [SparseStateFile](crate::SparseStateFile)
15/// used to render the object changes, [SparseRefRawInline](SparseRefRawInline)
16/// will deserialize it again in order to always be up to date.
17#[derive(Debug, Clone, Deserialize, Serialize, Getters, PartialEq)]
18#[serde(transparent)]
19pub struct SparseRefRawInline<S> {
20    /// The value deserialized value, if any
21    #[serde(skip)]
22    #[getset(get = "pub")]
23    #[serde(default = "SparsePointedValue::<S>::default_boxed")]
24    val: Box<SparsePointedValue<S>>,
25    #[serde(rename = "$ref")]
26    #[getset(get = "pub")]
27    raw_pointer: String,
28    /// Metadata about the pointer
29    #[serde(skip)]
30    #[getset(get = "pub")]
31    utils: SparseMetadata,
32}
33
34impl<S> SparsableTrait for SparseRefRawInline<S>
35where
36    S: DeserializeOwned + Serialize + SparsableTrait,
37{
38    fn sparse_init(
39        &mut self,
40        state: &mut SparseState,
41        metadata: &SparseMetadata,
42        depth: u32,
43    ) -> Result<(), SparseError> {
44        self.check_depth(depth)?;
45        match *self.val {
46            SparsePointedValue::Null => self.self_reset(state, metadata, depth)?,
47            _ => {
48                if let Some(SparseError::OutdatedPointer) = self.check_version(state).err() {
49                    self.self_reset(state, metadata, depth)?
50                }
51            }
52        }
53        self.val.sparse_init(state, metadata, depth + 1)
54    }
55
56    fn sparse_updt<'a>(
57        &mut self,
58        state: &mut SparseState,
59        metadata: &SparseMetadata,
60        depth: u32,
61    ) -> Result<(), SparseError> {
62        self.check_depth(depth)?;
63        let vcheck = self.check_version(state);
64        match vcheck {
65            Ok(()) => (),
66            Err(SparseError::OutdatedPointer) => {
67                self.self_reset(state, metadata, depth)?;
68                self.val.sparse_init(state, metadata, depth + 1)?
69            }
70            Err(_) => return vcheck,
71        }
72        self.val.sparse_updt(state, metadata, depth + 1)
73    }
74}
75
76impl<S> SparsePointer<S> for SparseRefRawInline<S>
77where
78    S: DeserializeOwned + Serialize + SparsableTrait,
79{
80    fn check_version<'a>(&'a self, state: &'a SparseState) -> Result<(), SparseError> {
81        let res =
82            state.get_state_file(self.utils().pfile_path())?.version() == self.utils().version();
83        if !res {
84            Err(SparseError::OutdatedPointer)
85        } else {
86            Ok(())
87        }
88    }
89
90    fn get(&self) -> Result<SparseValue<'_, S>, SparseError> {
91        self.val.get(Some(&self.utils))
92    }
93
94    fn get_mut(
95        &mut self,
96        state_cell: Rc<RefCell<SparseState>>,
97    ) -> Result<SparseValueMut<'_, S>, SparseError> {
98        {
99            let state = state_cell
100                .try_borrow()
101                .map_err(|_e| SparseError::StateAlreadyBorrowed)?;
102            self.check_version(&state)?;
103        }
104        self.val.get_mut(state_cell, Some(&self.utils))
105    }
106
107    fn self_reset(
108        &mut self,
109        state: &mut SparseState,
110        metadata: &SparseMetadata,
111        depth: u32,
112    ) -> Result<(), SparseError> {
113        self.check_depth(depth)?;
114        self.utils = SparseMetadata::new(self.raw_pointer().clone(), metadata.pfile_path().clone());
115        self._self_reset(state, metadata, depth)
116    }
117}
118
119impl<S> SparseRefRawInline<S>
120where
121    S: DeserializeOwned + Serialize + SparsableTrait,
122{
123    /// Fetch a reference to the state file from the [SparseState](SparseState)
124    fn get_state_file_init<'a>(
125        state: &'a mut SparseState,
126        utils: &SparseMetadata,
127    ) -> Result<&'a SparseStateFile, SparseError> {
128        let pfile_path: &PathBuf = utils.pfile_path();
129        state.add_file(pfile_path.clone())?;
130        state.get_state_file(pfile_path)
131    }
132
133    /// Initialize the inner value using the [SparseState](SparseState).
134    fn init_val(
135        state: &mut SparseState,
136        utils: &mut SparseMetadata,
137        depth: u32,
138    ) -> Result<SparsePointedValue<S>, SparseError> {
139        let state_file = SparseRefRawInline::<S>::get_state_file_init(state, utils)?;
140
141        let mut val: SparsePointedValue<S> = serde_json::from_value(
142            state_file
143                .val()
144                .pointer(utils.pointer())
145                .ok_or_else(|| SparseError::UnkownPath(utils.pointer().clone()))?
146                .clone(),
147        )?;
148        val = match val {
149            SparsePointedValue::RefRaw(mut x) => {
150                *x.base_path_mut() = utils.pfile_path().clone();
151                SparsePointedValue::RefRaw(x)
152            }
153            _ => val,
154        };
155        *utils.version_mut() = state_file.version();
156        val.sparse_init(state, utils, depth + 1)?;
157        Ok(val)
158    }
159
160    /// Reset the inner value in case of change, in order to resolve the pointer again
161    fn _self_reset(
162        &mut self,
163        state: &mut SparseState,
164        _metadata: &SparseMetadata,
165        depth: u32,
166    ) -> Result<(), SparseError> {
167        *self.val = SparsePointedValue::Null;
168        *self.val = SparseRefRawInline::init_val(state, &mut self.utils, depth)?;
169        Ok(())
170    }
171
172    /// Create a new [SparseRefRawInline](SparseRefRawInline)
173    pub fn new(
174        state: &mut SparseState,
175        path: PathBuf,
176        raw_pointer: String,
177        depth: u32,
178    ) -> Result<Self, SparseError> {
179        let mut utils = SparseMetadata::new(raw_pointer.clone(), path);
180        let val: Box<SparsePointedValue<S>> =
181            Box::new(SparseRefRawInline::init_val(state, &mut utils, depth)?);
182        Ok(SparseRefRawInline {
183            val,
184            raw_pointer,
185            utils,
186        })
187    }
188}