01mf02 / jaq

A jq clone focussed on correctness, speed, and simplicity

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Example showing how to use jaq as a library is incomplete

kimjarvis opened this issue · comments

I would like to use the crate as a library. The example in the code comments of jaq-core/lib.rs does not compile.

15 |     let (f, errs) = jaq_parse::parse(filter, jaq_parse::main());
   |                     ^^^^^^^^^ use of undeclared crate or module `jaq_parse`

Also, the jaq crate combines the component crates into a workspace. It is not clear what I should put in my Cargo.toml file to use this crate as a library.

Happy to hear that you want to use jaq as a library.

The code that you are referring to is from the current development version on Git, which has a quite different API than the latest stable release (0.10.1).
Code for using the stable release can be found at: https://docs.rs/jaq-core/latest/jaq_core/

You can browse the source code for the stable release at: https://github.com/01mf02/jaq/tree/v0.10

And finally, your Cargo.toml should include the following entries to use jaq:

jaq-core = { version = "0.10.1" }
jaq-std  = { version = "0.10.0" }

I hope that this works for you.

Thank you for your guidance. I was able to get the example code in jaq-core/lib.rs to run. I checked out the jaq master branch. I added the path to these crates to my Cargo.toml file.

Cargo.toml

[dependencies]
serde_json = "1.0"
jaq-core = { path = "../jaq/jaq-core" }
jaq-parse = { path = "../jaq/jaq-parse" }

src/main.rs

use jaq_core::{Ctx, FilterT, ParseCtx, RcIter, Val};
use serde_json::{json};

fn main() {

    let input = json!(["Hello", "world"]);
    let filter = ".[]";

    // start out only from core filters,
    // which do not include filters in the standard library
    // such as `map`, `select` etc.
    let mut defs = ParseCtx::new(Vec::new());

    // parse the filter
    let (f, errs) = jaq_parse::parse(filter, jaq_parse::main());
    assert_eq!(errs, Vec::new());

    // compile the filter in the context of the given definitions
    let f = defs.compile(f.unwrap());
    assert!(defs.errs.is_empty());

    let inputs = RcIter::new(core::iter::empty());

    // iterator over the output values
    let mut out = f.run((Ctx::new([], &inputs), Val::from(input)));

    assert_eq!(out.next(), Some(Ok(Val::from(json!("Hello")))));
    assert_eq!(out.next(), Some(Ok(Val::from(json!("world")))));
    assert_eq!(out.next(), None);
}

@kimjarvis For anyone else viewing this thread it's now like this:

extern crate jaq_core;
extern crate jaq_interpret;
extern crate serde;

fn jq() {
    let input = serde_json::json!(["Hello", "world"]);
    let filter = ".[]";

    // start out only from core filters,
    // which do not include filters in the standard library
    // such as `map`, `select` etc.
    let mut defs = jaq_interpret::ParseCtx::new(Vec::new());

    // parse the filter
    let (f, errs) = jaq_parse::parse(filter, jaq_parse::main());
    assert_eq!(errs, Vec::new());

    // compile the filter in the context of the given definitions
    let f = defs.compile(f.unwrap());
    assert!(defs.errs.is_empty());

    let inputs = jaq_interpret::RcIter::new(core::iter::empty());

    // iterator over the output values
    let mut out = f.run((jaq_interpret::Ctx::new([], &inputs), jaq_interpret::Val::from(input)));

    assert_eq!(
        out.next(),
        Some(Ok(jaq_interpret::Val::from(serde_json::json!("Hello"))))
    );
    assert_eq!(
        out.next(),
        Some(Ok(jaq_interpret::Val::from(serde_json::json!("world"))))
    );
    assert_eq!(out.next(), None);
}

Given Cargo.toml with:

[dependencies]
serde = { version = "1.0.199", features = ["serde_derive"] }
serde_json = "1.0.116"
jaq-core = "1.2.1"
jaq-parse = "1.0.2"
jaq-std = "1.2.1"
jaq-interpret = "1.2.1"