pub trait ParcodeVisitor {
// Required methods
fn visit<'a>(
&'a self,
graph: &mut TaskGraph<'a>,
parent_id: Option<ChunkId>,
config_override: Option<JobConfig>,
);
fn create_job<'a>(
&'a self,
config_override: Option<JobConfig>,
) -> Box<dyn SerializationJob<'a> + 'a>;
// Provided methods
fn serialize_shallow<W: Write>(&self, writer: &mut W) -> Result<()>
where Self: Serialize { ... }
fn serialize_slice<W: Write>(slice: &[Self], writer: &mut W) -> Result<()>
where Self: Sized + Serialize { ... }
fn visit_inlined<'a>(
&'a self,
_graph: &mut TaskGraph<'a>,
_parent_id: ChunkId,
_config_override: Option<JobConfig>,
) { ... }
}Expand description
A trait for types that can be structurally visited to build a Parcode [TaskGraph].
This trait is the core abstraction for graph construction in Parcode. It allows types to define how they should be decomposed into nodes and how dependencies between nodes should be established.
§Relationship to Other Traits
serde::Serialize: Required for actual byte serialization (used bySerializationJob)ParcodeVisitor: Defines graph structure (this trait)SerializationJob: Executes the actual serialization of a node’s payloadParcodeNative: Defines deserialization strategy (reader-side)
§Automatic Implementation
This trait is typically implemented automatically via #[derive(ParcodeObject)]. Manual
implementation is only needed for custom serialization strategies.
§Thread Safety
Implementations must be Sync to support parallel graph execution. This is automatically
satisfied for most types.
Required Methods§
Sourcefn visit<'a>(
&'a self,
graph: &mut TaskGraph<'a>,
parent_id: Option<ChunkId>,
config_override: Option<JobConfig>,
)
fn visit<'a>( &'a self, graph: &mut TaskGraph<'a>, parent_id: Option<ChunkId>, config_override: Option<JobConfig>, )
Visits the object and populates the graph with nodes and dependencies.
This is the primary method for graph construction. It creates a node for the object, links it to its parent (if any), and recursively visits all remote children.
§Lifetimes
'a: The lifetime of the graph and the data being serialized. The object must outlive'ato enable zero-copy serialization (the graph holds references to the object’s data).
§Parameters
graph: The task graph being constructed. Nodes are added to this graph.parent_id: The ID of the parent node, if this object is a child of another node.Noneindicates this is the root object.config_override: Optional configuration to override default settings (e.g., compression).
§Behavior
- Creates a new node for this object using
create_job - Links the new node to the parent (if
parent_idisSome) - Recursively calls
visiton all remote children (chunkable/map fields)
§Example
use parcode::graph::TaskGraph;
use parcode::visitor::ParcodeVisitor;
let my_object = vec![1, 2, 3];
let mut graph = TaskGraph::new();
my_object.visit(&mut graph, None, None); // Root object, no parentSourcefn create_job<'a>(
&'a self,
config_override: Option<JobConfig>,
) -> Box<dyn SerializationJob<'a> + 'a>
fn create_job<'a>( &'a self, config_override: Option<JobConfig>, ) -> Box<dyn SerializationJob<'a> + 'a>
Creates the serialization job for this object.
This method returns a boxed SerializationJob that knows how to serialize the object’s
local fields (excluding remote children). The job will be executed later during graph
execution.
§Parameters
config_override: Optional configuration to apply to this job (e.g., compression settings).
§Returns
A boxed SerializationJob with lifetime 'a, allowing it to hold references to self.
§Implementation Note
The derive macro typically implements this by cloning self and wrapping it in a job.
For types with large local fields, consider implementing a custom job that holds references
instead of cloning.
Provided Methods§
Sourcefn serialize_shallow<W: Write>(&self, writer: &mut W) -> Result<()>where
Self: Serialize,
fn serialize_shallow<W: Write>(&self, writer: &mut W) -> Result<()>where
Self: Serialize,
Serializes only the local fields of this object (excluding chunkable/map fields).
This method is used when the object is part of a collection and its local data needs
to be serialized inline. Remote children are handled separately via visit_inlined.
§Default Implementation
The default implementation serializes the entire object using bincode. Types with chunkable fields should override this to serialize only local fields.
§Parameters
writer: The writer to serialize data into.
§Errors
Returns ParcodeError::Serialization if
serialization fails.
§Example
use parcode::error::Result;
use serde::Serialize;
#[derive(Serialize)]
struct MyStruct { local_field: i32 }
impl MyStruct {
// For a struct with local and remote fields:
fn serialize_shallow<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
// Only serialize local fields
parcode::internal::bincode::serde::encode_into_std_write(&self.local_field, writer, parcode::internal::bincode::config::standard()).map_err(|e| parcode::ParcodeError::Serialization(e.to_string()))?;
Ok(())
}
}Sourcefn serialize_slice<W: Write>(slice: &[Self], writer: &mut W) -> Result<()>
fn serialize_slice<W: Write>(slice: &[Self], writer: &mut W) -> Result<()>
Serializes a slice of objects.
This method is used to serialize collections of objects. The default implementation uses bincode to serialize the entire slice, which is efficient for types without chunkable fields.
§Override for Chunkable Types
Types with chunkable fields should override this method to:
- Serialize the slice length
- Call
serialize_shallowfor each element
This ensures that only local fields are serialized inline, while remote children
are handled via visit_inlined.
§Parameters
slice: The slice of objects to serialize.writer: The writer to serialize data into.
§Errors
Returns ParcodeError::Serialization if
serialization fails.
Sourcefn visit_inlined<'a>(
&'a self,
_graph: &mut TaskGraph<'a>,
_parent_id: ChunkId,
_config_override: Option<JobConfig>,
)
fn visit_inlined<'a>( &'a self, _graph: &mut TaskGraph<'a>, _parent_id: ChunkId, _config_override: Option<JobConfig>, )
Visits the object as an inlined item within a container (e.g., Vec).
In this mode, the object does NOT create a new node for itself, as its local data
is already serialized in the container’s payload (via serialize_shallow). However,
it must still visit its remote children (chunkable fields) and link them to the
container’s node.
§When is this called?
This method is called when:
- The object is an element in a
Vec<T>whereThas chunkable fields - The object is a value in a
HashMap<K, V>whereVhas chunkable fields
§Default Implementation
The default implementation does nothing, which is correct for types without chunkable fields. Types with chunkable fields must override this to visit their remote children.
§Parameters
graph: The task graph being constructed.parent_id: The ID of the container node (e.g., theVecnode).config_override: Optional configuration override.
§Example
use parcode::visitor::ParcodeVisitor;
use parcode::graph::{TaskGraph, ChunkId, JobConfig};
struct MyStruct { remote_field: Vec<u8> }
impl MyStruct {
// For a struct with a chunkable field:
fn visit_inlined<'a>(&'a self, graph: &mut TaskGraph<'a>, parent_id: ChunkId, config: Option<JobConfig>) {
// Visit remote children and link them to parent_id
self.remote_field.visit(graph, Some(parent_id), None);
}
}Note: Users deriving ParcodeObject do not need to implement this manually.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.