rive_rs/
option_cell.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::cell::Cell;
6use std::fmt;
7
8pub struct OptionCell<T>(Cell<Option<T>>);
9
10impl<T> OptionCell<T> {
11    pub fn new() -> Self {
12        Self(Cell::new(None))
13    }
14}
15
16impl<T: Clone> OptionCell<T> {
17    pub fn get(&self) -> Option<T> {
18        let val = self.0.take();
19        self.0.set(val.clone());
20        val
21    }
22}
23
24impl<T> OptionCell<T> {
25    pub fn maybe_init(&self, f: impl FnOnce() -> T) {
26        let val = self.0.take();
27        self.0.set(Some(val.unwrap_or_else(f)));
28    }
29
30    pub fn set(&self, val: Option<T>) {
31        self.0.set(val);
32    }
33
34    pub fn with<U>(&self, mut f: impl FnMut(Option<&T>) -> U) -> U {
35        let val = self.0.take();
36        let result = f(val.as_ref());
37        self.0.set(val);
38
39        result
40    }
41
42    pub fn with_mut<U>(&self, mut f: impl FnMut(Option<&mut T>) -> U) -> U {
43        let mut val = self.0.take();
44        let result = f(val.as_mut());
45        self.0.set(val);
46
47        result
48    }
49}
50
51impl<T> Default for OptionCell<T> {
52    fn default() -> Self {
53        Self(Cell::new(None))
54    }
55}
56
57impl<T: fmt::Debug> fmt::Debug for OptionCell<T> {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        self.with(|val| fmt::Debug::fmt(&val, f))
60    }
61}