/*! This is an `implementation crate`, It exports the root module(a struct of function pointers) required by the `example_0_interface`(the `interface crate`). */ use std::collections::HashSet; use abi_stable::{ export_root_module, sabi_extern_fn, external_types::crossbeam_channel::RSender, prefix_type::PrefixTypeTrait, sabi_trait::prelude::TU_Opaque, std_types::{RStr,RVec, RString,RResult,ROk}, }; use example_interface::{ AsyncCommand, ApplicationMut, CommandDescription, Error as AppError, Plugin,PluginType,PluginId,PluginMod,PluginMod_Ref, Plugin_TO, utils::process_command, }; use core_extensions::{SelfOps,StringExt}; use serde::{Serialize,Deserialize}; /////////////////////////////////////////////////////////////////////////////////// /// Exports the root module of this library. /// /// This code isn't run until the layout of the type it returns is checked. #[export_root_module] fn instantiate_root_module()->PluginMod_Ref{ PluginMod { new, }.leak_into_prefix() } ////////////////////////////////////////////////////////////////////////////////////// /// Instantiates the plugin. #[sabi_extern_fn] pub fn new(_sender:RSender,plugin_id:PluginId) -> RResult { let this=TextMunging{ plugin_id, }; ROk(Plugin_TO::from_value(this,TU_Opaque)) } ////////////////////////////////////////////////////////////////////////////////////// #[derive(Debug,Serialize,Deserialize)] pub enum ProcessTextCmd{ Rot13(String), CapitalizeWords{ text:String, words:HashSet }, } #[derive(Debug,Serialize,Deserialize)] pub enum ReturnValue{ Rot13(String), CapitalizeWords(String), } ////////////////////////////////////////////////////////////////////////////////////// fn run_command_inner( _this:&mut TextMunging, command:ProcessTextCmd, _app:ApplicationMut<'_>, )->Result{ match command { ProcessTextCmd::Rot13(text)=>{ pub fn rot13(this:char)-> char{ match this{ v@'a'..='z'=> ((((v as u8 - b'a')+13)%26)+b'a')as char, v@'A'..='Z'=> ((((v as u8 - b'A')+13)%26)+b'A')as char, v=>v } } text.chars() .map(rot13) .collect::() .piped(ReturnValue::Rot13) } ProcessTextCmd::CapitalizeWords{text,words}=>{ let mut buffer=String::with_capacity(10); for kv in text.split_while(|c|c.is_alphabetic()) { let str_=kv.str; let is_a_word=kv.key; if is_a_word && words.contains(str_) { buffer.extend(str_.chars().flat_map(char::to_uppercase)); }else{ buffer.push_str(str_); } } ReturnValue::CapitalizeWords(buffer) } }.piped(Ok) } ////////////////////////////////////////////////////////////////////////////////////// struct TextMunging{ plugin_id:PluginId, } impl Plugin for TextMunging { fn json_command( &mut self, command: RStr<'_>, app:ApplicationMut<'_>, )->RResult{ process_command(self,command,|this,command:ProcessTextCmd|{ run_command_inner(this,command,app) }) } fn plugin_id(&self)->&PluginId{ &self.plugin_id } fn list_commands(&self)->RVec{ vec![ CommandDescription::from_literals( "Rot13", "Uses the rot13 algorithm to hide spoilers in plain text." ), CommandDescription::from_literals( "CapitalizeWords", "Capitalizes the words specified in words.\n\ \n\ Command parans:\n\ {\"text\":\"text here\",words:[\"word0\",\"word1\"]}", ), ].into() } fn close(self,_app:ApplicationMut<'_>){} }