use anyhow::Error; use futures_util::{SinkExt, StreamExt}; use giterated_models::{ messages::error::ConnectionError, model::{ authenticated::{Authenticated, AuthenticationSourceProvider}, instance::Instance, }, }; use serde::{de::DeserializeOwned, Serialize}; use tokio_tungstenite::tungstenite::Message; use crate::DaemonConnectionPool; pub fn request_local<'a, T: Serialize + DeserializeOwned>( request: &'a T, ) -> PreparedRequest<'a, T> { PreparedRequest { request: Authenticated::new_empty(request), instance: None, } } pub fn request<'a, T: Serialize + DeserializeOwned>( instance: &'a Instance, request: &'a T, ) -> PreparedRequest<'a, T> { PreparedRequest { request: Authenticated::new_empty(request), instance: Some(instance), } } pub struct PreparedRequest<'a, T: Serialize + DeserializeOwned> { instance: Option<&'a Instance>, request: Authenticated<&'a T>, } impl<'a, T: Serialize + DeserializeOwned> PreparedRequest<'a, T> { pub fn authenticate( mut self, source: &impl ToOwned, ) -> Self { self.request.append_authentication(source.to_owned()); self } pub async fn execute_expect( self, pool: &DaemonConnectionPool, ) -> Result { let mut socket = pool.0.get().await.unwrap(); let payload = serde_json::to_vec(&self.request).unwrap(); socket.send(Message::Binary(payload)).await?; while let Some(message) = socket.next().await { let payload = match message? { Message::Binary(payload) => payload, _ => { continue; } }; let as_target = serde_json::from_slice::(&payload).map_err(|e| Error::from(e)); if as_target.is_err() { // Maybe we got an error payload? if let Ok(error_payload) = serde_json::from_slice::(&payload) { return Err(error_payload.into()); } } else { // We did not get an error payload, forward the deserialization error from the // expected type return as_target; } } panic!() } }