stage 1
Create the basic framework
- Create the basics, use Rocket because it is similar to node frameworks I have used in the past. It uses macros to “annotate” the functions that actually handle the requests.
#[get("/task/<id>")]
fn get_task_by_id( id: u32) -> String {
...
}
fn main() {
...
rocket::ignite()
.mount("/", routes![get_task_by_id])
.launch();
}
- Add in a basic struct and implement the new function for it.
- Use Serde Json to handle the serialization ad deserialization of the object to Json and back
#[derive(Serialize,Deserialize,Debug)]
pub struct Task {
pub element: u32,
pub name: String,
}
impl Task {
pub fn new(element: u32, name: String) -> Self { Self { element, name } }
}
- Create a struct that contains a list of these Tasks indexed by id (u32).
type TaskHashMap = HashMap<u32,Task>;
pub struct TaskList {
pub tasks : TaskHashMap,
}
- Use the state sharing cpabilities of Rocket to share the list.
#[post("/tasks", data = "<t>")]
fn add_task(state: State<tasks::TaskList>, t: Json<Task>) -> String {...}
...
fn main() {
let task_db= tasks::TaskList::new();
rocket::ignite()
.mount("/", routes![get_tasks,add_task,get_task_by_id])
.manage(task_db)
.launch();
}
- Realise that Rocket is threaded and so I need to share the tasks amongst concurrent threads.
- this is done by wrapping the TaskList in an ARC and RwLock to sunchronise access and satify the compiler.
type TaskHashMap = HashMap<u32,Task>;
pub struct TaskList {
pub tasks : Arc<RwLock<TaskHashMap>>,
}
impl TaskList {
pub fn new() -> TaskList {
TaskList {
tasks : Arc::new(RwLock::new(TaskHashMap::new())),
}
}
...
}
//in main functions
#[post("/tasks", data = "<t>")]
fn add_task(state: State<tasks::TaskList>, t: Json<Task>) -> String {
let tl = self.tasks.clone();
let mut my_tasks = tl.read().expect("RWLOCK poisoned");
//we should get the request body here and read in the json body
let o = tasks::Task::new(...);
//insert the object
let r = match my_tasks.insert(new_id, o) {
...
};
...
}
- Saving the structures to a file in the first instance.
//
// Save list after each addition (inefficient but works)
// no particular location
let f = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open("tasklist.json").unwrap();
//use a buffer
let fb = std::io::BufWriter::new(f);
//collect the tasks and put into a vector to serialize
let my_vec: Vec<&Task> = my_tasks.iter().map(|(_,v)| v.clone()).collect();
//use serde to actually save it.
serde_json::ser::to_writer_pretty(fb, &my_vec).expect("Failed to write");
r
- The working version of this stage is pre-release tag 1.0
Back to index page of the project is about getting the initial rust API running.