// Code generated by ndpgen. DO NOT EDIT. // // This file contains client wrappers for the {{.Service.Name}} host service. // It is intended for use in Navidrome plugins built with extism-pdk. use extism_pdk::*; use serde::{Deserialize, Serialize}; {{- /* Generate struct definitions */ -}} {{- range .Service.Structs}} {{if .Doc}} {{rustDocComment .Doc}} {{else}} {{end}}#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct {{.Name}} { {{- range .Fields}} {{- if .NeedsDefault}} #[serde(default)] {{- end}} pub {{.RustName}}: {{fieldRustType .}}, {{- end}} } {{- end}} {{- /* Generate request/response types */ -}} {{- range .Service.Methods}} {{- if .HasParams}} #[derive(Debug, Clone, Serialize)] #[serde(rename_all = "camelCase")] struct {{requestType .}} { {{- range .Params}} {{.RustName}}: {{rustType .}}, {{- end}} } {{- end}} {{- if not .Raw}} #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] struct {{responseType .}} { {{- range .Returns}} #[serde(default)] {{.RustName}}: {{rustType .}}, {{- end}} {{- if .HasError}} #[serde(default)] error: Option, {{- end}} } {{- end}} {{- end}} #[host_fn] extern "ExtismHost" { {{- range .Service.Methods}} {{- if not .Raw}} fn {{exportName .}}(input: Json<{{if .HasParams}}{{requestType .}}{{else}}serde_json::Value{{end}}>) -> Json<{{responseType .}}>; {{- end}} {{- end}} } {{- /* Declare raw extern "C" imports for raw methods */ -}} {{- range .Service.Methods}} {{- if .Raw}} #[link(wasm_import_module = "extism:host/user")] extern "C" { fn {{exportName .}}(offset: u64) -> u64; } {{- end}} {{- end}} {{- /* Generate wrapper functions */ -}} {{range .Service.Methods}} {{- if .Raw}} {{if .Doc}}{{rustDocComment .Doc}}{{else}}/// Calls the {{exportName .}} host function.{{end}} {{- if .HasParams}} /// /// # Arguments {{- range .Params}} /// * `{{.RustName}}` - {{rustType .}} parameter. {{- end}} {{- end}} /// /// # Returns /// A tuple of (content_type, data) with the raw binary response. /// /// # Errors /// Returns an error if the host function call fails. pub fn {{rustFunc .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.RustName}}: {{rustParamType $p}}{{end}}) -> Result<(String, Vec), Error> { {{- if .HasParams}} let req = {{requestType .}} { {{- range .Params}} {{.RustName}}: {{.RustName}}{{if .NeedsToOwned}}.to_owned(){{end}}, {{- end}} }; let input_bytes = serde_json::to_vec(&req).map_err(|e| Error::msg(e.to_string()))?; {{- else}} let input_bytes = b"{}".to_vec(); {{- end}} let input_mem = Memory::from_bytes(&input_bytes).map_err(|e| Error::msg(e.to_string()))?; let response_offset = unsafe { {{exportName .}}(input_mem.offset()) }; let response_mem = Memory::find(response_offset) .ok_or_else(|| Error::msg("empty response from host"))?; let response_bytes = response_mem.to_vec(); if response_bytes.is_empty() { return Err(Error::msg("empty response from host")); } if response_bytes[0] == 0x01 { let msg = String::from_utf8_lossy(&response_bytes[1..]).to_string(); return Err(Error::msg(msg)); } if response_bytes[0] != 0x00 { return Err(Error::msg("unknown response status")); } if response_bytes.len() < 5 { return Err(Error::msg("malformed raw response: incomplete header")); } let ct_len = u32::from_be_bytes([ response_bytes[1], response_bytes[2], response_bytes[3], response_bytes[4], ]) as usize; if ct_len > response_bytes.len() - 5 { return Err(Error::msg("malformed raw response: content-type overflow")); } let ct_end = 5 + ct_len; let content_type = String::from_utf8_lossy(&response_bytes[5..ct_end]).to_string(); let data = response_bytes[ct_end..].to_vec(); Ok((content_type, data)) } {{- else}} {{if .Doc}}{{rustDocComment .Doc}}{{else}}/// Calls the {{exportName .}} host function.{{end}} {{- if .HasParams}} /// /// # Arguments {{- range .Params}} /// * `{{.RustName}}` - {{rustType .}} parameter. {{- end}} {{- end}} {{- if .HasReturns}} /// /// # Returns {{- if .IsOptionPattern}} /// `Some({{(index .Returns 0).RustName}})` if found, `None` otherwise. {{- else if eq (len .Returns) 1}} /// The {{(index .Returns 0).RustName}} value. {{- else}} /// A tuple of ({{range $i, $r := .Returns}}{{if $i}}, {{end}}{{$r.RustName}}{{end}}). {{- end}} {{- end}} /// /// # Errors /// Returns an error if the host function call fails. {{- if .IsOptionPattern}} pub fn {{rustFunc .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.RustName}}: {{rustParamType $p}}{{end}}) -> Result, Error> { let response = unsafe { {{- if .HasParams}} {{exportName .}}(Json({{requestType .}} { {{- range .Params}} {{.RustName}}: {{.RustName}}{{if .NeedsToOwned}}.to_owned(){{end}}, {{- end}} }))? {{- else}} {{exportName .}}(Json(serde_json::json!({})))? {{- end}} }; {{if .HasError}} if let Some(err) = response.0.error { return Err(Error::msg(err)); } {{end}} if response.0.{{(index .Returns 1).RustName}} { Ok(Some(response.0.{{(index .Returns 0).RustName}})) } else { Ok(None) } } {{- else}} pub fn {{rustFunc .}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.RustName}}: {{rustParamType $p}}{{end}}) -> Result<{{if eq (len .Returns) 0}}(){{else if eq (len .Returns) 1}}{{rustType (index .Returns 0)}}{{else}}({{range $i, $r := .Returns}}{{if $i}}, {{end}}{{rustType $r}}{{end}}){{end}}, Error> { let response = unsafe { {{- if .HasParams}} {{exportName .}}(Json({{requestType .}} { {{- range .Params}} {{.RustName}}: {{.RustName}}{{if .NeedsToOwned}}.to_owned(){{end}}, {{- end}} }))? {{- else}} {{exportName .}}(Json(serde_json::json!({})))? {{- end}} }; {{if .HasError}} if let Some(err) = response.0.error { return Err(Error::msg(err)); } {{end}} {{- if eq (len .Returns) 0}} Ok(()) {{- else if eq (len .Returns) 1}} Ok(response.0.{{(index .Returns 0).RustName}}) {{- else}} Ok(({{range $i, $r := .Returns}}{{if $i}}, {{end}}response.0.{{$r.RustName}}{{end}})) {{- end}} } {{- end}} {{- end}} {{- end}}