implement Serialize/Deserialize for Entry, Address, remove as_json
+ cosmetics (to_str -> to_string)feat/vaults
parent
99f6c6c052
commit
dc71bec67a
|
@ -1,14 +1,15 @@
|
|||
use crate::hash::{decode, encode, Hash};
|
||||
use anyhow::{anyhow, Result};
|
||||
use serde::de::Visitor;
|
||||
use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use unsigned_varint::encode;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::hash::{encode, Hash};
|
||||
use std::str::FromStr;
|
||||
use thiserror::private::DisplayAsDisplay;
|
||||
use unsigned_varint::encode;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Address {
|
||||
|
@ -57,6 +58,42 @@ impl Address {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serialize for Address {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(encode(self.encode().map_err(ser::Error::custom)?).as_str())
|
||||
}
|
||||
}
|
||||
|
||||
struct AddressVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for AddressVisitor {
|
||||
type Value = Address;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a valid UpEnd address (hash/UUID) as a multi-hashed string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, str: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let bytes = decode(str).map_err(de::Error::custom)?;
|
||||
Ok(Address::decode(bytes.as_ref()).map_err(de::Error::custom)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Address {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Address, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_str(AddressVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Address {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ use lexpr::value::Value::Symbol;
|
|||
use lexpr::Value::Cons;
|
||||
use log::{debug, trace};
|
||||
use nonempty::NonEmpty;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -23,34 +24,20 @@ use std::path::{Path, PathBuf};
|
|||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Entry {
|
||||
pub target: Address,
|
||||
pub key: String,
|
||||
pub value: EntryValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EntryValue {
|
||||
Value(serde_json::Value),
|
||||
Address(Address),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
pub fn as_json(&self) -> serde_json::Value {
|
||||
json!({
|
||||
"target": self.target.to_string(),
|
||||
"key": self.key,
|
||||
"value": match &self.value {
|
||||
EntryValue::Value(value) => ("VALUE", value.clone()),
|
||||
EntryValue::Address(address) => ("ADDR", json!(address.to_string())),
|
||||
EntryValue::Invalid => ("INVALID", json!("INVALID")),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<models::Entry> for Entry {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
@ -74,13 +61,13 @@ impl Hashable for Entry {
|
|||
let mut result = Cursor::new(vec![0u8; 0]);
|
||||
result.write_all(self.target.encode()?.as_slice())?;
|
||||
result.write_all(self.key.as_bytes())?;
|
||||
result.write_all(self.value.to_str()?.as_bytes())?;
|
||||
result.write_all(self.value.to_string()?.as_bytes())?;
|
||||
Ok(hash(result.get_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl EntryValue {
|
||||
pub fn to_str(&self) -> Result<String> {
|
||||
pub fn to_string(&self) -> Result<String> {
|
||||
let (type_char, content) = match self {
|
||||
EntryValue::Value(value) => ('J', serde_json::to_string(value)?),
|
||||
EntryValue::Address(address) => ('O', address.to_string()),
|
||||
|
@ -193,7 +180,7 @@ pub fn retrieve_object<C: Connection<Backend = Sqlite>>(
|
|||
|
||||
let matches = data
|
||||
.filter(target.eq(object_address.encode()?))
|
||||
.or_filter(value.eq(EntryValue::Address(object_address).to_str()?))
|
||||
.or_filter(value.eq(EntryValue::Address(object_address).to_string()?))
|
||||
.load::<models::Entry>(connection)?;
|
||||
let entries = matches
|
||||
.into_iter()
|
||||
|
@ -239,7 +226,7 @@ pub fn remove_object<C: Connection<Backend = Sqlite>>(
|
|||
|
||||
let matches = data
|
||||
.filter(target.eq(object_address.encode()?))
|
||||
.or_filter(value.eq(EntryValue::Address(object_address).to_str()?));
|
||||
.or_filter(value.eq(EntryValue::Address(object_address).to_string()?));
|
||||
|
||||
Ok(diesel::delete(matches).execute(connection)?)
|
||||
}
|
||||
|
@ -499,11 +486,11 @@ fn query_to_sqlite(query: &Query) -> Result<Box<Predicate>> {
|
|||
|
||||
match &eq.value {
|
||||
QueryComponent::Exact(q_value) => {
|
||||
subqueries.push(Box::new(data::value.eq(q_value.to_str()?)))
|
||||
subqueries.push(Box::new(data::value.eq(q_value.to_string()?)))
|
||||
}
|
||||
QueryComponent::In(q_values) => {
|
||||
let values: Result<Vec<_>, _> =
|
||||
q_values.iter().map(|v| v.to_str()).collect();
|
||||
q_values.iter().map(|v| v.to_string()).collect();
|
||||
subqueries.push(Box::new(data::value.eq_any(values?)))
|
||||
}
|
||||
QueryComponent::Contains(q_value) => {
|
||||
|
@ -583,9 +570,9 @@ pub fn query_entries<C: Connection<Backend = Sqlite>>(
|
|||
};
|
||||
|
||||
query = match entry_query.value {
|
||||
QueryComponent::Exact(q_value) => query.filter(value.eq(q_value.to_str()?)),
|
||||
QueryComponent::Exact(q_value) => query.filter(value.eq(q_value.to_string()?)),
|
||||
QueryComponent::In(q_values) => {
|
||||
let values: Result<Vec<_>, _> = q_values.into_iter().map(|v| v.to_str()).collect();
|
||||
let values: Result<Vec<_>, _> = q_values.into_iter().map(|v| v.to_string()).collect();
|
||||
query.filter(value.eq_any(values?))
|
||||
}
|
||||
QueryComponent::Contains(q_value_string) => {
|
||||
|
@ -617,7 +604,7 @@ pub fn insert_entry<C: Connection<Backend = Sqlite>>(
|
|||
identity: entry.hash()?.0,
|
||||
target: entry.target.encode()?,
|
||||
key: entry.key,
|
||||
value: entry.value.to_str()?,
|
||||
value: entry.value.to_string()?,
|
||||
};
|
||||
|
||||
Ok(diesel::insert_into(data::table)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use actix::prelude::*;
|
||||
use anyhow::{anyhow, Result};
|
||||
use filebuffer::FileBuffer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use tiny_keccak::{Hasher, KangarooTwelve};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Hash(pub Vec<u8>);
|
||||
|
||||
impl AsRef<[u8]> for Hash {
|
||||
|
|
|
@ -53,11 +53,11 @@ pub async fn get_object(
|
|||
|
||||
debug!("{:?}", response);
|
||||
|
||||
let mut result: HashMap<String, serde_json::Value> = HashMap::new();
|
||||
let mut result: HashMap<String, Entry> = HashMap::new();
|
||||
for entry in response.map_err(error::ErrorInternalServerError)? {
|
||||
result.insert(
|
||||
encode(entry.hash().map_err(ErrorInternalServerError)?),
|
||||
entry.as_json(),
|
||||
entry,
|
||||
);
|
||||
}
|
||||
Ok(HttpResponse::Ok().json(result))
|
||||
|
@ -90,12 +90,7 @@ pub async fn list_hier(
|
|||
.await
|
||||
.map_err(ErrorNotFound)?; // todo: 500 if actual error occurs
|
||||
|
||||
Ok(HttpResponse::Ok().json(
|
||||
entries
|
||||
.iter()
|
||||
.map(Entry::as_json)
|
||||
.collect::<serde_json::Value>(),
|
||||
))
|
||||
Ok(HttpResponse::Ok().json(entries))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -111,12 +106,7 @@ pub async fn get_lookup(
|
|||
let connection = state.db_pool.get().map_err(ErrorInternalServerError)?;
|
||||
let response = lookup_by_filename(&connection, info.query).map_err(ErrorInternalServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(
|
||||
response
|
||||
.iter()
|
||||
.map(Entry::as_json)
|
||||
.collect::<serde_json::Value>(),
|
||||
))
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -135,12 +125,7 @@ pub async fn get_query(
|
|||
let in_query = Query::from_sexp(&sexp).map_err(ErrorInternalServerError)?;
|
||||
let result = query(&connection, in_query).map_err(ErrorInternalServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(
|
||||
result
|
||||
.iter()
|
||||
.map(Entry::as_json)
|
||||
.collect::<serde_json::Value>(),
|
||||
))
|
||||
Ok(HttpResponse::Ok().json(result))
|
||||
}
|
||||
|
||||
#[post("/api/refresh")]
|
||||
|
|
Loading…
Reference in New Issue