typed_graph 0.4.0

Staticly typed graph library
Documentation
use serde::de::{DeserializeOwned, Error};
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};

use crate::{EdgeExt, Id, Key, NodeExt, Typed};

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(bound = "K: DeserializeOwned + Serialize")]
#[serde(try_from = "Value")]
#[serde(into = "Value")]
pub struct AnyWeight<K: Key> {
    id: K,
    ty: String,
    data: Map<String, Value>,
}

impl<K: DeserializeOwned + Key> TryFrom<Value> for AnyWeight<K> {
    type Error = serde_json::Error;

    fn try_from(value: Value) -> Result<Self, Self::Error> {
        match value {
            Value::Object(o) => {
                if o.len() != 1 {
                    return Err(serde_json::Error::custom("expected type in object"));
                }

                let (ty, data) = o.into_iter().next().unwrap();

                let data = if let Value::Object(o) = data {
                    o
                } else {
                    return Err(serde_json::Error::custom("expected data to be object"));
                };
                let id_value = data
                    .get("id")
                    .ok_or_else(|| serde_json::Error::custom("expected id field"))?;

                let id = serde_json::from_value(id_value.clone())?;

                Ok(AnyWeight { id, ty, data })
            }
            _ => Err(serde_json::Error::custom("expected object")),
        }
    }
}

impl<K: Serialize + Key> Into<Value> for AnyWeight<K> {
    fn into(self) -> Value {
        let id = serde_json::to_value(self.id).unwrap();
        let mut out_data = self.data;
        out_data.insert("id".to_string(), id);

        let mut object = Map::new();
        object.insert(self.ty, Value::Object(out_data));

        Value::Object(object)
    }
}

impl<K: Key> PartialEq<String> for AnyWeight<K> {
    fn eq(&self, other: &String) -> bool {
        &self.ty == other
    }
}

impl<NK: Key> NodeExt<NK> for AnyWeight<NK> {}
impl<NK: Key> EdgeExt<NK> for AnyWeight<NK> {}

impl<NK: Key> Id<NK> for AnyWeight<NK> {
    fn get_id(&self) -> NK {
        self.id
    }

    fn set_id(&mut self, new_id: NK) {
        self.id = new_id;
    }
}

impl<NK: Key> Typed for AnyWeight<NK> {
    type Type = String;

    fn get_type(&self) -> Self::Type {
        self.ty.clone()
    }
}