basic implementation for EmoteMapper
[?]
8LW8624xwrzheYNE1i3XKqUsNUezeTo6cRFa6qrKJout
Oct 10, 2021, 9:42 PM
BK53SCKOZP5KD4QHQJWL4SOA543MT7JM7DTFNXQBM2IZK4UMUFOACDependencies
- [2]
6ON2OTNRinit
Change contents
- replacement in src/lib.rs at line 1
#[cfg(test)]mod tests {#[test]fn it_works() {assert_eq!(2 + 2, 4);use std::{collections::HashMap,convert::TryFrom,fmt::Display,fs::File,io::{Read, Write},path::Path,str::FromStr,};use csv::Trim;use serde::*;use serde_with::{serde_as, TryFromInto};use thiserror::Error;use EmoteMapperError::*;pub struct EmoteMapper {map: HashMap<String, CodePoint>,emote_width: usize,}impl Default for EmoteMapper {fn default() -> Self {Self {map: Default::default(),emote_width: 3,}}}impl EmoteMapper {pub fn emote_width(mut self, emote_width: usize) -> Self {self.emote_width = emote_width;self}pub fn to_char(&self, emote_name: &str) -> Option<char> {self.map.get(emote_name).copied().map(char::from)}pub fn to_string(&self, emote_name: &str) -> Option<String> {self.to_char(emote_name).map(|c| format!("{}{}", c, " ".repeat(self.emote_width - 1)))}}/// Parsingimpl EmoteMapper {pub fn from_reader(rdr: impl Read) -> Result<Self, EmoteMapperError> {let mut rdr = csv::ReaderBuilder::new().has_headers(false).trim(Trim::All).from_reader(rdr);let map = rdr.deserialize::<Mapping>().map(|r| {let r: Mapping = r.map_err(StringParsingError)?;Ok((r.name, r.code_point))}).collect::<Result<_, EmoteMapperError>>()?;Ok(EmoteMapper {map,..EmoteMapper::default()})}pub fn from_path(p: &Path) -> Result<Self, EmoteMapperError> {Self::from_reader(File::open(p).map_err(IOError)?)}}impl FromStr for EmoteMapper {type Err = EmoteMapperError;fn from_str(s: &str) -> Result<Self, Self::Err> {Self::from_reader(s.as_bytes())}}/// Savingimpl EmoteMapper {pub fn to_writer(self, wtr: impl Write) -> Result<(), EmoteMapperError> {let mut wtr = csv::WriterBuilder::new().has_headers(false).from_writer(wtr);for mapping in self.map.into_iter().map(Mapping::from) {wtr.serialize(mapping).unwrap();}wtr.flush().map_err(IOError)}pub fn to_path(self, p: &Path) -> Result<(), EmoteMapperError> {self.to_writer(File::open(p).map_err(IOError)?)}}impl From<EmoteMapper> for String {fn from(val: EmoteMapper) -> Self {let mut s = "".to_string();{val.to_writer(unsafe { s.as_mut_vec() }).expect("Writing to String should not fail");}s}}#[test]fn from_into_str() {let str = "testEmote,F4000\n";let em = EmoteMapper::from_str(str).unwrap();assert_eq!(em.map.get("testEmote").unwrap().0, '\u{F4000}');assert_eq!(String::from(em), str)}#[serde_as]#[derive(Debug, Deserialize, Serialize)]struct Mapping {name: String,#[serde_as(as = "TryFromInto<String>")]code_point: CodePoint,}impl From<(String, CodePoint)> for Mapping {fn from((name, code_point): (String, CodePoint)) -> Self {Mapping { name, code_point }}}#[derive(Error, Debug)]pub enum EmoteMapperError {#[error("codepoint is expected to be a hex number: `{0}`")]InvalidCodepoint(String),#[error("Parsing from string failed with:\n{0}")]StringParsingError(csv::Error),#[error("Failed due to IO-Error:\n{0}")]IOError(std::io::Error),}#[derive(Clone, Copy, Debug)]struct CodePoint(char);impl From<CodePoint> for char {fn from(cp: CodePoint) -> Self {cp.0}}impl Display for CodePoint {fn fmt(&self, f: &mut __private::Formatter<'_>) -> std::fmt::Result {char::from(*self).fmt(f)}}impl From<CodePoint> for String {fn from(val: CodePoint) -> Self {format!("{:X}", val.0 as u32)}}impl TryFrom<String> for CodePoint {type Error = EmoteMapperError;fn try_from(s: String) -> Result<Self, Self::Error> {Ok(CodePoint(char::from_u32(u32::from_str_radix(&s, 16).map_err(|_| InvalidCodepoint(s.to_string()))?,).ok_or_else(|| InvalidCodepoint(s.to_string()))?,)) - edit in Cargo.toml at line 9[2.361]
csv = "1.1.6"serde = { version = "1.0.130", features = ["derive"] }serde_with = { version = "1.10.0", features = ["hex"] }thiserror = "1.0.30"