rustkernel/handlers.rs
1use std::io::prelude::*;
2use std::net::TcpStream;
3use String;
4
5use crate::Program;
6
7/// The requests from VS Code are marshalled through `Serde` via this struct
8/// # Terms
9/// - index: the current vertical position of the cell that was executed
10/// - fragment: a unique ID for each cell, if they change order this id remains the same
11/// - filename: Where the file was executed from, important to reset the code if the user changes files
12/// - contents: the contents / source code of a cell
13pub struct CodeRequest {
14 pub index: u32,
15 pub fragment: u32,
16 pub filename: String,
17 pub workspace: String,
18 pub contents: String,
19}
20
21/// All requests run through here
22/// # Parameters
23/// stream: Contains the http request, when it's read from it modifies
24/// internal state, which is why it needs to be `mut`. Also contains
25/// a reference to the `Program` which lives for the lifetime of the
26/// server running. It retains information between requests
27pub fn code_request(mut stream: TcpStream, program: &mut Program) {
28 // Set a buffer and read in the stream
29 let mut buffer = [0; 8192];
30 stream.read(&mut buffer).expect("Error reading stream");
31
32 // Convert the utf8 to a string
33 let req = String::from_utf8_lossy(&buffer);
34 let mut req_iter = req.split("\0");
35
36 let cr = CodeRequest {
37 index: req_iter.next().unwrap().parse().unwrap(),
38 fragment: req_iter.next().unwrap().parse().unwrap(),
39 filename: req_iter.next().unwrap().to_string(),
40 workspace: req_iter.next().unwrap().to_string(),
41 contents: req_iter.next().unwrap().to_string(),
42 };
43
44 // If the filename is different to last run, this resets
45 // the state of `Program`
46 if cr.filename != program.filename {
47 *program = Program::new();
48 }
49 program.filename = cr.filename.to_owned();
50 program.workspace = cr.workspace.to_owned();
51
52 // If there is a cell already there, update existing, otherwise create
53 match program.cells.get(&cr.fragment) {
54 Some(_) => program.update_cell(&cr),
55 None => program.create_cell(&cr),
56 }
57
58 // Runs through all the cells and creates a program to run
59 program.write_to_file(cr.fragment);
60
61 // Run the program and return response to caller
62 let response = program.run();
63 stream.write(response.as_bytes()).unwrap();
64 stream.flush().unwrap();
65
66 // Format the file for anyone looking at the source code
67 program.fmt();
68}