loro_internal/
configure.rs

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