loro_internal/
configure.rs1pub 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 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}