pub trait Adapter<'vertex> {
    type Vertex: Clone + Debug + 'vertex;

    // Required methods
    fn resolve_starting_vertices(
        &self,
        edge_name: &Arc<str>,
        parameters: &EdgeParameters,
        resolve_info: &ResolveInfo
    ) -> VertexIterator<'vertex, Self::Vertex>;
    fn resolve_property<V: AsVertex<Self::Vertex> + 'vertex>(
        &self,
        contexts: ContextIterator<'vertex, V>,
        type_name: &Arc<str>,
        property_name: &Arc<str>,
        resolve_info: &ResolveInfo
    ) -> ContextOutcomeIterator<'vertex, V, FieldValue>;
    fn resolve_neighbors<V: AsVertex<Self::Vertex> + 'vertex>(
        &self,
        contexts: ContextIterator<'vertex, V>,
        type_name: &Arc<str>,
        edge_name: &Arc<str>,
        parameters: &EdgeParameters,
        resolve_info: &ResolveEdgeInfo
    ) -> ContextOutcomeIterator<'vertex, V, VertexIterator<'vertex, Self::Vertex>>;
    fn resolve_coercion<V: AsVertex<Self::Vertex> + 'vertex>(
        &self,
        contexts: ContextIterator<'vertex, V>,
        type_name: &Arc<str>,
        coerce_to_type: &Arc<str>,
        resolve_info: &ResolveInfo
    ) -> ContextOutcomeIterator<'vertex, V, bool>;
}
Expand description

Trustfall data providers implement this trait to enable querying their data sets.

The most straightforward way to implement this trait is to use the trustfall_stubgen code-generator tool tool to auto-generate stubs customized to match your dataset’s schema, then fill in the blanks denoted by todo!().

If you prefer to implement the trait without code generation, consider implementing BasicAdapter instead. That’s a simpler version of this trait and can be faster to implement without a significant loss of functionality:

  • Both traits support the same set of queries. Under the hood, BasicAdapter itself implements Adapter.
  • If you need optimizations like batching or caching, you can implement them within BasicAdapter as well.
  • If you need more advanced optimizations such as predicate pushdown, or need to access Trustfall’s static analysis capabilities, implement this trait directly instead.

Required Associated Types§

source

type Vertex: Clone + Debug + 'vertex

The type of vertices in the dataset this adapter queries. Unless your intended vertex type is cheap to clone, consider wrapping it an Rc or Arc to make cloning it cheaper since that’s a fairly common operation when queries are evaluated.

Required Methods§

source

fn resolve_starting_vertices( &self, edge_name: &Arc<str>, parameters: &EdgeParameters, resolve_info: &ResolveInfo ) -> VertexIterator<'vertex, Self::Vertex>

Produce an iterator of vertices for the specified starting edge.

Starting edges are the entry points for querying according to a schema. Each query starts at such an edge, and such starting edges are defined directly on the root query type of the schema.

Example

Consider this query which gets the URLs of the posts currently on the front page of HackerNews: playground

query {
  FrontPage {
    url @output
  }
}

The HackerNews schema defines FrontPage as a starting edge that points to vertices of type Item.

As part of executing this query, Trustfall will call this method with edge_name = "FrontPage". Here’s the implementation of this method in the HackerNews example adapter.

Preconditions and postconditions

The caller guarantees that:

  • The specified edge is a starting edge in the schema being queried.
  • Any parameters the edge requires per the schema have values provided.
source

fn resolve_property<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, property_name: &Arc<str>, resolve_info: &ResolveInfo ) -> ContextOutcomeIterator<'vertex, V, FieldValue>

Resolve a property required by the query that’s being evaluated.

Each DataContext in the contexts parameter has an active vertex DataContext::active_vertex(). This call is asking for the value of the specified property on each such active vertex, for each active vertex in the input iterator.

The most ergonomic way to implement this method is usually via the resolve_property_with() helper method together with the field_property!() and accessor_property!() macros.

Example

Consider this query which gets the URLs of the posts currently on the front page of HackerNews: playground

query {
  FrontPage {
    url @output
  }
}

Our HackerNews schema defines FrontPage as a starting edge that points to vertices of type Item, and defines url as a property on the Item type.

As part of executing this query, Trustfall will call this method with type_name = "Item" and property_name = "url". This is how Trustfall looks up the URLs of the items returned by this query. Here’s the implementation of this method in the HackerNews example adapter.

Preconditions and postconditions

The active vertex may be None, or a Some(v) whose v is of Rust type &Self::Vertex and represents a vertex whose type in the Trustfall schema is given by this function’s type_name parameter.

The caller guarantees that:

  • type_name is a type or interface defined in the schema.
  • property_name is either a property field on type_name defined in the schema, or the special value "__typename" requesting the name of the vertex’s type.
  • When the active vertex is Some(...), its represents a vertex of type type_name: either its type is exactly type_name, or type_name is an interface implemented by the vertex’s type.

The returned iterator must satisfy these properties:

  • Produce (context, property_value) tuples with the property’s value for that context.
  • Produce contexts in the same order as the input contexts iterator produced them.
  • Produce property values whose type matches the property’s type defined in the schema.
  • When a context’s active vertex is None, its property value is FieldValue::Null.
