1use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
2use std::sync::Mutex;
3
4use anyhow::{bail, Result};
5use lazy_static::lazy_static;
6use nine::p2000::OpenMode;
7
8use crate::dial;
9use crate::{fid::Fid, fsys::Fsys};
10lazy_static! {
11 pub static ref FSYS: Mutex<Fsys> = Mutex::new(dial::mount_service("acme").unwrap());
12}
13
14#[derive(Debug)]
15pub struct WinInfo {
16 pub id: usize,
17 pub name: String,
18}
19
20impl WinInfo {
21 pub fn windows() -> Result<Vec<WinInfo>> {
22 let index = FSYS.lock().unwrap().open("index", OpenMode::READ)?;
23 let r = BufReader::new(index);
24 let mut ws = Vec::new();
25 for line in r.lines() {
26 if let Ok(line) = line {
27 let sp: Vec<&str> = line.split_whitespace().collect();
28 if sp.len() < 6 {
29 continue;
30 }
31 ws.push(WinInfo {
32 id: sp[0].parse()?,
33 name: sp[5].to_string(),
34 });
35 }
36 }
37 Ok(ws)
38 }
39}
40
41pub struct LogReader {
42 f: Fid,
43 buf: [u8; 8192],
44}
45
46#[derive(Debug)]
47pub struct LogEvent {
48 pub id: usize,
49 pub op: String,
50 pub name: String,
51}
52
53impl LogReader {
54 pub fn new() -> Result<LogReader> {
55 let log = FSYS.lock().unwrap().open("log", OpenMode::READ)?;
56 Ok(LogReader {
57 f: log,
58 buf: [0; 8192],
59 })
60 }
61 pub fn read(&mut self) -> Result<LogEvent> {
62 let sz = self.f.read(&mut self.buf)?;
63 let data = String::from_utf8(self.buf[0..sz].to_vec())?;
64 let sp: Vec<String> = data.splitn(3, " ").map(|x| x.to_string()).collect();
65 if sp.len() != 3 {
66 bail!("malformed log event");
67 }
68 let id = sp[0].parse()?;
69 let op = sp[1].to_string();
70 let name = sp[2].trim().to_string();
71 Ok(LogEvent { id, op, name })
72 }
73}
74
75pub struct Win {
76 id: usize,
77 ctl: Fid,
78 body: Fid,
79 addr: Fid,
80 data: Fid,
81 tag: Fid,
82}
83
84pub enum File {
85 Ctl,
86 Body,
87 Addr,
88 Data,
89 Tag,
90}
91
92pub struct WinEvents {
93 event: Fid,
94}
95
96impl WinEvents {
97 pub fn read_event(&mut self) -> Result<Event> {
98 let mut e = self.get_event()?;
99
100 if e.flag & 2 != 0 {
102 let mut e2 = self.get_event()?;
103 if e.q0 == e.q1 {
104 e2.orig_q0 = e.q0;
105 e2.orig_q1 = e.q1;
106 e2.flag = e.flag;
107 e = e2;
108 }
109 }
110
111 if e.flag & 8 != 0 {
113 let e3 = self.get_event()?;
114 let e4 = self.get_event()?;
115 e.arg = e3.text;
116 e.loc = e4.text;
117 }
118
119 Ok(e)
120 }
121 fn get_ch(&mut self) -> Result<char> {
122 let mut buf = [0; 1];
123 self.event.read_exact(&mut buf)?;
125 Ok(buf[0] as char)
126 }
127 fn get_en(&mut self) -> Result<u32> {
128 let mut c: char;
129 let mut n: u32 = 0;
130 loop {
131 c = self.get_ch()?;
132 if c < '0' || c > '9' {
133 break;
134 }
135 n = n * 10 + c.to_digit(10).unwrap();
136 }
137 if c != ' ' {
138 bail!("event number syntax");
139 }
140 Ok(n)
141 }
142 fn get_event(&mut self) -> Result<Event> {
143 let c1 = self.get_ch()?;
144 let c2 = self.get_ch()?;
145 let q0 = self.get_en()?;
146 let q1 = self.get_en()?;
147 let flag = self.get_en()?;
148 let nr = self.get_en()? as usize;
149 if nr > EVENT_SIZE {
150 bail!("event size too long");
151 }
152 let mut text = vec![];
153 while text.len() < nr {
154 text.push(self.get_ch()?);
155 }
156 let text: String = text.into_iter().collect();
157 if self.get_ch()? != '\n' {
158 bail!("phase error");
159 }
160
161 Ok(Event {
162 c1,
163 c2,
164 q0,
165 q1,
166 flag,
167 nr: nr as u32,
168 text,
169 orig_q0: q0,
170 orig_q1: q1,
171 arg: "".to_string(),
172 loc: "".to_string(),
173 })
174 }
175 pub fn write_event(&mut self, ev: Event) -> Result<()> {
176 let s = format!("{}{}{} {} \n", ev.c1, ev.c2, ev.q0, ev.q1);
177 self.event.write(s.as_bytes())?;
178 Ok(())
179 }
180}
181
182impl Win {
183 pub fn new() -> Result<Win> {
184 let mut fsys = FSYS.lock().unwrap();
185 let mut fid = fsys.open("new/ctl", OpenMode::RDWR)?;
186 let mut buf = [0; 100];
187 let sz = fid.read(&mut buf)?;
188 let data = String::from_utf8(buf[0..sz].to_vec())?;
189 let sp: Vec<&str> = data.split_whitespace().collect();
190 if sp.len() == 0 {
191 bail!("short read from acme/new/ctl");
192 }
193 let id = sp[0].parse()?;
194 Win::open(&mut fsys, id, fid)
195 }
196 pub fn open(fsys: &mut Fsys, id: usize, ctl: Fid) -> Result<Win> {
198 let body = fsys.open(format!("{}/body", id).as_str(), OpenMode::RDWR)?;
199 let addr = fsys.open(format!("{}/addr", id).as_str(), OpenMode::RDWR)?;
200 let data = fsys.open(format!("{}/data", id).as_str(), OpenMode::RDWR)?;
201 let tag = fsys.open(format!("{}/tag", id).as_str(), OpenMode::RDWR)?;
202 Ok(Win {
203 id,
204 ctl,
205 body,
206 addr,
207 data,
208 tag,
209 })
210 }
211 pub fn events(&mut self) -> Result<WinEvents> {
212 let event = FSYS
213 .lock()
214 .unwrap()
215 .open(format!("{}/event", self.id).as_str(), OpenMode::RDWR)?;
216 Ok(WinEvents { event })
217 }
218 pub fn id(&self) -> usize {
219 self.id
220 }
221 pub fn write(&mut self, file: File, data: &str) -> Result<()> {
222 let f = self.fid(file);
223 f.write(data.as_bytes())?;
224 Ok(())
225 }
226 fn fid(&mut self, file: File) -> &mut Fid {
227 match file {
228 File::Ctl => &mut self.ctl,
229 File::Body => &mut self.body,
230 File::Addr => &mut self.addr,
231 File::Data => &mut self.data,
232 File::Tag => &mut self.tag,
233 }
234 }
235 pub fn ctl(&mut self, data: &str) -> Result<()> {
236 self.write(File::Ctl, &format!("{}\n", data))
237 }
238 pub fn addr(&mut self, data: &str) -> Result<()> {
239 self.write(File::Addr, &format!("{}", data))
240 }
241 pub fn clear(&mut self) -> Result<()> {
242 self.write(File::Addr, &format!(","))?;
243 self.write(File::Data, &format!(""))?;
244 Ok(())
245 }
246 pub fn name(&mut self, name: &str) -> Result<()> {
247 self.ctl(&format!("name {}", name))
248 }
249 pub fn del(&mut self, sure: bool) -> Result<()> {
250 let cmd = if sure { "delete" } else { "del" };
251 self.ctl(cmd)
252 }
253 pub fn read_addr(&mut self) -> Result<(usize, usize)> {
254 let mut buf: [u8; 40] = [0; 40];
255 let f = self.fid(File::Addr);
256 f.seek(SeekFrom::Start(0))?;
257 let sz = f.read(&mut buf)?;
258 let addr = std::str::from_utf8(&buf[0..sz])?;
259 let a: Vec<&str> = addr.split_whitespace().collect();
260 if a.len() < 2 {
261 bail!("short read from acme addr");
262 }
263 Ok((a[0].parse()?, a[1].parse()?))
264 }
265 pub fn read(&mut self, file: File) -> Result<&mut Fid> {
266 let f = self.fid(file);
267 f.seek(SeekFrom::Start(0))?;
268 Ok(f)
269 }
270 pub fn seek(&mut self, file: File, pos: SeekFrom) -> Result<u64> {
271 let f = self.fid(file);
272 Ok(f.seek(pos)?)
273 }
274}
275
276const EVENT_SIZE: usize = 256;
277
278#[derive(Debug)]
279pub struct Event {
280 pub c1: char,
281 pub c2: char,
282 pub q0: u32,
283 pub q1: u32,
284 pub orig_q0: u32,
285 pub orig_q1: u32,
286 pub flag: u32,
287 pub nr: u32,
288 pub text: String,
289 pub arg: String,
290 pub loc: String,
291}
292
293impl Event {
294 pub fn load_text(&mut self) {
295 if self.text.len() == 0 && self.q0 < self.q1 {
296 panic!("unimplemented");
305 }
306 }
307}
308
309#[derive(Debug)]
310pub struct NlOffsets {
311 nl: Vec<u64>,
312 leftover: u64,
313}
314
315impl NlOffsets {
316 pub fn new<R: Read>(r: R) -> Result<NlOffsets> {
317 let mut r = BufReader::new(r);
318 let mut nl = vec![0];
319 let mut o = 0;
320 let mut line = vec![];
321 let mut leftover = 0;
322 loop {
323 line.clear();
324 let sz = r.read_until('\n' as u8, &mut line)?;
325 if sz == 0 {
326 break;
327 }
328 let n = std::str::from_utf8(&line)?.chars().count() as u64;
329 let last: u8 = *line.last().unwrap();
330 if last != '\n' as u8 {
331 leftover = n;
332 break;
333 }
334 o += n;
335 nl.push(o);
336 }
337 Ok(NlOffsets { nl, leftover })
338 }
339 pub fn offset_to_line(&self, offset: u64) -> (u64, u64) {
341 for (i, o) in self.nl.iter().enumerate() {
342 if *o > offset {
343 return (i as u64 - 1, offset - self.nl[i - 1]);
344 }
345 }
346 let i = self.nl.len() - 1;
347 if offset >= self.nl[i] {
348 return (i as u64, offset - self.nl[i]);
349 }
350 panic!("unreachable");
351 }
352 pub fn line_to_offset(&self, line: u64, col: u64) -> u64 {
353 let line = line as usize;
354 let eof = self.nl[self.nl.len() - 1] + self.leftover;
355 if line >= self.nl.len() {
356 return eof;
358 }
359 let mut o = self.nl[line] + col;
360 if o > eof {
361 o = eof;
362 }
363 o
364 }
365 pub fn last(&self) -> (u64, u64) {
367 if self.nl.is_empty() {
368 (0, self.leftover)
369 } else {
370 (self.nl.len() as u64 - 1, self.leftover)
371 }
372 }
373}
374
375#[cfg(test)]
376mod tests {
377 use crate::acme::*;
378
379 #[test]
380 fn nloffsets() {
381 let s = "12345\n678\n90";
382 let c = std::io::Cursor::new(s);
383 let n = NlOffsets::new(c).unwrap();
384 assert_eq!(n.offset_to_line(0), (0, 0));
385 assert_eq!(n.offset_to_line(3), (0, 3));
386 assert_eq!(n.offset_to_line(5), (0, 5));
387 assert_eq!(n.offset_to_line(6), (1, 0));
388 assert_eq!(n.offset_to_line(7), (1, 1));
389 assert_eq!(n.offset_to_line(9), (1, 3));
390 assert_eq!(n.offset_to_line(10), (2, 0));
391 assert_eq!(n.offset_to_line(11), (2, 1));
392 assert_eq!(n.last(), (2, 2));
393 }
394
395 #[test]
396 fn windows() {
397 let ws = WinInfo::windows().unwrap();
398 assert_ne!(ws.len(), 0);
399 }
400
401 #[test]
402 fn log() {
403 let mut log = LogReader::new().unwrap();
404 log.read().unwrap();
405 }
406
407 #[test]
408 #[ignore]
409 fn new() {
410 let mut w = Win::new().unwrap();
411 let mut wev = w.events().unwrap();
412 w.name("testing").unwrap();
413 w.write(File::Body, "blah hello done hello").unwrap();
414 loop {
415 let mut ev = wev.read_event().unwrap();
416 println!("ev: {:?}", ev);
417 match ev.c2 {
418 'x' | 'X' => {
419 let text = ev.text.trim();
420 if text == "done" {
421 break;
422 }
423 println!("cmd text: {}", ev.text);
424 wev.write_event(ev).unwrap();
425 }
426 'l' | 'L' => {
427 ev.load_text();
428 println!("look: {}", ev.text);
429 wev.write_event(ev).unwrap();
430 }
431 _ => {}
432 }
433 }
434 w.del(true).unwrap();
435 }
436}