1use crate::{language::LanguageRegistry, settings, time::ReplicaId, AppState};
2use ctor::ctor;
3use gpui::AppContext;
4use rand::Rng;
5use std::{
6 collections::BTreeMap,
7 path::{Path, PathBuf},
8 sync::Arc,
9};
10use tempdir::TempDir;
11
12#[ctor]
13fn init_logger() {
14 env_logger::init();
15}
16
17#[derive(Clone)]
18struct Envelope<T: Clone> {
19 message: T,
20 sender: ReplicaId,
21}
22
23pub(crate) struct Network<T: Clone> {
24 inboxes: BTreeMap<ReplicaId, Vec<Envelope<T>>>,
25 all_messages: Vec<T>,
26}
27
28impl<T: Clone> Network<T> {
29 pub fn new() -> Self {
30 Network {
31 inboxes: BTreeMap::new(),
32 all_messages: Vec::new(),
33 }
34 }
35
36 pub fn add_peer(&mut self, id: ReplicaId) {
37 self.inboxes.insert(id, Vec::new());
38 }
39
40 pub fn is_idle(&self) -> bool {
41 self.inboxes.values().all(|i| i.is_empty())
42 }
43
44 pub fn broadcast<R>(&mut self, sender: ReplicaId, messages: Vec<T>, rng: &mut R)
45 where
46 R: Rng,
47 {
48 for (replica, inbox) in self.inboxes.iter_mut() {
49 if *replica != sender {
50 for message in &messages {
51 let min_index = inbox
52 .iter()
53 .enumerate()
54 .rev()
55 .find_map(|(index, envelope)| {
56 if sender == envelope.sender {
57 Some(index + 1)
58 } else {
59 None
60 }
61 })
62 .unwrap_or(0);
63
64 // Insert one or more duplicates of this message *after* the previous
65 // message delivered by this replica.
66 for _ in 0..rng.gen_range(1..4) {
67 let insertion_index = rng.gen_range(min_index..inbox.len() + 1);
68 inbox.insert(
69 insertion_index,
70 Envelope {
71 message: message.clone(),
72 sender,
73 },
74 );
75 }
76 }
77 }
78 }
79 self.all_messages.extend(messages);
80 }
81
82 pub fn has_unreceived(&self, receiver: ReplicaId) -> bool {
83 !self.inboxes[&receiver].is_empty()
84 }
85
86 pub fn receive<R>(&mut self, receiver: ReplicaId, rng: &mut R) -> Vec<T>
87 where
88 R: Rng,
89 {
90 let inbox = self.inboxes.get_mut(&receiver).unwrap();
91 let count = rng.gen_range(0..inbox.len() + 1);
92 inbox
93 .drain(0..count)
94 .map(|envelope| envelope.message)
95 .collect()
96 }
97}
98
99pub fn sample_text(rows: usize, cols: usize) -> String {
100 let mut text = String::new();
101 for row in 0..rows {
102 let c: char = ('a' as u32 + row as u32) as u8 as char;
103 let mut line = c.to_string().repeat(cols);
104 if row < rows - 1 {
105 line.push('\n');
106 }
107 text += &line;
108 }
109 text
110}
111
112pub fn temp_tree(tree: serde_json::Value) -> TempDir {
113 let dir = TempDir::new("").unwrap();
114 write_tree(dir.path(), tree);
115 dir
116}
117
118fn write_tree(path: &Path, tree: serde_json::Value) {
119 use serde_json::Value;
120 use std::fs;
121
122 if let Value::Object(map) = tree {
123 for (name, contents) in map {
124 let mut path = PathBuf::from(path);
125 path.push(name);
126 match contents {
127 Value::Object(_) => {
128 fs::create_dir(&path).unwrap();
129 write_tree(&path, contents);
130 }
131 Value::Null => {
132 fs::create_dir(&path).unwrap();
133 }
134 Value::String(contents) => {
135 fs::write(&path, contents).unwrap();
136 }
137 _ => {
138 panic!("JSON object must contain only objects, strings, or null");
139 }
140 }
141 }
142 } else {
143 panic!("You must pass a JSON object to this helper")
144 }
145}
146
147pub fn build_app_state(cx: &AppContext) -> AppState {
148 let settings = settings::channel(&cx.font_cache()).unwrap().1;
149 let language_registry = Arc::new(LanguageRegistry::new());
150 AppState {
151 settings,
152 language_registry,
153 rpc: zed_rpc::Peer::new(),
154 }
155}