-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Impl
TryFromJsonSyntax
for syntax::abs::Layout
.
- Loading branch information
1 parent
383646d
commit 6fd716b
Showing
20 changed files
with
1,608 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "tldr" | ||
description = "TreeLDR Distiller" | ||
version.workspace = true | ||
authors.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
|
||
[dependencies] | ||
treeldr-layouts.workspace = true | ||
clap = { workspace = true, features = ["derive"] } | ||
stderrlog.workspace = true | ||
json-syntax.workspace = true | ||
codespan-reporting.workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# TreeLDR Layouts | ||
|
||
<!-- cargo-rdme start --> | ||
|
||
TreeLDR's RDF Layouts are a powerful tool to map structured data to RDF datasets. | ||
This library provides core types to define layouts, an abstract syntax to | ||
describe layouts and "distillation" functions to serialize/deserialize data | ||
using layouts. | ||
|
||
## Basic usage | ||
|
||
The following example shows how to create a layout from its abstract syntax | ||
representation (using JSON), compile it and use it to serialize an RDF | ||
dataset into a structured value. | ||
|
||
```rust | ||
use static_iref::iri; | ||
use rdf_types::{Quad, Term, Literal, literal::Type}; | ||
use xsd_types::XSD_STRING; | ||
use serde_json::json; | ||
|
||
// Create a layout builder. | ||
let mut builder = treeldr_layouts::abs::Builder::new(); | ||
|
||
// Parse the layout definition, here from JSON. | ||
let layout: treeldr_layouts::abs::syntax::Layout = serde_json::from_value( | ||
json!({ | ||
"type": "record", | ||
"fields": { | ||
"id": { | ||
"value": { | ||
"layout": { "type": "id" }, | ||
"input": "_:self" | ||
} | ||
}, | ||
"name": { | ||
"value": { "type": "string" }, | ||
"property": "https://schema.org/name" | ||
} | ||
} | ||
}) | ||
).unwrap(); | ||
|
||
// Build the layout. | ||
let layout_ref = layout.build(&mut builder).unwrap(); // returns a `Ref` to the layout. | ||
|
||
// Get the compiled layouts collection. | ||
let layouts = builder.build(); | ||
|
||
// Create an RDF dataset with a single triple. | ||
let dataset: grdf::BTreeDataset = [ | ||
Quad( | ||
Term::iri(iri!("https://example.org/#john.smith").to_owned()), | ||
Term::iri(iri!("https://schema.org/name").to_owned()), | ||
Term::Literal(Literal::new("John Smith".to_owned(), Type::Any(XSD_STRING.to_owned()))), | ||
None | ||
) | ||
].into_iter().collect(); | ||
|
||
// Hydrate the dataset to get a structured data value. | ||
let value = treeldr_layouts::hydrate( | ||
&layouts, | ||
&dataset, | ||
&layout_ref, | ||
&[Term::iri(iri!("https://example.org/#john.smith").to_owned())] | ||
).unwrap().into_untyped(); // we don't care about types here. | ||
|
||
// Create a structured data value with the expected result. | ||
// Parse the layout definition, here from JSON. | ||
let expected: treeldr_layouts::Value = serde_json::from_value( | ||
json!({ | ||
"id": "https://example.org/#john.smith", | ||
"name": "John Smith" | ||
}) | ||
).unwrap(); | ||
|
||
// Check equality. | ||
assert_eq!(value, expected) | ||
``` | ||
|
||
## The `Layout` types | ||
|
||
Layouts come in several forms: | ||
- `abs::syntax::Layout`: represents a | ||
layout definition in the abstract syntax. In this representation | ||
variables have names and layouts can be nested. | ||
- `abs::Layout`: represents an abstract layout with | ||
stripped variable names and flattened layouts. These layouts are | ||
managed by the layout [`Builder`](https://docs.rs/treeldr-layouts/latest/treeldr_layouts/abs/struct.Builder.html). | ||
- `Layout`: the most optimized and compact form, used | ||
by the distillation functions. Such layouts are stored in a | ||
[`Layouts`](https://docs.rs/treeldr-layouts/latest/treeldr_layouts/struct.Layouts.html) collection. | ||
|
||
<!-- cargo-rdme end --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
use codespan_reporting::{ | ||
diagnostic::{Diagnostic, Label}, | ||
files::SimpleFiles, | ||
term::{ | ||
self, | ||
termcolor::{ColorChoice, StandardStream}, | ||
}, | ||
}; | ||
use std::{fs, path::PathBuf, process::ExitCode}; | ||
|
||
#[derive(clap::Parser)] | ||
#[clap(name="tldr", author, version, about, long_about = None)] | ||
struct Args { | ||
/// Input files. | ||
filenames: Vec<PathBuf>, | ||
|
||
/// Sets the level of verbosity. | ||
#[clap(short, long = "verbose", action = clap::ArgAction::Count)] | ||
verbosity: u8, | ||
} | ||
|
||
fn main() -> ExitCode { | ||
// Parse options. | ||
let args: Args = clap::Parser::parse(); | ||
|
||
// Initialize logger. | ||
stderrlog::new() | ||
.verbosity(args.verbosity as usize) | ||
.init() | ||
.unwrap(); | ||
|
||
let mut files = SimpleFiles::new(); | ||
|
||
for filename in args.filenames { | ||
match fs::read_to_string(&filename) { | ||
Ok(content) => { | ||
let file_id = files.add(filename.to_string_lossy().into_owned(), content); | ||
if !load_file(&files, file_id) { | ||
return ExitCode::FAILURE; | ||
} | ||
} | ||
Err(e) => { | ||
eprintln!("Unable to read file `{}`: {e}", filename.display()); | ||
return ExitCode::FAILURE; | ||
} | ||
} | ||
} | ||
|
||
ExitCode::SUCCESS | ||
} | ||
|
||
fn load_file(files: &SimpleFiles<String, String>, file_id: usize) -> bool { | ||
use json_syntax::{Parse, TryFromJsonSyntax}; | ||
|
||
match json_syntax::Value::parse_str(files.get(file_id).unwrap().source().as_str()) { | ||
Ok((json, code_map)) => { | ||
match treeldr_layouts::abs::syntax::Layout::try_from_json_syntax(&json, &code_map) { | ||
Ok(_layout) => true, | ||
Err(e) => { | ||
let span = code_map.get(e.position()).unwrap().span; | ||
let diagnostic = Diagnostic::error() | ||
.with_message("Layout syntax error") | ||
.with_labels(vec![ | ||
Label::primary(file_id, span).with_message(e.to_string()) | ||
]) | ||
.with_notes(e.hints().into_iter().map(|h| h.to_string()).collect()); | ||
|
||
let writer = StandardStream::stderr(ColorChoice::Always); | ||
let config = codespan_reporting::term::Config::default(); | ||
term::emit(&mut writer.lock(), &config, files, &diagnostic).unwrap(); | ||
false | ||
} | ||
} | ||
} | ||
Err(e) => { | ||
let diagnostic = Diagnostic::error() | ||
.with_message("JSON error") | ||
.with_labels(vec![ | ||
Label::primary(file_id, e.span()).with_message(e.to_string()) | ||
]); | ||
let writer = StandardStream::stderr(ColorChoice::Always); | ||
let config = codespan_reporting::term::Config::default(); | ||
term::emit(&mut writer.lock(), &config, files, &diagnostic).unwrap(); | ||
false | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.