use dever_runtime::api; use dever_runtime::application::Session; use dever_runtime::auth; use dever_runtime::config::RuntimeProfile; use dever_runtime::http::{Request, Response}; use dever_runtime::wire::decode::{self, Fields, Reader}; use dever_runtime::wire::{Encoded, Encoder}; use dever_runtime::{lifecycle, task}; #[derive(Default)] struct Row { id: i64, text: String, weight: f64, note: Option, } impl Fields for Row { fn count(&self) -> usize { 4 } fn index(&self, name: &str) -> Result { match name { "id" => Ok(0), "text" => Ok(1), "weight" => Ok(2), "note" => Ok(3), _ => Err("unknown wire record field".into()), } } fn required(&self, index: usize) -> bool { index != 3 } fn read(&mut self, index: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> { match index { 0 => self.id = reader.int()?, 1 => self.text = reader.text()?.into_owned(), 2 => self.weight = reader.float()?, 3 => { reader.nullable(&mut |reader| { self.note = Some(reader.text()?.into_owned()); Ok(()) })?; } _ => return Err("invalid wire field index".into()), } Ok(()) } } #[derive(Default)] struct Payload { rows: Vec, raw: Option, } impl Fields for Payload { fn count(&self) -> usize { 2 } fn index(&self, name: &str) -> Result { match name { "rows" => Ok(0), "raw" => Ok(1), _ => Err("unknown wire record field".into()), } } fn required(&self, _: usize) -> bool { true } fn read(&mut self, index: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> { match index { 0 => reader.list(&mut |reader| { let mut row = Row::default(); reader.record(&mut row)?; self.rows.push(row); Ok(()) }), 1 => { self.raw = Some(reader.json()?); Ok(()) } _ => Err("invalid wire field index".into()), } } } impl Payload { fn encode(self) -> Result { let mut encoder = Encoder::default(); encoder.compiled_record(2, |encoder| { encoder.compiled_key("\"rows\":")?; encoder.begin_array()?; for row in self.rows { encoder.compiled_record(4, |encoder| { encoder.compiled_key("\"id\":")?; encoder.int(row.id)?; encoder.compiled_key(",\"text\":")?; encoder.text(&row.text)?; encoder.compiled_key(",\"weight\":")?; encoder.float(row.weight)?; encoder.compiled_key(",\"note\":")?; match row.note { Some(note) => encoder.text(¬e), None => encoder.null(), } })?; } encoder.end()?; encoder.compiled_key(",\"raw\":")?; encoder.encoded(&self.raw.ok_or("missing required wire field")?) })?; encoder.finish() } } enum Value { Typed(Payload), Raw(Encoded), } struct Arguments { typed: bool, value: Option, } impl Fields for Arguments { fn count(&self) -> usize { 1 } fn index(&self, name: &str) -> Result { if name == if self.typed { "payload" } else { "source" } { Ok(0) } else { Err("unknown wire record field".into()) } } fn required(&self, _: usize) -> bool { true } fn read(&mut self, _: usize, reader: &mut Reader<'_, '_>) -> Result<(), String> { self.value = Some(if self.typed { let mut payload = Payload::default(); reader.record(&mut payload)?; Value::Typed(payload) } else { Value::Raw(reader.json()?) }); Ok(()) } } async fn call(mut request: Request, typed: bool) -> Response { if let Err(error) = auth::require_components(&[], &[]).await { return api::auth_error(error); } if let Err(error) = api::upload::read_body(&mut request).await { return api::invalid_input(error); } let body = match api::Inputs::json_body(&request) { Ok(body) => body, Err(error) => return api::invalid_input(error), }; let mut arguments = Arguments { typed, value: None }; if let Err(error) = decode::read(body, &mut |reader| reader.record(&mut arguments)) { return api::invalid_input(api::InputError(error)); } let encoded = match arguments.value { Some(Value::Typed(payload)) => payload.encode(), Some(Value::Raw(value)) => Ok(value), None => Err("missing required wire field".into()), }; match encoded { Ok(value) => { if api::commit_response_metadata().is_err() { return api::internal_error(); } api::success(value) } Err(_) => api::internal_error(), } } async fn route(request: Request) -> Result { let typed = match request.target.split('?').next().unwrap_or("") { "/benchmark/echo/echo" => true, "/benchmark/echo/raw" => false, _ => return Ok(api::not_found()), }; if request.method != "POST" { return Ok(api::method_not_allowed(&["POST"])); } let prepared = match auth::prepare(&[], &request, true) { Ok(prepared) => prepared, Err(error) => return Ok(api::auth_error(error)), }; let identity = prepared.claims().map(|claims| auth::Identity { id: claims.subject.clone(), user_id: None, tenant_id: None, }); Ok( match auth::scope(prepared, identity, call(request, typed)).await { Ok(response) => response, Err(error) => api::auth_error(error), }, ) } fn main() -> Result<(), String> { let session = Session::load( RuntimeProfile { sqlite: true, postgres: false, }, &[(None, "benchmark", false)], &[], )?; session.initialize_authorization(false)?; let cleanup = session.clone(); task::run_entry_with_typed_cleanup( task::RuntimeConfig::default(), session.clone().scope(async move { session .databases() .prepare() .await .map_err(|error| error.to_string())?; lifecycle::configure(true, false)?; lifecycle::run(api::serve(route)).await }), |result| async move { let closed = cleanup.close().await; result.and(closed) }, ) }