mirror of https://github.com/tstack/lnav
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.3 KiB
Rust
127 lines
3.3 KiB
Rust
#![cfg(not(target_family = "wasm"))]
|
|
|
|
use prqlc::Target;
|
|
use prqlc::{ErrorMessage, ErrorMessages};
|
|
use std::panic;
|
|
use std::path::PathBuf;
|
|
use std::str::FromStr;
|
|
|
|
#[cxx::bridge(namespace = "prqlc")]
|
|
mod ffi {
|
|
struct Options {
|
|
pub format: bool,
|
|
pub target: String,
|
|
pub signature_comment: bool,
|
|
}
|
|
|
|
struct SourceTreeElement {
|
|
pub path: String,
|
|
pub content: String,
|
|
}
|
|
|
|
enum MessageKind {
|
|
Error,
|
|
Warning,
|
|
Lint,
|
|
}
|
|
|
|
struct Message {
|
|
pub kind: MessageKind,
|
|
pub code: String,
|
|
pub reason: String,
|
|
pub hints: Vec<String>,
|
|
pub display: String,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct CompileResult2 {
|
|
pub output: String,
|
|
pub messages: Vec<Message>,
|
|
}
|
|
|
|
extern "Rust" {
|
|
fn compile_tree(tree: &Vec<SourceTreeElement>, options: &Options) -> CompileResult2;
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&ffi::Options> for prqlc::Options {
|
|
type Error = ErrorMessages;
|
|
|
|
fn try_from(value: &ffi::Options) -> Result<Self, Self::Error> {
|
|
Ok(prqlc::Options {
|
|
format: value.format,
|
|
target: Target::from_str(value.target.as_str()).map_err(prqlc::ErrorMessages::from)?,
|
|
signature_comment: value.signature_comment,
|
|
color: false,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl From<prqlc::MessageKind> for ffi::MessageKind {
|
|
fn from(value: prqlc::MessageKind) -> Self {
|
|
match value {
|
|
prqlc::MessageKind::Error => ffi::MessageKind::Error,
|
|
prqlc::MessageKind::Warning => ffi::MessageKind::Warning,
|
|
prqlc::MessageKind::Lint => ffi::MessageKind::Lint,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ErrorMessage> for ffi::Message {
|
|
fn from(value: ErrorMessage) -> Self {
|
|
ffi::Message {
|
|
kind: value.kind.into(),
|
|
code: value.code.unwrap_or(String::new()),
|
|
reason: value.reason,
|
|
hints: value.hints,
|
|
display: value.display.unwrap_or(String::new()),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn compile_tree_int(
|
|
tree: &Vec<ffi::SourceTreeElement>,
|
|
options: &ffi::Options,
|
|
) -> Result<String, ErrorMessages> {
|
|
let tree = prqlc::SourceTree::new(
|
|
tree.iter()
|
|
.map(|ste| (PathBuf::from(ste.path.clone()), ste.content.clone())),
|
|
None,
|
|
);
|
|
|
|
let options: prqlc::Options = options.try_into()?;
|
|
|
|
panic::catch_unwind(|| {
|
|
Ok(prqlc::prql_to_pl_tree(&tree)
|
|
.and_then(prqlc::pl_to_rq)
|
|
.map_err(|e: ErrorMessages| ErrorMessages::from(e).composed(&tree))
|
|
.and_then(|rq| prqlc::rq_to_sql(rq, &options))?)
|
|
.map_err(|e: ErrorMessages| ErrorMessages::from(e).composed(&tree))
|
|
})
|
|
.map_err(|p| {
|
|
ErrorMessages::from(ErrorMessage {
|
|
kind: prqlc::MessageKind::Error,
|
|
code: None,
|
|
reason: format!("internal error: {:#?}", p),
|
|
hints: vec![],
|
|
span: None,
|
|
display: None,
|
|
location: None,
|
|
})
|
|
})?
|
|
}
|
|
|
|
pub fn compile_tree(
|
|
tree: &Vec<ffi::SourceTreeElement>,
|
|
options: &ffi::Options,
|
|
) -> ffi::CompileResult2 {
|
|
let mut retval = ffi::CompileResult2::default();
|
|
|
|
match compile_tree_int(tree, options) {
|
|
Ok(output) => retval.output = output,
|
|
Err(errors) => retval.messages = errors.inner.into_iter().map(|x| x.into()).collect(),
|
|
}
|
|
|
|
retval
|
|
}
|