source

fn resolve_neighbors<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, edge_name: &Arc<str>, parameters: &EdgeParameters, resolve_info: &ResolveEdgeInfo ) -> ContextOutcomeIterator<'vertex, V, VertexIterator<'vertex, Self::Vertex>>

Resolve the neighboring vertices across an edge.

Each DataContext in the contexts parameter has an active vertex DataContext::active_vertex(). This call is asking for the iterator of neighboring vertices of the active vertex along a specified edge, for each active vertex in the input iterator.

The most ergonomic way to implement this method is usually via the resolve_neighbors_with() helper method.

Example

Consider this query which gets the usernames and karma points of the users who submitted the latest stories on HackerNews: playground

query {
  Latest {
    byUser {
      id @output
      karma @output
    }
  }
}

Our HackerNews schema defines Latest as a starting edge that points to vertices of type Story. In turn, Story has an edge called byUser that points to User vertices.

As part of executing this query, Trustfall will call this method with type_name = "Story" and edge_name = "byUser". This is how Trustfall looks up the user vertices representing the submitters of the latest HackerNews stories. Here’s the implementation of this method in the HackerNews example adapter.

Preconditions and postconditions

The active vertex may be None, or a Some(v) whose v is of Rust type &Self::Vertex and represents a vertex whose type in the Trustfall schema is given by this function’s type_name parameter.

If the schema this adapter covers has no edges aside from starting edges, then this method will never be called and may be implemented as unreachable!().

The caller guarantees that:

  • type_name is a type or interface defined in the schema.
  • edge_name is an edge field on type_name defined in the schema.
  • Each parameter required by the edge has a value of appropriate type, per the schema.
  • When the active vertex is Some(...), its represents a vertex of type type_name: either its type is exactly type_name, or type_name is an interface implemented by the vertex’s type.

The returned iterator must satisfy these properties:

  • Produce (context, neighbors) tuples with an iterator of neighbor vertices for that edge.
  • Produce contexts in the same order as the input contexts iterator produced them.
  • Each neighboring vertex is of the type specified for that edge in the schema.
  • When a context’s active vertex is None, it has an empty neighbors iterator.
source

fn resolve_coercion<V: AsVertex<Self::Vertex> + 'vertex>( &self, contexts: ContextIterator<'vertex, V>, type_name: &Arc<str>, coerce_to_type: &Arc<str>, resolve_info: &ResolveInfo ) -> ContextOutcomeIterator<'vertex, V, bool>

Attempt to coerce vertices to a subtype, as required by the query that’s being evaluated.

Each DataContext in the contexts parameter has an active vertex DataContext::active_vertex(). This call is asking whether the active vertex happens to be an instance of a subtype, for each active vertex in the input iterator.

The most ergonomic ways to implement this method usually rely on the resolve_coercion_using_schema() or resolve_coercion_with() helper methods.

Example

Consider this query which gets the titles of all stories on the front page of HackerNews, while discarding non-story items such as job postings and polls: playground

query {
  FrontPage {
    ... on Story {
      title @output
    }
  }
}

Our HackerNews schema defines FrontPage as a starting edge that points to vertices of type Item. It also defines Story as a subtype of Item.

After resolving the FrontPage starting edge, Trustfall will need to determine which of the resulting Item vertices are actually of type Story. This is when Trustfall will call this method with type_name = "Item" and coerce_to_type = "Story". Here’s the implementation of this method in the HackerNews example adapter.

Preconditions and postconditions

The active vertex may be None, or a Some(v) whose v is of Rust type &Self::Vertex and represents a vertex whose type in the Trustfall schema is given by this function’s type_name parameter.

If this adapter’s schema contains no subtyping, then no type coercions are possible: this method will never be called and may be implemented as unreachable!().

The caller guarantees that:

  • type_name is an interface defined in the schema.
  • coerce_to_type is a type or interface that implements type_name in the schema.
  • When the active vertex is Some(...), its represents a vertex of type type_name: either its type is exactly type_name, or type_name is an interface implemented by the vertex’s type.

The returned iterator must satisfy these properties:

  • Produce (context, can_coerce) tuples showing if the coercion succeded for that context.
  • Produce contexts in the same order as the input contexts iterator produced them.
  • Each neighboring vertex is of the type specified for that edge in the schema.
  • When a context’s active vertex is None, its coercion outcome is false.

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<'a> Adapter<'a> for SchemaAdapter<'a>

§

type Vertex = SchemaVertex<'a>

source§

impl<'vertex, AdapterT> Adapter<'vertex> for AdapterTap<'vertex, AdapterT>where AdapterT: Adapter<'vertex>, AdapterT::Vertex: Clone + Debug + PartialEq + Eq + Serialize + DeserializeOwned + 'vertex,

§

type Vertex = <AdapterT as Adapter<'vertex>>::Vertex

source§

impl<'vertex, T> Adapter<'vertex> for Twhere T: BasicAdapter<'vertex>,

§

type Vertex = <T as BasicAdapter<'vertex>>::Vertex