loro_internal/
configure.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
pub use crate::container::richtext::config::{StyleConfig, StyleConfigMap};
use crate::LoroDoc;

#[derive(Clone, Debug)]
pub struct Configure {
    pub(crate) text_style_config: Arc<RwLock<StyleConfigMap>>,
    record_timestamp: Arc<AtomicBool>,
    pub(crate) merge_interval_in_s: Arc<AtomicI64>,
    pub(crate) editable_detached_mode: Arc<AtomicBool>,
}

impl LoroDoc {
    pub(crate) fn set_config(&self, config: &Configure) {
        self.config_text_style(config.text_style_config.read().unwrap().clone());
        self.set_record_timestamp(config.record_timestamp());
        self.set_change_merge_interval(config.merge_interval());
        self.set_detached_editing(config.detached_editing());
    }
}

impl Default for Configure {
    fn default() -> Self {
        Self {
            text_style_config: Arc::new(RwLock::new(StyleConfigMap::default_rich_text_config())),
            record_timestamp: Arc::new(AtomicBool::new(false)),
            editable_detached_mode: Arc::new(AtomicBool::new(false)),
            merge_interval_in_s: Arc::new(AtomicI64::new(1000)),
        }
    }
}

impl Configure {
    pub fn fork(&self) -> Self {
        Self {
            text_style_config: Arc::new(RwLock::new(
                self.text_style_config.read().unwrap().clone(),
            )),
            record_timestamp: Arc::new(AtomicBool::new(
                self.record_timestamp
                    .load(std::sync::atomic::Ordering::Relaxed),
            )),
            merge_interval_in_s: Arc::new(AtomicI64::new(
                self.merge_interval_in_s
                    .load(std::sync::atomic::Ordering::Relaxed),
            )),
            editable_detached_mode: Arc::new(AtomicBool::new(
                self.editable_detached_mode
                    .load(std::sync::atomic::Ordering::Relaxed),
            )),
        }
    }

    pub fn text_style_config(&self) -> &Arc<RwLock<StyleConfigMap>> {
        &self.text_style_config
    }

    pub fn record_timestamp(&self) -> bool {
        self.record_timestamp
            .load(std::sync::atomic::Ordering::Relaxed)
    }

    pub fn set_record_timestamp(&self, record: bool) {
        self.record_timestamp
            .store(record, std::sync::atomic::Ordering::Relaxed);
    }

    pub fn detached_editing(&self) -> bool {
        self.editable_detached_mode
            .load(std::sync::atomic::Ordering::Relaxed)
    }

    pub fn set_detached_editing(&self, mode: bool) {
        self.editable_detached_mode
            .store(mode, std::sync::atomic::Ordering::Relaxed);
    }

    pub fn merge_interval(&self) -> i64 {
        self.merge_interval_in_s
            .load(std::sync::atomic::Ordering::Relaxed)
    }

    pub fn set_merge_interval(&self, interval: i64) {
        self.merge_interval_in_s
            .store(interval, std::sync::atomic::Ordering::Relaxed);
    }
}

#[derive(Debug)]
pub struct DefaultRandom;

#[cfg(test)]
use std::sync::atomic::AtomicU64;
use std::sync::{
    atomic::{AtomicBool, AtomicI64},
    Arc, RwLock,
};
#[cfg(test)]
static mut TEST_RANDOM: AtomicU64 = AtomicU64::new(0);

impl SecureRandomGenerator for DefaultRandom {
    fn fill_byte(&self, dest: &mut [u8]) {
        #[cfg(not(test))]
        getrandom::getrandom(dest).unwrap();

        #[cfg(test)]
        // SAFETY: this is only used in test
        unsafe {
            #[allow(static_mut_refs)]
            let bytes = TEST_RANDOM.fetch_add(1, std::sync::atomic::Ordering::Release);
            dest.copy_from_slice(&bytes.to_le_bytes());
        }
    }
}

pub trait SecureRandomGenerator: Send + Sync {
    fn fill_byte(&self, dest: &mut [u8]);
    fn next_u64(&self) -> u64 {
        let mut buf = [0u8; 8];
        self.fill_byte(&mut buf);
        u64::from_le_bytes(buf)
    }

    fn next_u32(&self) -> u32 {
        let mut buf = [0u8; 4];
        self.fill_byte(&mut buf);
        u32::from_le_bytes(buf)
    }

    fn next_i64(&self) -> i64 {
        let mut buf = [0u8; 8];
        self.fill_byte(&mut buf);
        i64::from_le_bytes(buf)
    }

    fn next_i32(&self) -> i32 {
        let mut buf = [0u8; 4];
        self.fill_byte(&mut buf);
        i32::from_le_bytes(buf)
    }
}