loro_internal/
configure.rs

1pub use crate::container::richtext::config::{StyleConfig, StyleConfigMap};
2use crate::LoroDoc;
3use std::sync::atomic::{AtomicBool, AtomicI64};
4use std::sync::Arc;
5use std::sync::RwLock;
6
7#[derive(Clone, Debug)]
8pub struct Configure {
9    pub(crate) text_style_config: Arc<RwLock<StyleConfigMap>>,
10    record_timestamp: Arc<AtomicBool>,
11    pub(crate) merge_interval_in_s: Arc<AtomicI64>,
12    pub(crate) editable_detached_mode: Arc<AtomicBool>,
13}
14
15impl LoroDoc {
16    pub(crate) fn set_config(&self, config: &Configure) {
17        self.config_text_style(config.text_style_config.read().unwrap().clone());
18        self.set_record_timestamp(config.record_timestamp());
19        self.set_change_merge_interval(config.merge_interval());
20        self.set_detached_editing(config.detached_editing());
21    }
22}
23
24impl Default for Configure {
25    fn default() -> Self {
26        Self {
27            text_style_config: Arc::new(RwLock::new(StyleConfigMap::default_rich_text_config())),
28            record_timestamp: Arc::new(AtomicBool::new(false)),
29            editable_detached_mode: Arc::new(AtomicBool::new(false)),
30            merge_interval_in_s: Arc::new(AtomicI64::new(1000)),
31        }
32    }
33}
34
35impl Configure {
36    pub fn fork(&self) -> Self {
37        Self {
38            text_style_config: Arc::new(RwLock::new(
39                self.text_style_config.read().unwrap().clone(),
40            )),
41            record_timestamp: Arc::new(AtomicBool::new(
42                self.record_timestamp
43                    .load(std::sync::atomic::Ordering::Relaxed),
44            )),
45            merge_interval_in_s: Arc::new(AtomicI64::new(
46                self.merge_interval_in_s
47                    .load(std::sync::atomic::Ordering::Relaxed),
48            )),
49            editable_detached_mode: Arc::new(AtomicBool::new(
50                self.editable_detached_mode
51                    .load(std::sync::atomic::Ordering::Relaxed),
52            )),
53        }
54    }
55
56    pub fn text_style_config(&self) -> &Arc<RwLock<StyleConfigMap>> {
57        &self.text_style_config
58    }
59
60    pub fn record_timestamp(&self) -> bool {
61        self.record_timestamp
62            .load(std::sync::atomic::Ordering::Relaxed)
63    }
64
65    pub fn set_record_timestamp(&self, record: bool) {
66        self.record_timestamp
67            .store(record, std::sync::atomic::Ordering::Relaxed);
68    }
69
70    pub fn detached_editing(&self) -> bool {
71        self.editable_detached_mode
72            .load(std::sync::atomic::Ordering::Relaxed)
73    }
74
75    pub fn set_detached_editing(&self, mode: bool) {
76        self.editable_detached_mode
77            .store(mode, std::sync::atomic::Ordering::Relaxed);
78    }
79
80    pub fn merge_interval(&self) -> i64 {
81        self.merge_interval_in_s
82            .load(std::sync::atomic::Ordering::Relaxed)
83    }
84
85    pub fn set_merge_interval(&self, interval: i64) {
86        self.merge_interval_in_s
87            .store(interval, std::sync::atomic::Ordering::Relaxed);
88    }
89}
90
91#[derive(Debug)]
92pub struct DefaultRandom;
93
94#[cfg(test)]
95use std::sync::atomic::AtomicU64;
96#[cfg(test)]
97static mut TEST_RANDOM: AtomicU64 = AtomicU64::new(0);
98
99impl SecureRandomGenerator for DefaultRandom {
100    fn fill_byte(&self, dest: &mut [u8]) {
101        #[cfg(not(test))]
102        getrandom::getrandom(dest).unwrap();
103
104        #[cfg(test)]
105        // SAFETY: this is only used in test
106        unsafe {
107            #[allow(static_mut_refs)]
108            let bytes = TEST_RANDOM.fetch_add(1, std::sync::atomic::Ordering::Release);
109            dest.copy_from_slice(&bytes.to_le_bytes());
110        }
111    }
112}
113
114pub trait SecureRandomGenerator: Send + Sync {
115    fn fill_byte(&self, dest: &mut [u8]);
116    fn next_u64(&self) -> u64 {
117        let mut buf = [0u8; 8];
118        self.fill_byte(&mut buf);
119        u64::from_le_bytes(buf)
120    }
121
122    fn next_u32(&self) -> u32 {
123        let mut buf = [0u8; 4];
124        self.fill_byte(&mut buf);
125        u32::from_le_bytes(buf)
126    }
127
128    fn next_i64(&self) -> i64 {
129        let mut buf = [0u8; 8];
130        self.fill_byte(&mut buf);
131        i64::from_le_bytes(buf)
132    }
133
134    fn next_i32(&self) -> i32 {
135        let mut buf = [0u8; 4];
136        self.fill_byte(&mut buf);
137        i32::from_le_bytes(buf)
138    }
139}