Add monitor node for graph introspection

Adds a `serialize` function on Node which can be implemented by nodes to
allow introspecting their content. This pr also adds a Monitor Node that
always caches the last value it was evaluated with.

Test Plan: -

Reviewers: 0HyperCube

Reviewed By: 0HyperCube

Pull Request: https://github.com/GraphiteEditor/Graphite/pull/1165
This commit is contained in:
Dennis Kobert 2023-04-26 23:21:50 +02:00 committed by Keavon Chambers
parent 9cf93a9156
commit 271f9d5158
6 changed files with 41 additions and 8 deletions

View file

@ -1,9 +1,11 @@
use graphene_core::Node;
use serde::Serialize;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex;
use xxhash_rust::xxh3::Xxh3;
/// Caches the output of a given Node and acts as a proxy
@ -49,6 +51,37 @@ impl<T, CachedNode> CacheNode<T, CachedNode> {
}
}
/// Caches the output of the last graph evaluation for introspection
#[derive(Default)]
pub struct MonitorNode<T, CachedNode> {
output: Mutex<Option<T>>,
node: CachedNode,
}
impl<'i, T: 'i + Serialize + Clone, I: 'i + Hash, CachedNode: 'i> Node<'i, I> for MonitorNode<T, CachedNode>
where
CachedNode: for<'any_input> Node<'any_input, I, Output = T>,
{
type Output = T;
fn eval(&'i self, input: I) -> Self::Output {
let output = self.node.eval(input);
*self.output.lock().unwrap() = Some(output.clone());
output
}
fn serialize(&self) -> Option<String> {
let output = self.output.lock().unwrap();
(&*output).as_ref().map(|output| serde_json::to_string(output).ok()).flatten()
}
}
impl<T, CachedNode> std::marker::Unpin for MonitorNode<T, CachedNode> {}
impl<T, CachedNode> MonitorNode<T, CachedNode> {
pub const fn new(node: CachedNode) -> MonitorNode<T, CachedNode> {
MonitorNode { output: Mutex::new(None), node }
}
}
/// Caches the output of a given Node and acts as a proxy
/// It provides two modes of operation, it can either be set
/// when calling the node with a `Some<T>` variant or the last