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