GitRoot

craft your forge, build your project, grow your community freely
 1// SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
 2//
 3// SPDX-License-Identifier: MIT
 4
 5use crate::gitroot::{get, with_plugin, with_plugin_reporter};
 6use crate::ptr::{ptr_to_string, string_to_ptr};
 7use crate::{Commit, ConfPlugin, Report};
 8use std::mem::MaybeUninit;
 9
10#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "init"))]
11pub fn init(
12    repo_name_ptr: u32,
13    repo_name_size: u32,
14    conf_has_changed_ptr: u32,
15    conf_has_changed_size: u32,
16    conf_ptr: u32,
17    conf_size: u32,
18) {
19    let repo_name = ptr_to_string(repo_name_ptr, repo_name_size);
20    let conf_has_changed = ptr_to_string(conf_has_changed_ptr, conf_has_changed_size) == "true";
21    let conf = ptr_to_string(conf_ptr, conf_size);
22    with_plugin(|plugin| plugin.init(repo_name, conf_has_changed, conf));
23}
24
25#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "startCommit"))]
26pub fn start_commit(json: &str) {
27    let commit: Commit = serde_json::from_str(json).expect("JSON was not well-formatted");
28    with_plugin(|plugin| plugin.start_commit(commit));
29}
30
31#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "addFile"))]
32pub fn add_file(filepath: &str) {
33    with_plugin(|plugin| plugin.add_file(String::from(filepath)));
34}
35
36#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "modFile"))]
37pub fn mod_file(from_filepath: &str, to_filepath: &str) {
38    with_plugin(|plugin| plugin.mod_file(String::from(from_filepath), String::from(to_filepath)));
39}
40
41#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "delFile"))]
42pub fn del_file(filepath: &str) {
43    with_plugin(|plugin| plugin.del_file(String::from(filepath)));
44}
45
46#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "endCommit"))]
47pub fn end_commit(json: &str) {
48    let commit: Commit = serde_json::from_str(json).expect("JSON was not well-formatted");
49    with_plugin(|plugin| plugin.end_commit(commit));
50}
51
52#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "finish"))]
53pub fn finish() {
54    with_plugin(|plugin| plugin.finish());
55}
56
57#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "report"))]
58pub fn report(json: &str) {
59    let report: Report = serde_json::from_str(json).expect("JSON was not well-formatted");
60    with_plugin_reporter(|plugin| plugin.report(report));
61}
62
63/// # Safety
64///
65/// Called by host
66#[cfg_attr(all(target_arch = "wasm32"), unsafe(export_name = "pluginConf"))]
67pub unsafe extern "C" fn plugin_conf() -> u64 {
68    let conf_plugin = ConfPlugin {
69        default_run: get().run.clone(),
70        sdk_version: String::from("0.3.0"),
71        sdk_type: String::from("tinygo"),
72    };
73    let conf = serde_json::to_string(&conf_plugin).unwrap();
74    let (ptr, len) = string_to_ptr(&conf);
75    // Note: This changes ownership of the pointer to the external caller. If
76    // we didn't call forget, the caller would read back a corrupt value. Since
77    // we call forget, the caller must deallocate externally to prevent leaks.
78    std::mem::forget(conf);
79    ((ptr as u64) << 32) | len as u64
80}
81
82#[unsafe(no_mangle)]
83extern "C" fn gitrootAlloc(size: u32) -> *mut u8 {
84    // Allocate the amount of bytes needed.
85    let vec: Vec<MaybeUninit<u8>> = vec![MaybeUninit::uninit(); size as usize];
86    // into_raw leaks the memory to the caller.
87    Box::into_raw(vec.into_boxed_slice()) as *mut u8
88}
89
90#[unsafe(no_mangle)]
91extern "C" fn gitrootFree(ptr: u32, size: u32) {
92    unsafe {
93        let _ = Vec::from_raw_parts(ptr as *mut u8, 0, size as usize);
94    }
95}