Fix some things

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2025-02-08 15:45:21 +01:00
parent 6b1e799d6b
commit e600807376
10 changed files with 421 additions and 81 deletions

View file

@ -8,6 +8,7 @@ license.workspace = true
[dependencies]
camino = { version = "1.1.9", features = ["serde", "serde1"] }
clap = { version = "4.5.27", features = ["derive"] }
filesystem-trustfall-adapter = { version = "0.1.1", path = "../../../trustfall-adapters-zimbopro/filesystem-trustfall-adapter" }
futures = "0.3.31"
human-panic = "2.0.2"
jiff = "0.1.28"

View file

@ -8,8 +8,10 @@ use camino::Utf8PathBuf;
use clap::Parser;
use clap::Subcommand;
use clap::ValueHint;
use filesystem_trustfall_adapter::FileSystemAdapter;
use human_panic::Metadata;
use miette::IntoDiagnostic;
use parsing::Definition;
use parsing::Record;
use tracing::info;
use tracing_subscriber::EnvFilter;
@ -64,7 +66,7 @@ async fn main() -> miette::Result<()> {
let records = parsing::load_records(root_folder, &definitions).await?;
let schema = trustfall_plaixt::to_schema(&definitions);
let (schema, adapter) = get_schema_and_adapter(&definitions, records.clone());
match args.mode {
ArgMode::Query => {
@ -75,13 +77,9 @@ async fn main() -> miette::Result<()> {
let result = execute_query(
&schema,
Arc::new(trustfall_plaixt::TrustfallMultiAdapter {
plaixt: trustfall_plaixt::PlaixtAdapter {
records: records.clone(),
},
}),
Arc::new(adapter),
&query,
BTreeMap::<Arc<str>, FieldValue>::from([("search".into(), "trust".into())]),
BTreeMap::<Arc<str>, FieldValue>::from([]),
)
.unwrap()
.collect::<Vec<_>>();
@ -96,6 +94,20 @@ async fn main() -> miette::Result<()> {
Ok(())
}
fn get_schema_and_adapter(
definitions: &BTreeMap<String, Vec<Definition>>,
records: Vec<Record>,
) -> (trustfall::Schema, trustfall_plaixt::TrustfallMultiAdapter) {
let schema = trustfall_plaixt::to_schema(definitions);
let adapter = trustfall_plaixt::TrustfallMultiAdapter {
plaixt: trustfall_plaixt::PlaixtAdapter {
records: records.clone(),
},
filesystem: FileSystemAdapter::new(),
};
(schema, adapter)
}
fn print_records(records: &[Record]) {
for record in records {
println!("{kind} @ {at} {{", kind = record.kind, at = record.at);
@ -105,3 +117,37 @@ fn print_records(records: &[Record]) {
println!("}}")
}
}
#[cfg(test)]
mod tests {
use camino::Utf8PathBuf;
use tracing_subscriber::EnvFilter;
use trustfall::provider::check_adapter_invariants;
use crate::get_schema_and_adapter;
use crate::parsing;
#[tokio::test]
async fn ensure_adapter_satisfies_invariants() {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.pretty()
.with_test_writer()
.init();
let root_folder = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../examples");
println!("{root_folder}");
let definitions = parsing::load_definitions(&root_folder.join("definitions"))
.await
.unwrap();
let records = parsing::load_records(&root_folder, &definitions)
.await
.unwrap();
let (schema, adapter) = get_schema_and_adapter(&definitions, records.clone());
check_adapter_invariants(&schema, adapter);
}
}

View file

@ -15,6 +15,8 @@ use miette::NamedSource;
use owo_colors::OwoColorize;
use tokio_stream::wrappers::ReadDirStream;
use crate::trustfall_plaixt::ADAPTER_SEP;
#[derive(Debug, Clone)]
pub struct Record {
pub(crate) kind: String,
@ -156,6 +158,7 @@ pub(crate) async fn load_records(
#[derive(Debug)]
pub enum DefinitionKind {
String,
Path,
OneOf(Vec<String>),
}
@ -163,6 +166,7 @@ impl DefinitionKind {
pub(crate) fn trustfall_kind(&self) -> String {
match self {
DefinitionKind::String => String::from("String"),
DefinitionKind::Path => format!("fs{ADAPTER_SEP}Path"),
DefinitionKind::OneOf(_vecs) => String::from("String"),
}
}
@ -173,6 +177,10 @@ impl DefinitionKind {
.is_string()
.then_some(())
.ok_or("Expected a string here".to_string()),
DefinitionKind::Path => val
.is_string()
.then_some(())
.ok_or("Expected a path encoded as a string here".to_string()),
DefinitionKind::OneOf(options) => val
.as_string()
.is_some_and(|val| options.iter().any(|o| o == val))
@ -187,6 +195,7 @@ impl TryFrom<&str> for DefinitionKind {
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.to_ascii_lowercase().as_str() {
"string" => Ok(DefinitionKind::String),
"path" => Ok(DefinitionKind::Path),
other => miette::bail!("Did not recognize valid field kind: \"{other}\""),
}
}

View file

@ -19,7 +19,7 @@ use trustfall::Schema;
use crate::parsing::Definition;
use crate::parsing::Record;
const ADAPTER_SEP: &str = "__";
pub(crate) const ADAPTER_SEP: &str = "__";
#[derive(Debug, Default)]
pub struct StartingVertex {
@ -155,12 +155,29 @@ pub(crate) fn to_schema(definitions: &BTreeMap<String, Vec<Definition>>) -> Sche
{}
type RootSchemaQuery {{
{roots}
fs{ADAPTER_SEP}Path(path: String!): fs{ADAPTER_SEP}Path!,
}}
interface Record {{
at: String!,
kind: String!,
}}
interface fs{ADAPTER_SEP}Path {{
path: String!
}}
type fs{ADAPTER_SEP}Folder implements fs{ADAPTER_SEP}Path {{
path: String!
children: [fs{ADAPTER_SEP}Path!]
}}
type fs{ADAPTER_SEP}File implements fs{ADAPTER_SEP}Path {{
path: String!
size: Int!
extension: String!
Hash: String!
}}
{types}
"#,
Schema::ALL_DIRECTIVE_DEFINITIONS,
@ -179,11 +196,23 @@ pub(crate) fn to_schema(definitions: &BTreeMap<String, Vec<Definition>>) -> Sche
pub struct TrustfallMultiAdapter {
pub plaixt: PlaixtAdapter,
pub filesystem: filesystem_trustfall_adapter::FileSystemAdapter,
}
#[derive(Debug, Clone)]
pub enum TrustfallMultiVertex {
Plaixt(PlaixtVertex),
Filesystem(filesystem_trustfall_adapter::vertex::Vertex),
}
impl AsVertex<filesystem_trustfall_adapter::vertex::Vertex> for TrustfallMultiVertex {
fn as_vertex(&self) -> Option<&filesystem_trustfall_adapter::vertex::Vertex> {
self.as_filesystem()
}
fn into_vertex(self) -> Option<filesystem_trustfall_adapter::vertex::Vertex> {
self.as_filesystem().cloned()
}
}
impl AsVertex<PlaixtVertex> for TrustfallMultiVertex {
@ -204,6 +233,20 @@ impl TrustfallMultiVertex {
None
}
}
pub fn as_filesystem(
&self,
) -> Option<
&<filesystem_trustfall_adapter::FileSystemAdapter as trustfall::provider::Adapter<
'static,
>>::Vertex,
> {
if let Self::Filesystem(v) = self {
Some(v)
} else {
None
}
}
}
impl<'v> Adapter<'v> for TrustfallMultiAdapter {
@ -217,7 +260,11 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
) -> trustfall::provider::VertexIterator<'v, Self::Vertex> {
let (adapter_name, edge_name) = edge_name.split_once(ADAPTER_SEP).unwrap();
trace!(?adapter_name, ?edge_name, "Got start vertex");
trace!(
?adapter_name,
?edge_name,
"resolving top-level starting vertex"
);
match adapter_name {
"Plaixt" => {
@ -229,6 +276,18 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
Box::new(iter.map(TrustfallMultiVertex::Plaixt))
}
"fs" => {
let iter = self.filesystem.resolve_starting_vertices(
&Arc::from(edge_name),
parameters,
resolve_info,
);
Box::new(
iter.inspect(|v| trace!(?v, "Got vertex"))
.map(TrustfallMultiVertex::Filesystem),
)
}
_ => unreachable!(),
}
}
@ -243,7 +302,10 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
where
V: trustfall::provider::AsVertex<Self::Vertex> + 'v,
{
let (adapter_name, type_name) = type_name.split_once(ADAPTER_SEP).unwrap();
trace!(?type_name, ?property_name, "resolving top-level property");
let (adapter_name, type_name) = type_name
.split_once(ADAPTER_SEP)
.unwrap_or(("Plaixt", type_name));
match adapter_name {
"Plaixt" => {
@ -268,6 +330,29 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
.map(|((_ctx, name), og_ctx)| (og_ctx, name)),
)
}
"fs" => {
let contexts = contexts.collect::<Vec<_>>();
let properties = self.filesystem.resolve_property(
Box::new(
contexts
.clone()
.into_iter()
.map(|v| v.flat_map(&mut |v: V| v.into_vertex()))
.inspect(|v| trace!(?v, "Got vertex")),
),
&Arc::from(type_name),
property_name,
resolve_info,
);
Box::new(
properties
.into_iter()
.zip(contexts)
.map(|((_ctx, name), og_ctx)| (og_ctx, name)),
)
}
_ => unreachable!(),
}
}
@ -284,6 +369,7 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
V,
trustfall::provider::VertexIterator<'v, Self::Vertex>,
> {
trace!(?type_name, ?edge_name, "Resolving top-level neighbor");
let (adapter_name, type_name) = type_name.split_once(ADAPTER_SEP).unwrap();
match adapter_name {
@ -315,6 +401,37 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
}),
)
}
"fs" => {
let contexts = contexts.collect::<Vec<_>>();
let properties = self.filesystem.resolve_neighbors(
Box::new(
contexts
.clone()
.into_iter()
.map(|v| v.flat_map(&mut |v: V| v.into_vertex())),
),
&Arc::from(type_name),
edge_name,
parameters,
resolve_info,
);
Box::new(
properties
.into_iter()
.zip(contexts)
.map(|((_ctx, vals), og_ctx)| {
(
og_ctx,
Box::new(
vals.inspect(|v| trace!(?v, "Got vertex"))
.map(TrustfallMultiVertex::Filesystem),
) as Box<_>,
)
}),
)
}
_ => unreachable!(),
}
}
@ -326,7 +443,7 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
coerce_to_type: &Arc<str>,
resolve_info: &trustfall::provider::ResolveInfo,
) -> trustfall::provider::ContextOutcomeIterator<'v, V, bool> {
trace!(?type_name, ?coerce_to_type, "Trying to coerce");
trace!(?type_name, ?coerce_to_type, "Top-level coerce");
let (adapter_name, coerce_to_type) = coerce_to_type.split_once(ADAPTER_SEP).unwrap();
match adapter_name {
@ -352,6 +469,30 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
.map(|((_ctx, val), og_ctx)| (og_ctx, val)),
)
}
"fs" => {
let contexts = contexts.collect::<Vec<_>>();
let properties = self.filesystem.resolve_coercion(
Box::new(
contexts
.clone()
.into_iter()
.map(|v| v.flat_map(&mut |v: V| v.into_vertex())),
),
type_name,
&Arc::from(coerce_to_type),
resolve_info,
);
let type_name = type_name.clone();
let coerce_to_type = coerce_to_type.to_string();
Box::new(properties.into_iter().zip(contexts).map(
move |((_ctx, allowed), og_ctx)| {
trace!(?allowed, ?type_name, ?coerce_to_type, "Allowed coercion?");
(og_ctx, allowed)
},
))
}
_ => unreachable!(),
}
}
@ -454,7 +595,7 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
fn resolve_neighbors<V: trustfall::provider::AsVertex<Self::Vertex> + 'a>(
&self,
contexts: trustfall::provider::ContextIterator<'a, V>,
_type_name: &Arc<str>,
type_name: &Arc<str>,
edge_name: &Arc<str>,
_parameters: &trustfall::provider::EdgeParameters,
_resolve_info: &trustfall::provider::ResolveEdgeInfo,
@ -463,6 +604,7 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
V,
trustfall::provider::VertexIterator<'a, Self::Vertex>,
> {
trace!(?type_name, ?edge_name, "Resolving neighbors");
match edge_name.as_ref() {
"fields" => resolve_neighbors_with(contexts, |c| {
Box::new(
@ -474,7 +616,8 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
.into_iter(),
)
}),
_ => unreachable!(),
_ => resolve_neighbors_with(contexts, |c| todo!()),
_ => unreachable!("Could not resolve {edge_name}"),
}
}