Skip to content

Instantly share code, notes, and snippets.

Created October 6, 2017 15:14
Show Gist options
  • Save anonymous/9d2535d71f997dba662e942b4b751aec to your computer and use it in GitHub Desktop.
Save anonymous/9d2535d71f997dba662e942b4b751aec to your computer and use it in GitHub Desktop.
Rust code shared from the playground
#![feature(try_from)]
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::convert::TryFrom;
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Double(f64),
Text(String),
}
#[derive(Debug)]
pub enum DaoError<'a, T>
where
T: TryFrom<&'a Value>,
<T as TryFrom<&'a Value>>::Error: Debug,
{
UglyConvertError(<T as TryFrom<&'a Value>>::Error), // this is ugly
ConvertError(ConvertError), // why can't it be wrapped into this?
NoSuchValueError(String),
}
#[derive(Debug)]
pub enum ConvertError {
NotSupported(String),
}
#[derive(Debug, PartialEq)]
pub struct Dao<'a>(BTreeMap<&'a str, Value>);
impl<'a> Dao<'a> {
pub fn new() -> Self {
Dao(BTreeMap::new())
}
pub fn insert<V>(&mut self, s: &'a str, v: V)
where
V: Into<Value>,
{
self.0.insert(s, v.into());
}
pub fn get<T>(&'a self, s: &str) -> Result<T, DaoError<T>>
where
T: TryFrom<&'a Value>,
<T as TryFrom<&'a Value>>::Error: Debug,
{
let value: Option<&'a Value> = self.0.get(s);
match value {
Some(v) => TryFrom::try_from(v).map_err(|e| DaoError::UglyConvertError(e)),
None => Err(DaoError::NoSuchValueError(s.into())),
}
}
/*
//I wanted a simpler Error signature, but this is erroneous
pub fn simpl_get<T>(&'a self, s: &str) -> Result<T, DaoError<T>>
where
T: TryFrom<&'a Value>
{
let value: Option<&'a Value> = self.0.get(s);
match value {
Some(v) => TryFrom::try_from(v).map_err(|e| DaoError::ConvertError(e)),
None => Err(DaoError::NoSuchValueError(s.into())),
}
}
*/
}
impl<'a> TryFrom<&'a Value> for f64 {
type Error = ConvertError;
fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
match *value {
Value::Double(v) => Ok(v),
_ => Err(ConvertError::NotSupported("can not convert to f64".into())),
}
}
}
impl<'a> TryFrom<&'a Value> for String {
type Error = ConvertError;
fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
match *value {
Value::Text(ref v) => Ok(v.to_owned()),
_ => Err(ConvertError::NotSupported(
"can not convert to String".into(),
)),
}
}
}
impl From<f64> for Value {
fn from(f: f64) -> Self {
Value::Double(f)
}
}
impl<'a> From<&'a str> for Value {
fn from(f: &str) -> Self {
Value::Text(f.to_owned())
}
}
fn main() {
let mut dao = Dao::new();
dao.insert("life", 42.0f64);
dao.insert("lemons", "lemonade");
let life: Result<f64, _> = dao.get("life");
println!("life: {:#?}", life);
assert!(life.is_ok());
if let Ok(life) = life {
assert_eq!(life, 42.0f64);
};
let lemons: Result<String, _> = dao.get("lemons");
println!("lemons?: {:#?}", lemons);
assert!(lemons.is_ok());
if let Ok(lemons) = lemons {
assert_eq!(lemons, "lemonade");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment