Write new parser/formatters for Values/IndexableValues

This commit is contained in:
Yuriy Dupyn 2024-02-01 15:50:19 +01:00
parent 6b93452d3e
commit d4a941a738

View file

@ -179,16 +179,134 @@ impl Value {
} }
} }
// ===formatting===
fn db_type_to_string(type_: DbType) -> String {
match type_ {
DbType::String => format!("String()"),
DbType::Int => format!("Int()"),
DbType::Number => format!("Number()"),
DbType::Uuid => format!("Uuid()"),
DbType::Option(type_) => format!("Option({})", db_type_to_string(*type_)),
}
}
fn indexable_value_to_string(value: IndexableValue) -> String { fn indexable_value_to_string(value: IndexableValue) -> String {
match value { match value {
IndexableValue::String(s) => format!("String({s})"), IndexableValue::String(s) => format!("String({s})"),
IndexableValue::Int(i) => format!("Int({i})"), IndexableValue::Int(i) => format!("Int({i})"),
IndexableValue::Uuid(u) => format!("Uuid({u})"), IndexableValue::Uuid(u) => format!("Uuid({u})"),
IndexableValue::Some(val) => todo!(), IndexableValue::Some(val) => format!("Some({})", indexable_value_to_string(*val)),
IndexableValue::None(type_) => "None()".to_string(), IndexableValue::None(_type_) => "None()".to_string(),
} }
} }
fn value_to_string(value: Value) -> String {
match value {
Value::Number(x) => format!("Number({x})"),
Value::String(s) => format!("String({s})"),
Value::Int(i) => format!("Int({i})"),
Value::Uuid(u) => format!("Uuid({u})"),
Value::Some(val) => format!("Some({})", value_to_string(*val)),
Value::None(_type_) => "None()".to_string(),
}
}
// ===parsing===
fn parse_db_type(str: &str) -> Result<DbType, String> {
if !str.ends_with(')') {
return Err(format!("Invalid DbType: {}", str));
}
if str.starts_with("String(") {
Ok(DbType::String)
} else if str.starts_with("Int(") {
Ok(DbType::Int)
} else if str.starts_with("Number(") {
Ok(DbType::Number)
} else if str.starts_with("Uuid(") {
Ok(DbType::Uuid)
} else if str.starts_with("Option(") {
let s = &str[7..str.len() - 1];
Ok(DbType::Option(Box::new(parse_db_type(s)?)))
} else {
Err(format!("Invalid DbType: {}", str))
}
}
fn parse_value(str: &str) -> Result<Value, String> {
if !str.ends_with(')') {
return Err(format!("Invalid IndexableValue: {}", str));
}
if str.starts_with("Number(") {
let s = str[7..str.len() - 1].to_string();
let n = s
.parse::<f64>()
.map_err(|e| format!("Invalid Number: {}", e))?;
Ok(Value::Number(n))
} else if str.starts_with("String(") {
let s = str[7..str.len() - 1].to_string();
Ok(Value::String(s))
} else if str.starts_with("Int(") {
let s = str[4..str.len() - 1].to_string();
let i = s
.parse::<u64>()
.map_err(|e| format!("Invalid Int: {}", e))?;
Ok(Value::Int(i))
} else if str.starts_with("Uuid(") {
let s = str[5..str.len() - 1].to_string();
let u = s
.parse::<u64>()
.map_err(|e| format!("Invalid UUID: {}", e))?;
Ok(Value::Uuid(u))
} else if str.starts_with("Some(") {
let s = str[5..str.len() - 1].to_string();
let val: Value = parse_value(&s)?;
Ok(Value::Some(Box::new(val)))
} else if str.starts_with("None(") {
let s = str[5..str.len() - 1].to_string();
let type_: DbType = TryFrom::try_from(s)?;
Ok(Value::None(type_))
} else {
Err(format!("Invalid IndexableValue: {}", str))
}
}
fn parse_indexable_value(str: &str) -> Result<IndexableValue, String> {
if !str.ends_with(')') {
return Err(format!("Invalid IndexableValue: {}", str));
}
if str.starts_with("String(") {
let s = str[7..str.len() - 1].to_string();
Ok(IndexableValue::String(s))
} else if str.starts_with("Int(") {
let s = str[4..str.len() - 1].to_string();
let i = s
.parse::<u64>()
.map_err(|e| format!("Invalid Int: {}", e))?;
Ok(IndexableValue::Int(i))
} else if str.starts_with("Uuid(") {
let s = str[5..str.len() - 1].to_string();
let u = s
.parse::<u64>()
.map_err(|e| format!("Invalid UUID: {}", e))?;
Ok(IndexableValue::Uuid(u))
} else if str.starts_with("Some(") {
let s = str[5..str.len() - 1].to_string();
let val: IndexableValue = parse_indexable_value(&s)?;
Ok(IndexableValue::Some(Box::new(val)))
} else if str.starts_with("None(") {
let s = str[5..str.len() - 1].to_string();
let type_: DbType = parse_db_type(&s)?;
Ok(IndexableValue::None(type_))
} else {
Err(format!("Invalid IndexableValue: {}", str))
}
}
// Own string serialization so enums can be used as keys in maps // Own string serialization so enums can be used as keys in maps
impl From<IndexableValue> for String { impl From<IndexableValue> for String {
fn from(value: IndexableValue) -> Self { fn from(value: IndexableValue) -> Self {
@ -196,71 +314,37 @@ impl From<IndexableValue> for String {
} }
} }
impl TryFrom<String> for IndexableValue { impl From<DbType> for String {
type Error = String; fn from(type_: DbType) -> Self {
fn try_from(value: String) -> Result<Self, Self::Error> { db_type_to_string(type_)
if !value.ends_with(')') {
return Err(format!("Invalid IndexableValue: {}", value));
}
if value.starts_with("String(") {
let s = value[7..value.len() - 1].to_string();
Ok(Self::String(s))
} else if value.starts_with("Int(") {
let s = value[4..value.len() - 1].to_string();
let i = s
.parse::<u64>()
.map_err(|e| format!("Invalid Int: {}", e))?;
Ok(Self::Int(i))
} else if value.starts_with("Uuid(") {
let s = value[5..value.len() - 1].to_string();
let u = s
.parse::<u64>()
.map_err(|e| format!("Invalid UUID: {}", e))?;
Ok(Self::Uuid(u))
} else if value.starts_with("Some(") {
// TODO: This needs some recursion
todo!()
} else if value.starts_with("None(") {
todo!()
} else {
Err(format!("Invalid IndexableValue: {}", value))
}
} }
} }
impl TryFrom<String> for DbType {
type Error = String;
fn try_from(str: String) -> Result<Self, Self::Error> {
parse_db_type(&str)
}
}
impl TryFrom<String> for IndexableValue {
type Error = String;
fn try_from(str: String) -> Result<Self, Self::Error> {
parse_indexable_value(&str)
}
}
impl From<Value> for String { impl From<Value> for String {
fn from(value: Value) -> Self { fn from(value: Value) -> Self {
// match value { value_to_string(value)
// Value::Number(n) => format!("Number({n})"),
// Value::Indexable(i) => format!("Indexable({})", String::from(i)),
// }
todo!()
} }
} }
impl TryFrom<String> for Value { impl TryFrom<String> for Value {
type Error = String; type Error = String;
fn try_from(value: String) -> Result<Self, Self::Error> { fn try_from(value: String) -> Result<Self, Self::Error> {
if !value.ends_with(')') { parse_value(&value)
return Err(format!("Invalid Value: {}", value));
}
// if value.starts_with("Number(") {
// let s = value[7..value.len() - 1].to_string();
// let n = s
// .parse::<f64>()
// .map_err(|e| format!("Invalid Number: {}", e))?;
// Ok(Self::Number(n))
// } else if value.starts_with("Indexable(") {
// let s = value[10..value.len() - 1].to_string();
// let i = IndexableValue::try_from(s)?;
// Ok(Self::Indexable(i))
// } else {
// Err(format!("Invalid Value: {}", value))
// }
todo!()
} }
} }