Implement /api/v0/language

This commit is contained in:
Konrad Borowski 2021-06-14 18:53:12 +02:00
parent c5f29e5953
commit a484351922
5 changed files with 142 additions and 3 deletions

1
Cargo.lock generated
View File

@ -1577,6 +1577,7 @@ dependencies = [
"rocket_codegen",
"rocket_http",
"serde",
"serde_json",
"state",
"tempfile",
"time 0.2.27",

View File

@ -16,7 +16,7 @@ log = "0.4.14"
once_cell = "1.8.0"
pulldown-cmark = "0.8.0"
rand = "0.8.3"
rocket = "0.5.0-rc.1"
rocket = { version = "0.5.0-rc.1", features = ["json"] }
rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["tera"] }
rocket_sync_db_pools = { version = "0.1.0-rc.1", features = ["diesel_postgres_pool"] }
serde = { version = "1.0.126", features = ["derive"] }

View File

@ -24,7 +24,7 @@ mod models;
mod routes;
mod schema;
use crate::routes::{display_paste, index, insert_paste, raw_paste};
use crate::routes::{api_language, display_paste, index, insert_paste, raw_paste};
use diesel::prelude::*;
use rocket::fairing::AdHoc;
use rocket::fs::{relative, FileServer};
@ -63,6 +63,9 @@ async fn rocket() -> _ {
.expect("database to be migrated");
rocket
}))
.mount("/", routes![index, insert_paste, display_paste, raw_paste])
.mount(
"/",
routes![api_language, index, insert_paste, display_paste, raw_paste],
)
.mount("/static", FileServer::from(relative!("static")))
}

View File

@ -0,0 +1,133 @@
// pastebin.run
// Copyright (C) 2020-2021 Konrad Borowski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::schema::{implementation_wrappers, implementations, languages};
use crate::Db;
use diesel::prelude::*;
use rocket::response::Debug;
use rocket::serde::json::Json;
use serde::Serialize;
#[derive(Queryable)]
struct Language {
id: i32,
hello_world: Option<String>,
}
#[derive(Serialize, Queryable)]
#[serde(rename_all = "camelCase")]
struct Wrapper {
identifier: String,
label: String,
is_asm: bool,
is_formatter: bool,
}
#[derive(Identifiable, Queryable)]
struct Implementation {
id: i32,
label: String,
}
#[derive(Associations, Identifiable, Queryable)]
#[belongs_to(Implementation)]
struct ImplementationWrapper {
id: i32,
implementation_id: i32,
identifier: String,
label: String,
is_asm: bool,
is_formatter: bool,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct JsonLanguage {
hello_world: Option<String>,
implementations: Vec<JsonImplementation>,
}
#[derive(Serialize)]
struct JsonImplementation {
label: String,
wrappers: Vec<Wrapper>,
}
#[get("/api/v0/language/<identifier>")]
pub async fn api_language(
db: Db,
identifier: String,
) -> Result<Option<Json<JsonLanguage>>, Debug<diesel::result::Error>> {
db.run(|conn| {
let language: Option<Language> = languages::table
.filter(languages::identifier.eq(identifier))
.select((languages::language_id, languages::hello_world))
.get_result(conn)
.optional()?;
Ok(if let Some(language) = language {
let implementations = implementations::table
.select((implementations::implementation_id, implementations::label))
.filter(implementations::language_id.eq(language.id))
.order(implementations::ordering)
.load(conn)?;
let implementation_wrappers = ImplementationWrapper::belonging_to(&implementations)
.select((
implementation_wrappers::implementation_wrapper_id,
implementation_wrappers::implementation_id,
implementation_wrappers::identifier,
implementation_wrappers::label,
implementation_wrappers::is_asm,
implementation_wrappers::is_formatter,
))
.order(implementation_wrappers::ordering)
.load(conn)?;
let implementations = implementation_wrappers
.grouped_by(&implementations)
.into_iter()
.zip(implementations)
.map(|(wrappers, implementation)| JsonImplementation {
label: implementation.label,
wrappers: wrappers
.into_iter()
.map(
|ImplementationWrapper {
identifier,
label,
is_asm,
is_formatter,
..
}| {
Wrapper {
identifier,
label,
is_asm,
is_formatter,
}
},
)
.collect(),
})
.collect();
Some(Json(JsonLanguage {
implementations,
hello_world: language.hello_world,
}))
} else {
None
})
})
.await
}

View File

@ -14,11 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
mod api_language_route;
mod display_paste_route;
mod index_route;
mod insert_paste_route;
mod raw_paste_route;
pub use api_language_route::*;
pub use display_paste_route::*;
pub use index_route::*;
pub use insert_paste_route::*;