Rust API
正在寻找跨语言 FFI 契约? 请参阅
./ffi-abi.md以了解call、"ERROR:"前缀、 4 MiB 的BUFFER_SIZE,以及kcl_apicrate。Rust 绑定 位于主kcl-lang/kcl仓库中(不在kcl-lang/libmonorepo 中), 并且是唯一进程内(in-process)运行的绑定——它不会经过 cdylib 跳转。
Rust 绑定
以 kcl-api crate 的形式发布(通过 kcl-lang 重新导出),来自主仓库
kcl-lang/kcl,
而不是来自 kcl-lang/lib monorepo。
后者仅包含进程外的 cdylib 绑定。因此,本页面仅作信息参考——
权威的 Rust API 参考文档请参阅 kcl-lang/kcl 文档。
该绑定暴露了两层 API:
kclvm_parser/kclvm_runner—— 围绕解析器和求值器的子 crate。 如果你需要更底层的控制,请使用这些。kcl_lang::*—— 高级外观层,镜像 Python 的kcl_lib.kclSDK。提供API::default(),以及从spec/spec.proto生成的 类型化*Args/*Result结构体。
安装
cargo add kcl-lang --git https://github.com/kcl-lang/kcl
(不要从 kcl-lang/lib 执行 cargo add——Rust 绑定位于
kcl-lang/kcl。lib monorepo 仅发布供其他语言使用的 cdylib 绑定。)
若要使用 KCL Rust 核心的某个子 crate:
# 以 kcl-runtime crate 为例。
cargo add --git https://github.com/kcl-lang/kcl kcl-runtime
快速上手
use kcl_lang::*;
use anyhow::Result;
fn main() -> Result<()> {
let api = API::default();
let args = &ExecProgramArgs {
k_filename_list: vec!["main.k".to_string()],
k_code_list: vec!["a = 1".to_string()],
..Default::default()
};
let exec_result = api.exec_program(args)?;
println!("{}", exec_result.yaml_result);
Ok(())
}
API 参考
exec_program
使用给定参数执行 KCL 文件。
示例
use kcl_lang::*;
use std::path::Path;
// 文件用例
let serv = API::default();
let args = &ExecProgramArgs {
work_dir: Path::new(".").join("src").join("testdata").canonicalize().unwrap().display().to_string(),
k_filename_list: vec!["test.k".to_string()],
..Default::default()
};
let exec_result = serv.exec_program(args).unwrap();
assert_eq!(exec_result.yaml_result, "alice:\n age: 18");
// 代码用例
let args = &ExecProgramArgs {
k_filename_list: vec!["file.k".to_string()],
k_code_list: vec!["alice = {age = 18}".to_string()],
..Default::default()
};
let exec_result = serv.exec_program(args).unwrap();
assert_eq!(exec_result.yaml_result, "alice:\n age: 18");
// 错误用例
let args = &ExecProgramArgs {
k_filename_list: vec!["invalid_file.k".to_string()],
..Default::default()
};
let error = serv.exec_program(args).unwrap_err();
assert!(error.to_string().contains("Cannot find the kcl file"), "{error}");
let args = &ExecProgramArgs {
k_filename_list: vec![],
..Default::default()
};
let error = serv.exec_program(args).unwrap_err();
assert!(error.to_string().contains("No input KCL files or paths"), "{error}");
format_code
格式化代码源的服务,返回格式化后的源码以及源码是否被修改。
示例
use kcl_lang::*;
let serv = API::default();
let source = r#"schema Person:
name: str
age: int
person = Person {
name = "Alice"
age = 18
}
"#.to_string();
let result = serv.format_code(&FormatCodeArgs {
source: source.clone(),
..Default::default()
}).unwrap();
assert_eq!(result.formatted, source.as_bytes().to_vec());
format_path
格式化 KCL 文件或包含 KCL 文件的目录路径的服务,并返回被修改的文件路径。
示例
use kcl_lang::*;
let serv = API::default();
let result = serv.format_path(&FormatPathArgs {
path: "./src/testdata/test.k".to_string(),
..Default::default()
}).unwrap();
assert!(result.changed_paths.is_empty());
lint_path
KCL Lint API 服务,检查一组文件,跳过执行,返回包含错误和警告的错误信息。
示例
use kcl_lang::*;
let serv = API::default();
let result = serv.lint_path(&LintPathArgs {
paths: vec!["./src/testdata/test-lint.k".to_string()],
..Default::default()
}).unwrap();
assert_eq!(result.results, vec!["Module 'math' imported but unused".to_string()]);
validate_code
使用 schema 代码字符串验证数据字符串的服务。当省略 schema 参数时, 使用 KCL 代码中出现的第一个 schema。
示例
use kcl_lang::*;
let serv = API::default();
let code = r#"
schema Person:
name: str
age: int
check:
0 < age < 120
"#.to_string();
let data = r#"
{
"name": "Alice",
"age": 10
}
"#.to_string();
let result = serv.validate_code(&ValidateCodeArgs {
code,
data,
..Default::default()
}).unwrap();
assert_eq!(result.success, true);
load_settings_files
从参数构建配置文件(settings file)配置的服务。
示例
use kcl_lang::*;
let serv = API::default();
let result = serv.load_settings_files(&LoadSettingsFilesArgs {
files: vec!["./src/testdata/settings/kcl.yaml".to_string()],
work_dir: "./src/testdata/settings".to_string(),
..Default::default()
}).unwrap();
assert_eq!(result.kcl_options.len(), 1);
rename
重命名文件中所有目标符号出现位置的服务。如果文件中包含需要重命名的符号, 此 API 会重写文件。返回被修改的文件路径。
示例
use kcl_lang::*;
let result = serv.rename(&RenameArgs {
package_root: "./src/testdata/rename_doc".to_string(),
symbol_path: "a".to_string(),
file_paths: vec!["./src/testdata/rename_doc/main.k".to_string()],
new_name: "a2".to_string(),
}).unwrap();
assert_eq!(result.changed_files.len(), 1);
rename_code
重命名所有目标符号出现位置并对其进行重命名的服务。此 API 不会重写文件, 但如果代码有变更,会返回修改后的代码。返回被修改的代码。
示例
use kcl_lang::*;
let serv = API::default();
let result = serv.rename_code(&RenameCodeArgs {
package_root: "/mock/path".to_string(),
symbol_path: "a".to_string(),
source_codes: vec![("/mock/path/main.k".to_string(), "a = 1\nb = a".to_string())].into_iter().collect(),
new_name: "a2".to_string(),
}).unwrap();
assert_eq!(result.changed_codes.len(), 1);
assert_eq!(result.changed_codes.get("/mock/path/main.k").unwrap(), "a2 = 1\nb = a2");
test
测试工具的服务。
示例
use kcl_lang::*;
let serv = API::default();
let result = serv.test(&TestArgs {
pkg_list: vec!["./src/testdata/testing/module/...".to_string()],
..TestArgs::default()
}).unwrap();
assert_eq!(result.info.len(), 2);
// 通过的用例
assert!(result.info[0].error.is_empty());
// 失败的用例
assert!(result.info[1].error.is_empty());
update_dependencies
update_dependencies 为用户提供更新 KCL 模块依赖的能力。
示例
use kcl_lang::*;
use std::path::Path;
use std::fs::remove_dir_all;
let serv = API::default();
let result = serv.update_dependencies(&UpdateDependenciesArgs {
manifest_path: "./src/testdata/update_dependencies".to_string(),
..Default::default()
}).unwrap();
assert_eq!(result.external_pkgs.len(), 1);
let result = serv.update_dependencies(&UpdateDependenciesArgs {
manifest_path: "./src/testdata/update_dependencies".to_string(),
vendor: true,
}).unwrap();
assert_eq!(result.external_pkgs.len(), 1);
let vendor_path = Path::new("./src/testdata/update_dependencies/vendor");
remove_dir_all(vendor_path);
get_version
返回 KCL 服务的版本信息。
use kcl_lang::*;
let serv = API::default();
let result = serv.get_version().unwrap();
assert!(!result.version.is_empty());
assert!(!result.git_sha.is_empty());
assert!(!result.checksum.is_empty());
ping
通过调度器对一个值进行往返(round-trip)。
use kcl_lang::*;
let serv = API::default();
let result = serv.ping(&PingArgs { value: "hello".into() }).unwrap();
assert_eq!(result.value, "hello");
list_method
列出底层运行时支持的 KCL 服务方法名。
use kcl_lang::*;
let serv = API::default();
for name in serv.list_method().unwrap().method_name_list {
println!("{}", name);
}
注意事项
旧的 BuildProgram 和 ExecArtifact RPC 已于 v0.13.0 中从
spec/spec.proto 中移除(参见
lib commit 815acac);
调度器已不再识别它们。如果你之前调用过 serv.build_program(...)
或 serv.exec_artifact(...),请改用 serv.exec_program(...)。
其余的 *_program、parse_*、list_*、get_schema_type_*、
format_*、lint_path、validate_code、load_settings_files、
rename*、test、override_file 方法的文档见上文或
kcl-lang/kcl 中的相关示例——请参阅本文件中每个方法对应章节了解使用方式。