diff --git a/src/main.rs b/src/main.rs index 7c4c5ef..f306464 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,109 +1,13 @@ extern crate rocket; -use std::sync::{ atomic::AtomicUsize, atomic::Ordering, Mutex }; -use std::{ collections::HashMap }; -use juniper::{ EmptySubscription, RootNode, graphql_object, Context }; use rocket::{ response::content, Rocket, State }; +use juniper::{ EmptySubscription }; -#[derive(Clone)] -pub struct Person { - id: String, - name: String, -} +mod model; +mod schema; -impl Person { - pub fn new(id: String, name: String) -> Person { - Person { id, name } - } - - fn name(&self) -> Option<&str> { - Some(self.name.as_str()) - } -} - -#[graphql_object(context = Database)] -impl Person { - fn id(&self) -> &str { - &self.id - } - - fn name(&self) -> Option<&str> { - Some(self.name.as_str()) - } -} - -#[derive(Default)] -pub struct Database { - people: Mutex>, - next_id: AtomicUsize, -} - -impl Database { - pub fn new() -> Database { - let database = Database { - people: Mutex::new(HashMap::new()), - next_id: AtomicUsize::new(1), - }; - database - } - - pub fn get_person(&self, id: &str) -> Option { - let people = self.people.lock().expect("Couldn't lock people"); - match people.get(id) { - Some(person) => Some(person.to_owned()), - None => None, - } - } - - pub fn add_person(&self, person: Person) { - self.people.lock().expect("Couldn't lock people").insert(person.id.to_owned(), person); - } - - pub fn new_id(&self) -> usize { - self.next_id.fetch_add(1, Ordering::Relaxed) - } - - pub fn new_person(&self, name: String) -> Option { - let person = Person { - id: self.new_id().to_string(), - name, - }; - self.people.lock().expect("lock people hashmap").insert(person.id.to_owned(), person.to_owned()); - Some(person) - } -} - -impl Context for Database {} - -pub struct Query; -#[graphql_object(context = Database)] -impl Query { - #[graphql(arguments(id(description = "id of the human")))] - fn human(database: &Database, id: String) -> Option { - database.get_person(&id) - } -} - -struct Mutations; - -#[graphql_object(context = Database)] -impl Mutations { - fn addHuman(database: &Database, id: String, name: String) -> Person { - let new_guy = Person::new(id, name); - database.add_person(new_guy.to_owned()); - new_guy.to_owned() - } - - fn newId(database: &Database) -> i32 { - database.new_id() as i32 - } - - fn newPerson(database: &Database, name: String) -> Option { - database.new_person(name) - } -} - -type Schema = RootNode<'static, Query, Mutations, EmptySubscription>; +use model::Database; +use schema::{ Schema, Query, Mutations }; #[rocket::get("/")] fn graphiql() -> content::Html { @@ -138,13 +42,15 @@ fn get_rest(id: String, context: &State) -> Option { #[rocket::main] async fn main() { + let schema = Schema::new( + Query, + Mutations, + EmptySubscription::::new(), + ); + Rocket::build() .manage(Database::new()) - .manage(Schema::new( - Query, - Mutations, - EmptySubscription::::new(), - )) + .manage(schema) .mount( "/", rocket::routes![graphiql, get_graphql_handler, post_graphql_handler, get_rest], diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..4f9b410 --- /dev/null +++ b/src/model.rs @@ -0,0 +1,63 @@ +use std::sync::{ atomic::AtomicUsize, atomic::Ordering, Mutex }; +use std::{ collections::HashMap }; + +#[derive(Clone)] +pub struct Person { + id: String, + name: String, +} + +impl Person { + pub fn new(id: String, name: String) -> Person { + Person { id, name } + } + + pub fn id(&self) -> &str { + self.id.as_str() + } + + pub fn name(&self) -> Option<&str> { + Some(self.name.as_str()) + } +} + +#[derive(Default)] +pub struct Database { + people: Mutex>, + next_id: AtomicUsize, +} + +impl Database { + pub fn new() -> Database { + let database = Database { + people: Mutex::new(HashMap::new()), + next_id: AtomicUsize::new(1), + }; + database + } + + pub fn get_person(&self, id: &str) -> Option { + let people = self.people.lock().expect("Couldn't lock people"); + match people.get(id) { + Some(person) => Some(person.to_owned()), + None => None, + } + } + + pub fn add_person(&self, person: Person) { + self.people.lock().expect("Couldn't lock people").insert(person.id.to_owned(), person); + } + + pub fn new_id(&self) -> usize { + self.next_id.fetch_add(1, Ordering::Relaxed) + } + + pub fn new_person(&self, name: String) -> Option { + let person = Person { + id: self.new_id().to_string(), + name, + }; + self.people.lock().expect("lock people hashmap").insert(person.id.to_owned(), person.to_owned()); + Some(person) + } +} diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..f51892f --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,45 @@ +impl Context for Database {} + +use juniper::{ EmptySubscription, RootNode, graphql_object, Context }; +use crate::model::{ Database, Person }; + +#[graphql_object(context = Database)] +impl Person { + fn id(&self) -> &str { + self.id() + } + + fn name(&self) -> Option<&str> { + self.name() + } +} + +pub struct Query; +#[graphql_object(context = Database)] +impl Query { + #[graphql(arguments(id(description = "id of the human")))] + fn human(database: &Database, id: String) -> Option { + database.get_person(&id) + } +} + +pub struct Mutations; + +#[graphql_object(context = Database)] +impl Mutations { + fn addHuman(database: &Database, id: String, name: String) -> Person { + let new_guy = Person::new(id, name); + database.add_person(new_guy.to_owned()); + new_guy.to_owned() + } + + fn newId(database: &Database) -> i32 { + database.new_id() as i32 + } + + fn newPerson(database: &Database, name: String) -> Option { + database.new_person(name) + } +} + +pub type Schema = RootNode<'static, Query, Mutations, EmptySubscription>;