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}