Skip to main content

dprint_core/plugins/wasm/
mod.rs

1/// The plugin system schema version that is incremented
2/// when there are any breaking changes.
3pub const PLUGIN_SYSTEM_SCHEMA_VERSION: u32 = 4;
4
5#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
6mod state;
7
8#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
9pub use state::WasmPluginState;
10
11#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
12unsafe extern "C" {
13  fn fd_write(fd: i32, iovs: *const crate::plugins::wasm::Iovec, iovs_len: i32, nwritten: *mut i32) -> i32;
14}
15
16#[derive(serde::Serialize, serde::Deserialize)]
17#[serde(tag = "kind", content = "data")]
18pub enum JsonResponse {
19  #[serde(rename = "ok")]
20  Ok(serde_json::Value),
21  #[serde(rename = "err")]
22  Err(String),
23}
24
25pub struct WasiPrintFd(pub i32);
26
27impl std::io::Write for WasiPrintFd {
28  fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
29    #[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
30    {
31      let iovec = Iovec {
32        buf: buf.as_ptr(),
33        buf_len: buf.len() as u32,
34      };
35      let mut nwritten: i32 = 0;
36      let result = unsafe { fd_write(self.0, &iovec, 1, &mut nwritten) };
37      if result == 0 {
38        Ok(nwritten as usize)
39      } else {
40        Err(std::io::Error::from_raw_os_error(result))
41      }
42    }
43    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
44    {
45      let size = buf.len();
46      match self.0 {
47        0 => std::io::stdout().write_all(buf)?,
48        1 => std::io::stderr().write_all(buf)?,
49        _ => return Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)),
50      }
51      Ok(size)
52    }
53  }
54
55  fn flush(&mut self) -> std::io::Result<()> {
56    Ok(())
57  }
58}
59
60#[repr(C)]
61pub struct Iovec {
62  pub buf: *const u8,
63  pub buf_len: u32,
64}
65
66#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
67pub mod macros {
68  #[macro_export]
69  macro_rules! generate_plugin_code {
70    ($wasm_plugin_struct:ident, $wasm_plugin_creation:expr) => {
71      $crate::generate_plugin_code!($wasm_plugin_struct, $wasm_plugin_creation, Configuration);
72    };
73    ($wasm_plugin_struct:ident, $wasm_plugin_creation:expr, $wasm_plugin_config:ident) => {
74      // Keep this expansion minimal because it's linted with the plugin's lint
75      // configuration (ex. clippy's `disallowed_types`). The implementation lives
76      // in dprint-core instead. Note that adding an `#[allow(...)]` here would
77      // conflict with a plugin forbidding any of the allowed lints.
78      const _: () = {
79        static STATE: $crate::plugins::wasm::WasmPluginState<$wasm_plugin_struct, $wasm_plugin_config> =
80          $crate::plugins::wasm::WasmPluginState::new(|| $wasm_plugin_creation);
81
82        // FORMATTING
83
84        #[unsafe(no_mangle)]
85        pub fn set_override_config() {
86          STATE.set_override_config()
87        }
88
89        #[unsafe(no_mangle)]
90        pub fn set_file_path() {
91          STATE.set_file_path()
92        }
93
94        #[unsafe(no_mangle)]
95        pub fn format(config_id: u32) -> u8 {
96          STATE.format(config_id, None)
97        }
98
99        #[unsafe(no_mangle)]
100        pub fn format_range(config_id: u32, range_start: u32, range_end: u32) -> u8 {
101          STATE.format(config_id, Some(range_start as usize..range_end as usize))
102        }
103
104        #[unsafe(no_mangle)]
105        pub fn get_formatted_text() -> usize {
106          STATE.get_formatted_text()
107        }
108
109        #[unsafe(no_mangle)]
110        pub fn get_error_text() -> usize {
111          STATE.get_error_text()
112        }
113
114        // INFORMATION & CONFIGURATION
115
116        #[unsafe(no_mangle)]
117        pub fn get_plugin_info() -> usize {
118          STATE.get_plugin_info()
119        }
120
121        #[unsafe(no_mangle)]
122        pub fn get_license_text() -> usize {
123          STATE.get_license_text()
124        }
125
126        #[unsafe(no_mangle)]
127        pub fn get_resolved_config(config_id: u32) -> usize {
128          STATE.get_resolved_config(config_id)
129        }
130
131        #[unsafe(no_mangle)]
132        pub fn get_config_diagnostics(config_id: u32) -> usize {
133          STATE.get_config_diagnostics(config_id)
134        }
135
136        #[unsafe(no_mangle)]
137        pub fn get_config_file_matching(config_id: u32) -> usize {
138          STATE.get_config_file_matching(config_id)
139        }
140
141        // INITIALIZATION
142
143        #[unsafe(no_mangle)]
144        pub fn register_config(config_id: u32) {
145          STATE.register_config(config_id)
146        }
147
148        #[unsafe(no_mangle)]
149        pub fn release_config(config_id: u32) {
150          STATE.release_config(config_id)
151        }
152
153        #[unsafe(no_mangle)]
154        pub fn check_config_updates() -> usize {
155          STATE.check_config_updates()
156        }
157
158        // LOW LEVEL SENDING AND RECEIVING
159
160        #[unsafe(no_mangle)]
161        pub fn dprint_plugin_version_4() -> u32 {
162          $crate::plugins::wasm::PLUGIN_SYSTEM_SCHEMA_VERSION
163        }
164
165        #[unsafe(no_mangle)]
166        pub fn get_shared_bytes_ptr() -> *const u8 {
167          STATE.get_shared_bytes_ptr()
168        }
169
170        #[unsafe(no_mangle)]
171        pub fn clear_shared_bytes(size: usize) -> *const u8 {
172          STATE.clear_shared_bytes(size)
173        }
174      };
175    };
176  }
177}