1use bifrostlink::error::ErrorT;2use bifrostlink::{request, AddressT, Rpc};3use serde::{Deserialize, Serialize};45use crate::{Error, Prompter, Source};67pub struct BifrostPrompter<A: AddressT, E: ErrorT> {8 pub address: A,9 pub rpc: Rpc<A, E>,10}1112#[derive(Serialize, Deserialize)]13struct EnumRequest {14 prompt: String,15 description: String,16 variants: Vec<String>,17 source: Vec<Source>,18}19#[derive(Serialize, Deserialize)]20struct EnumResponse {21 value: u32,22}23request!(EnumRequest => EnumResponse);2425#[derive(Serialize, Deserialize)]26struct TextRequest {27 echo: bool,28 prompt: String,29 description: String,30 source: Vec<Source>,31}32#[derive(Serialize, Deserialize)]33struct TextResponse {34 value: String,35}36request!(TextRequest => TextResponse);3738#[derive(Serialize, Deserialize)]39struct DisplayRequest {40 error: bool,41 description: String,42 source: Vec<Source>,43}44request!(DisplayRequest => ());4546impl<A: AddressT, E: ErrorT> Prompter for BifrostPrompter<A, E>47where48 crate::Error: From<E>,49{50 async fn prompt_enum(51 &self,52 prompt: &str,53 description: &str,54 variants: &[&str],55 source: &[crate::Source],56 ) -> crate::Result<u32> {57 let res = self58 .rpc59 .request(60 self.address.clone(),61 &EnumRequest {62 prompt: prompt.to_owned(),63 description: description.to_owned(),64 variants: variants.into_iter().map(|v| (*v).to_owned()).collect(),65 source: source.to_vec(),66 },67 )68 .await?;69 Ok(res.value)70 }7172 async fn prompt_text(73 &self,74 echo: bool,75 prompt: &str,76 description: &str,77 source: &[crate::Source],78 ) -> crate::Result<String> {79 let res = self80 .rpc81 .request(82 self.address.clone(),83 &TextRequest {84 echo,85 prompt: prompt.to_owned(),86 description: description.to_owned(),87 source: source.to_vec(),88 },89 )90 .await?;91 Ok(res.value)92 }9394 async fn display_text(95 &self,96 error: bool,97 description: &str,98 source: &[crate::Source],99 ) -> crate::Result<()> {100 self.rpc101 .request(102 self.address.clone(),103 &DisplayRequest {104 error,105 description: description.to_owned(),106 source: source.to_vec(),107 },108 )109 .await?;110 Ok(())111 }112}113114pub fn handle_bifrost_prompts<115 P: Prompter + Clone + 'static,116 A: AddressT,117 E: ErrorT + From<Error>,118>(119 rpc: &Rpc<A, E>,120 prompt: P,121) {122 rpc.register_request_handler(true, {123 let prompt = prompt.clone();124 move |_addr, req: EnumRequest| {125 let prompt = prompt.clone();126 async move {127 let i = prompt128 .prompt_enum(129 &req.prompt,130 &req.description,131 &req.variants.iter().map(|v| v.as_str()).collect::<Vec<_>>(),132 &req.source,133 )134 .await?;135136 Ok(EnumResponse { value: i })137 }138 }139 });140 rpc.register_request_handler(true, {141 let prompt = prompt.clone();142 move |_addr, req: TextRequest| {143 let prompt = prompt.clone();144 async move {145 let i = prompt146 .prompt_text(req.echo, &req.prompt, &req.description, &req.source)147 .await?;148149 Ok(TextResponse { value: i })150 }151 }152 });153 rpc.register_request_handler(true, {154 let prompt = prompt.clone();155 move |_addr, req: DisplayRequest| {156 let prompt = prompt.clone();157 async move {158 prompt159 .display_text(req.error, &req.description, &req.source)160 .await?;161162 Ok(())163 }164 }165 });166}