Skip to main content

fig_sys/
lib.rs

1//! Low-level FFI bindings for fig's C ABI, plus the build script that compiles
2//! and links the native `libfig.a`.
3//!
4//! This is the `-sys` layer: raw `extern "C"` functions, `#[repr(C)]` type
5//! mirrors, and status/format constants — nothing else. The safe, ergonomic
6//! API (and serde/derive integration) lives in the `fig` crate, which depends
7//! on this one. Direct use is `unsafe` and unstable across ABI-version bumps.
8#![allow(non_camel_case_types)]
9
10use std::os::raw::c_int;
11
12/// A fig C ABI status code, as a transparent wrapper over the raw `c_int` the
13/// ABI returns — deliberately *not* a Rust `enum`.
14///
15/// A fieldless `#[repr(C)]` enum returned by value from an `extern "C"` function
16/// is undefined behavior the instant the callee returns a discriminant the enum
17/// does not list, and fig's status set is allowed to grow after 1.0. The newtype
18/// preserves any code unchanged; compare against the associated constants and
19/// route unrecognized values through a fallback (the `fig` crate does this in
20/// its `Error::from_status`).
21#[repr(transparent)]
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct FigStatus(pub c_int);
24
25#[allow(dead_code)]
26impl FigStatus {
27    pub const OK: c_int = 0;
28    pub const INVALID_ARGUMENT: c_int = 1;
29    pub const PARSE_ERROR: c_int = 2;
30    pub const OUT_OF_MEMORY: c_int = 3;
31    pub const UNSUPPORTED_FORMAT: c_int = 4;
32    pub const NOT_FOUND: c_int = 5;
33    pub const INTERNAL_ERROR: c_int = 255;
34}
35
36#[repr(C)]
37#[derive(Clone, Copy, Debug, Eq, PartialEq)]
38pub enum FigFormat {
39    Json = 1,
40    Jsonc = 2,
41    Yaml = 3,
42    Toml = 4,
43    Zon = 5,
44    // `Xml = 6` in the C ABI is reader-only and has no writable `Format`
45    // variant, so it is intentionally omitted here; the discriminant gap is
46    // deliberate to keep JSON5 at its stable ABI value.
47    Json5 = 7,
48    // The native `fig` authoring dialect. Appended, same reasoning as JSON5.
49    Fig = 8,
50}
51
52pub enum FigDocument {}
53
54pub type FigNodeId = u32;
55
56/// Sentinel for "no such node", matching `FIG_NODE_NONE` in `fig.h`.
57pub const FIG_NODE_NONE: FigNodeId = 0xFFFF_FFFF;
58
59#[repr(C)]
60#[derive(Clone, Copy, Debug, Eq, PartialEq)]
61#[allow(dead_code)]
62pub enum FigNodeKind {
63    Invalid = -1,
64    Null = 0,
65    Bool = 1,
66    Int = 2,
67    Float = 3,
68    String = 4,
69    Sequence = 5,
70    Mapping = 6,
71    Keyvalue = 7,
72    Alias = 8,
73}
74
75impl FigNodeKind {
76    /// Map the raw `c_int` returned by `fig_node_kind` onto a `FigNodeKind`.
77    /// Unknown / future kinds collapse to [`FigNodeKind::Invalid`] rather than
78    /// being reinterpreted as an out-of-range enum value — which, for a value
79    /// returned by an `extern "C"` function into a Rust enum, is undefined
80    /// behavior. This is the only place a raw kind crosses into the enum.
81    pub fn from_c(raw: c_int) -> Self {
82        match raw {
83            0 => FigNodeKind::Null,
84            1 => FigNodeKind::Bool,
85            2 => FigNodeKind::Int,
86            3 => FigNodeKind::Float,
87            4 => FigNodeKind::String,
88            5 => FigNodeKind::Sequence,
89            6 => FigNodeKind::Mapping,
90            7 => FigNodeKind::Keyvalue,
91            8 => FigNodeKind::Alias,
92            _ => FigNodeKind::Invalid,
93        }
94    }
95}
96
97/// A caller-allocated parse diagnostic. Mirrors `FigError` in `fig.h`. Lead with
98/// `size = size_of::<FigError>()`: the library writes only the fields `size`
99/// covers, so it can gain fields in a later release without breaking this layout.
100/// `byte_offset`/`line`/`column` are 0 when unknown (always 0 in this release —
101/// offset plumbing is a planned core follow-up). `message` is NUL-terminated and
102/// truncated to fit; `message_len` excludes the NUL.
103#[repr(C)]
104#[derive(Clone, Copy)]
105pub struct FigError {
106    pub size: u32,
107    pub code: c_int,
108    pub byte_offset: usize,
109    pub line: u32,
110    pub column: u32,
111    pub message_len: usize,
112    pub message: [u8; 256],
113}
114
115impl FigError {
116    /// A zeroed struct with `size` set, ready to pass to `fig_parse_ex`.
117    pub fn new() -> Self {
118        FigError {
119            size: std::mem::size_of::<FigError>() as u32,
120            code: 0,
121            byte_offset: 0,
122            line: 0,
123            column: 0,
124            message_len: 0,
125            message: [0; 256],
126        }
127    }
128}
129
130unsafe extern "C" {
131    pub fn fig_version() -> u32;
132    pub fn fig_version_string() -> *const std::os::raw::c_char;
133    pub fn fig_format_capabilities(format: c_int) -> u32;
134
135    // Declared for ABI-mirror completeness; the binding parses via `fig_parse_ex`
136    // (richer errors), so this plain entry point is not called from Rust.
137    #[allow(dead_code)]
138    pub fn fig_parse(
139        input: *const u8,
140        input_len: usize,
141        format: c_int,
142        out_doc: *mut *mut FigDocument,
143    ) -> FigStatus;
144
145    pub fn fig_parse_ex(
146        input: *const u8,
147        input_len: usize,
148        format: c_int,
149        out_doc: *mut *mut FigDocument,
150        out_err: *mut FigError,
151    ) -> FigStatus;
152
153    pub fn fig_document_destroy(doc: *mut FigDocument);
154
155    pub fn fig_document_serialize(
156        doc: *mut FigDocument,
157        format: c_int,
158        options: *const FigSerializeOptions,
159        out_ptr: *mut *const u8,
160        out_len: *mut usize,
161    ) -> FigStatus;
162}
163
164// Read traversal — consumed by `Document::to_value` and the serde deserializer.
165unsafe extern "C" {
166    pub fn fig_document_root(doc: *const FigDocument) -> FigNodeId;
167    // Returns the raw kind as `c_int`, not `FigNodeKind`: decoding it directly
168    // into the enum would be UB if the core returned an unlisted value. Callers
169    // go through `FigNodeKind::from_c`.
170    pub fn fig_node_kind(doc: *const FigDocument, node: FigNodeId) -> c_int;
171    pub fn fig_node_first_child(doc: *const FigDocument, node: FigNodeId) -> FigNodeId;
172    pub fn fig_node_next_sibling(doc: *const FigDocument, node: FigNodeId) -> FigNodeId;
173    pub fn fig_node_child_count(doc: *const FigDocument, node: FigNodeId) -> usize;
174    pub fn fig_keyvalue_key(doc: *const FigDocument, node: FigNodeId) -> FigNodeId;
175    pub fn fig_keyvalue_value(doc: *const FigDocument, node: FigNodeId) -> FigNodeId;
176
177    pub fn fig_node_bool(doc: *const FigDocument, node: FigNodeId, out: *mut bool) -> bool;
178    pub fn fig_node_number(
179        doc: *const FigDocument,
180        node: FigNodeId,
181        out_ptr: *mut *const u8,
182        out_len: *mut usize,
183    ) -> bool;
184    pub fn fig_node_string(
185        doc: *const FigDocument,
186        node: FigNodeId,
187        out_ptr: *mut *const u8,
188        out_len: *mut usize,
189    ) -> bool;
190    pub fn fig_node_extended(
191        doc: *const FigDocument,
192        node: FigNodeId,
193        out_kind: *mut c_int,
194        out_ptr: *mut *const u8,
195        out_len: *mut usize,
196    ) -> bool;
197}
198
199// ---- value construction + serialization ----
200
201pub enum FigValue {}
202
203/// A `key: value` entry for `fig_value_map`. Mirrors `FigKeyValue` in `fig.h`.
204#[repr(C)]
205#[derive(Clone, Copy, Debug)]
206pub struct FigKeyValue {
207    pub key: FigNodeId,
208    pub value: FigNodeId,
209}
210
211/// Output style for `fig_value_serialize_opts`/`fig_document_serialize`. Mirrors
212/// `FigSerializeOptions` in `fig.h`. ALL trailing fields are declared explicitly
213/// (not left to struct padding): with `size = size_of` the core reads every byte
214/// up to `size`, so an undeclared `strip_comments`/`lossless` would otherwise be
215/// read out of uninitialized padding.
216#[repr(C)]
217#[derive(Clone, Copy, Debug)]
218pub struct FigSerializeOptions {
219    /// Set to `size_of::<FigSerializeOptions>()`. Version tag for the struct:
220    /// the core reads a field only when `size` covers it, so fields can be
221    /// appended without breaking this layout. See `FigSerializeOptions` in `fig.h`.
222    pub size: u32,
223    pub pretty: u8,
224    pub indent: u8,
225    pub strip_comments: u8,
226    pub lossless: u8,
227    pub width: u16,
228    /// fig-format fragments only: nonzero renders a container root as inline
229    /// flow (`[a, b]` / `{ k = v }`). Set by the editors' splice path (see
230    /// `value_text`); not exposed on the public `SerializeOptions` — inline is
231    /// a property of *where* the text goes, not a caller style preference.
232    pub flow: u8,
233}
234
235/// One lossy event from `fig_*_diagnose`, pulled by index via `fig_*_warning`.
236/// Caller-allocated; lead with `size = size_of::<FigWarning>()` (same policy as
237/// `FigSerializeOptions`/`FigError`). `path`/`note` are NOT NUL-terminated and
238/// borrow the producing handle's diagnostics arena (valid until the next
239/// diagnose on it or its destroy) — copy them out before then. Mirrors
240/// `FigWarning` in `fig.h`.
241#[repr(C)]
242#[derive(Clone, Copy)]
243pub struct FigWarning {
244    pub size: u32,
245    pub code: c_int,
246    pub cause: c_int,
247    pub path: *const u8,
248    pub path_len: usize,
249    pub note: *const u8,
250    pub note_len: usize,
251}
252
253impl FigWarning {
254    /// A zeroed struct with `size` set, ready to pass to a `fig_*_warning` call.
255    pub fn new() -> Self {
256        FigWarning {
257            size: std::mem::size_of::<FigWarning>() as u32,
258            code: 0,
259            cause: 0,
260            path: std::ptr::null(),
261            path_len: 0,
262            note: std::ptr::null(),
263            note_len: 0,
264        }
265    }
266}
267
268unsafe extern "C" {
269    pub fn fig_value_create(out_value: *mut *mut FigValue) -> FigStatus;
270    pub fn fig_value_destroy(value: *mut FigValue);
271
272    pub fn fig_value_null(value: *mut FigValue, out_id: *mut FigNodeId) -> FigStatus;
273    pub fn fig_value_bool(value: *mut FigValue, b: bool, out_id: *mut FigNodeId) -> FigStatus;
274    pub fn fig_value_int(value: *mut FigValue, n: i64, out_id: *mut FigNodeId) -> FigStatus;
275    pub fn fig_value_uint(value: *mut FigValue, n: u64, out_id: *mut FigNodeId) -> FigStatus;
276    pub fn fig_value_number(
277        value: *mut FigValue,
278        raw: *const u8,
279        raw_len: usize,
280        is_float: bool,
281        out_id: *mut FigNodeId,
282    ) -> FigStatus;
283    pub fn fig_value_string(
284        value: *mut FigValue,
285        ptr: *const u8,
286        len: usize,
287        out_id: *mut FigNodeId,
288    ) -> FigStatus;
289    pub fn fig_value_extended(
290        value: *mut FigValue,
291        kind: c_int,
292        text: *const u8,
293        text_len: usize,
294        out_id: *mut FigNodeId,
295    ) -> FigStatus;
296    pub fn fig_value_seq(
297        value: *mut FigValue,
298        items: *const FigNodeId,
299        items_len: usize,
300        out_id: *mut FigNodeId,
301    ) -> FigStatus;
302    pub fn fig_value_map(
303        value: *mut FigValue,
304        entries: *const FigKeyValue,
305        entries_len: usize,
306        out_id: *mut FigNodeId,
307    ) -> FigStatus;
308    // ABI-mirror decl; the binding always serializes through the `_opts` form.
309    #[allow(dead_code)]
310    pub fn fig_value_serialize(
311        value: *mut FigValue,
312        root: FigNodeId,
313        format: c_int,
314        out_ptr: *mut *const u8,
315        out_len: *mut usize,
316    ) -> FigStatus;
317    pub fn fig_value_serialize_opts(
318        value: *mut FigValue,
319        root: FigNodeId,
320        format: c_int,
321        options: *const FigSerializeOptions,
322        out_ptr: *mut *const u8,
323        out_len: *mut usize,
324    ) -> FigStatus;
325}
326
327// ---- serialization diagnostics ----
328
329unsafe extern "C" {
330    pub fn fig_document_diagnose(
331        doc: *mut FigDocument,
332        format: c_int,
333        options: *const FigSerializeOptions,
334        out_count: *mut usize,
335    ) -> FigStatus;
336    pub fn fig_document_warning(
337        doc: *mut FigDocument,
338        index: usize,
339        out: *mut FigWarning,
340    ) -> FigStatus;
341    pub fn fig_value_diagnose(
342        value: *mut FigValue,
343        root: FigNodeId,
344        format: c_int,
345        options: *const FigSerializeOptions,
346        out_count: *mut usize,
347    ) -> FigStatus;
348    pub fn fig_value_warning(value: *mut FigValue, index: usize, out: *mut FigWarning)
349    -> FigStatus;
350}
351
352// ---- editing (write path) ----
353
354pub enum FigEditor {}
355pub enum FigEmbed {}
356
357/// One step of a path: `kind == 0` selects mapping key `key_ptr[0..key_len]`;
358/// `kind == 1` selects sequence element `index`. Mirrors `FigPathSegment` in
359/// `fig.h`.
360#[repr(C)]
361#[derive(Clone, Copy, Debug)]
362pub struct FigPathSegment {
363    pub kind: i32,
364    pub key_ptr: *const u8,
365    pub key_len: usize,
366    pub index: usize,
367}
368
369/// A borrowed UTF-8 string slice (`ptr[0..len]`) passed across the C ABI.
370/// Mirrors `FigStr` in `fig.h`; used for the key list of `*_reorder_keys`.
371#[repr(C)]
372#[derive(Clone, Copy, Debug)]
373pub struct FigStr {
374    pub ptr: *const u8,
375    pub len: usize,
376}
377
378// `FigSpan`/`FigRegion`/`fig_embed_extract` mirror the low-level embed C ABI.
379// The Rust-facing consumer is `Embed` (which uses `fig_embed_*`); these are
380// declared for parity with the header and for any future low-level wrapper.
381#[repr(C)]
382#[derive(Clone, Copy, Debug, Default)]
383#[allow(dead_code)]
384pub struct FigSpan {
385    pub start: usize,
386    pub end: usize,
387}
388
389#[repr(C)]
390#[derive(Clone, Copy, Debug, Default)]
391#[allow(dead_code)]
392pub struct FigRegion {
393    /// Size-version tag: set to `size_of::<FigRegion>()` before
394    /// `fig_embed_extract` so the library only writes the fields this layout
395    /// covers. A zero `size` (e.g. from `Default`) makes the library write
396    /// nothing — always set it explicitly.
397    pub size: u32,
398    pub open_fence: FigSpan,
399    pub content: FigSpan,
400    pub close_fence: FigSpan,
401    pub body: FigSpan,
402}
403
404#[repr(C)]
405#[derive(Clone, Copy, Debug, Eq, PartialEq)]
406#[allow(dead_code)]
407pub enum FigEmbedType {
408    FrontmatterYaml = 0,
409    FrontmatterJson = 1,
410    EndmatterYaml = 2,
411    FrontmatterFig = 3,
412    PlusToml = 4,
413    FencedYaml = 5,
414    FencedJson = 6,
415    FencedToml = 7,
416    MdFrontmatterJson = 8,
417    MdFrontmatterToml = 9,
418    MdFrontmatterFig = 10,
419    HtmlScriptFig = 11,
420    HtmlScriptYaml = 12,
421    HtmlScriptJson = 13,
422    HtmlScriptToml = 14,
423    HtmlCodeFig = 15,
424    HtmlCodeYaml = 16,
425    HtmlCodeJson = 17,
426    HtmlCodeToml = 18,
427}
428
429unsafe extern "C" {
430    pub fn fig_editor_create(
431        input: *const u8,
432        input_len: usize,
433        format: c_int,
434        out_editor: *mut *mut FigEditor,
435    ) -> FigStatus;
436    pub fn fig_editor_destroy(editor: *mut FigEditor);
437
438    pub fn fig_editor_replace_val(
439        editor: *mut FigEditor,
440        path: *const FigPathSegment,
441        path_len: usize,
442        repl: *const u8,
443        repl_len: usize,
444    ) -> FigStatus;
445    pub fn fig_editor_replace_key(
446        editor: *mut FigEditor,
447        path: *const FigPathSegment,
448        path_len: usize,
449        repl: *const u8,
450        repl_len: usize,
451    ) -> FigStatus;
452    pub fn fig_editor_set(
453        editor: *mut FigEditor,
454        path: *const FigPathSegment,
455        path_len: usize,
456        val: *const u8,
457        val_len: usize,
458    ) -> FigStatus;
459    pub fn fig_editor_add_leading_comment(
460        editor: *mut FigEditor,
461        path: *const FigPathSegment,
462        path_len: usize,
463        text: *const u8,
464        text_len: usize,
465    ) -> FigStatus;
466    pub fn fig_editor_set_trailing_comment(
467        editor: *mut FigEditor,
468        path: *const FigPathSegment,
469        path_len: usize,
470        text: *const u8,
471        text_len: usize,
472    ) -> FigStatus;
473    pub fn fig_editor_delete_leading_comments(
474        editor: *mut FigEditor,
475        path: *const FigPathSegment,
476        path_len: usize,
477    ) -> FigStatus;
478    pub fn fig_editor_delete_trailing_comment(
479        editor: *mut FigEditor,
480        path: *const FigPathSegment,
481        path_len: usize,
482    ) -> FigStatus;
483    pub fn fig_editor_get_leading_comment(
484        editor: *mut FigEditor,
485        path: *const FigPathSegment,
486        path_len: usize,
487        out_ptr: *mut *const u8,
488        out_len: *mut usize,
489    ) -> FigStatus;
490    pub fn fig_editor_get_trailing_comment(
491        editor: *mut FigEditor,
492        path: *const FigPathSegment,
493        path_len: usize,
494        out_ptr: *mut *const u8,
495        out_len: *mut usize,
496    ) -> FigStatus;
497    pub fn fig_editor_insert_key(
498        editor: *mut FigEditor,
499        path: *const FigPathSegment,
500        path_len: usize,
501        key: *const u8,
502        key_len: usize,
503        val: *const u8,
504        val_len: usize,
505    ) -> FigStatus;
506    pub fn fig_editor_delete_key(
507        editor: *mut FigEditor,
508        path: *const FigPathSegment,
509        path_len: usize,
510    ) -> FigStatus;
511    pub fn fig_editor_append_seq(
512        editor: *mut FigEditor,
513        path: *const FigPathSegment,
514        path_len: usize,
515        val: *const u8,
516        val_len: usize,
517    ) -> FigStatus;
518    pub fn fig_editor_prepend_seq(
519        editor: *mut FigEditor,
520        path: *const FigPathSegment,
521        path_len: usize,
522        val: *const u8,
523        val_len: usize,
524    ) -> FigStatus;
525    pub fn fig_editor_remove_seq_item(
526        editor: *mut FigEditor,
527        path: *const FigPathSegment,
528        path_len: usize,
529        index: usize,
530    ) -> FigStatus;
531    pub fn fig_editor_move_key(
532        editor: *mut FigEditor,
533        src_path: *const FigPathSegment,
534        src_path_len: usize,
535        dest_path: *const FigPathSegment,
536        dest_path_len: usize,
537    ) -> FigStatus;
538    pub fn fig_editor_reorder_keys(
539        editor: *mut FigEditor,
540        path: *const FigPathSegment,
541        path_len: usize,
542        keys: *const FigStr,
543        keys_len: usize,
544    ) -> FigStatus;
545    pub fn fig_editor_move_item(
546        editor: *mut FigEditor,
547        path: *const FigPathSegment,
548        path_len: usize,
549        from: usize,
550        to: usize,
551    ) -> FigStatus;
552    pub fn fig_editor_reorder_items(
553        editor: *mut FigEditor,
554        path: *const FigPathSegment,
555        path_len: usize,
556        indices: *const usize,
557        indices_len: usize,
558    ) -> FigStatus;
559    pub fn fig_editor_set_sequence(
560        editor: *mut FigEditor,
561        path: *const FigPathSegment,
562        path_len: usize,
563        items: *const FigStr,
564        items_len: usize,
565    ) -> FigStatus;
566    // Whole-container ops, for containers scattered through the source (a TOML
567    // `[header]` table, an INI `[section]`, a fig block container). The key ops
568    // above cannot address one, and refuse with `INVALID_ARGUMENT` at such a
569    // path. A format that does not support the op answers `UNSUPPORTED_FORMAT`.
570    pub fn fig_editor_delete_container(
571        editor: *mut FigEditor,
572        path: *const FigPathSegment,
573        path_len: usize,
574    ) -> FigStatus;
575    pub fn fig_editor_insert_container(
576        editor: *mut FigEditor,
577        path: *const FigPathSegment,
578        path_len: usize,
579        body: *const u8,
580        body_len: usize,
581    ) -> FigStatus;
582    pub fn fig_editor_rename_container(
583        editor: *mut FigEditor,
584        path: *const FigPathSegment,
585        path_len: usize,
586        new_leaf: *const u8,
587        new_leaf_len: usize,
588    ) -> FigStatus;
589    /// A NULL `dest_path` means "to the end of the document" — distinct from a
590    /// zero-length path, which every other entry point reads as the root.
591    pub fn fig_editor_move_container(
592        editor: *mut FigEditor,
593        src_path: *const FigPathSegment,
594        src_path_len: usize,
595        dest_path: *const FigPathSegment,
596        dest_path_len: usize,
597    ) -> FigStatus;
598    pub fn fig_editor_reorder_containers(
599        editor: *mut FigEditor,
600        order: *const FigStr,
601        order_len: usize,
602    ) -> FigStatus;
603    pub fn fig_editor_append_container_to_seq(
604        editor: *mut FigEditor,
605        path: *const FigPathSegment,
606        path_len: usize,
607        body: *const u8,
608        body_len: usize,
609    ) -> FigStatus;
610    pub fn fig_editor_source(
611        editor: *const FigEditor,
612        out_ptr: *mut *const u8,
613        out_len: *mut usize,
614    ) -> FigStatus;
615
616    pub fn fig_embed_extract(
617        input: *const u8,
618        input_len: usize,
619        embed_type: c_int,
620        out_region: *mut FigRegion,
621    ) -> FigStatus;
622
623    pub fn fig_embed_detect(
624        input: *const u8,
625        input_len: usize,
626        out_embed_type: *mut c_int,
627    ) -> FigStatus;
628
629    pub fn fig_embed_open(
630        input: *const u8,
631        input_len: usize,
632        embed_type: c_int,
633        out_embed: *mut *mut FigEmbed,
634    ) -> FigStatus;
635    pub fn fig_embed_open_or_init(
636        input: *const u8,
637        input_len: usize,
638        embed_type: c_int,
639        out_embed: *mut *mut FigEmbed,
640    ) -> FigStatus;
641    pub fn fig_embed_destroy(fm: *mut FigEmbed);
642
643    pub fn fig_embed_replace_val(
644        fm: *mut FigEmbed,
645        path: *const FigPathSegment,
646        path_len: usize,
647        repl: *const u8,
648        repl_len: usize,
649    ) -> FigStatus;
650    pub fn fig_embed_replace_key(
651        fm: *mut FigEmbed,
652        path: *const FigPathSegment,
653        path_len: usize,
654        repl: *const u8,
655        repl_len: usize,
656    ) -> FigStatus;
657    pub fn fig_embed_set(
658        fm: *mut FigEmbed,
659        path: *const FigPathSegment,
660        path_len: usize,
661        val: *const u8,
662        val_len: usize,
663    ) -> FigStatus;
664    pub fn fig_embed_add_leading_comment(
665        fm: *mut FigEmbed,
666        path: *const FigPathSegment,
667        path_len: usize,
668        text: *const u8,
669        text_len: usize,
670    ) -> FigStatus;
671    pub fn fig_embed_set_trailing_comment(
672        fm: *mut FigEmbed,
673        path: *const FigPathSegment,
674        path_len: usize,
675        text: *const u8,
676        text_len: usize,
677    ) -> FigStatus;
678    pub fn fig_embed_delete_leading_comments(
679        fm: *mut FigEmbed,
680        path: *const FigPathSegment,
681        path_len: usize,
682    ) -> FigStatus;
683    pub fn fig_embed_delete_trailing_comment(
684        fm: *mut FigEmbed,
685        path: *const FigPathSegment,
686        path_len: usize,
687    ) -> FigStatus;
688    pub fn fig_embed_get_leading_comment(
689        fm: *mut FigEmbed,
690        path: *const FigPathSegment,
691        path_len: usize,
692        out_ptr: *mut *const u8,
693        out_len: *mut usize,
694    ) -> FigStatus;
695    pub fn fig_embed_get_trailing_comment(
696        fm: *mut FigEmbed,
697        path: *const FigPathSegment,
698        path_len: usize,
699        out_ptr: *mut *const u8,
700        out_len: *mut usize,
701    ) -> FigStatus;
702    pub fn fig_embed_insert_key(
703        fm: *mut FigEmbed,
704        path: *const FigPathSegment,
705        path_len: usize,
706        key: *const u8,
707        key_len: usize,
708        val: *const u8,
709        val_len: usize,
710    ) -> FigStatus;
711    pub fn fig_embed_delete_key(
712        fm: *mut FigEmbed,
713        path: *const FigPathSegment,
714        path_len: usize,
715    ) -> FigStatus;
716    pub fn fig_embed_append_seq(
717        fm: *mut FigEmbed,
718        path: *const FigPathSegment,
719        path_len: usize,
720        val: *const u8,
721        val_len: usize,
722    ) -> FigStatus;
723    pub fn fig_embed_prepend_seq(
724        fm: *mut FigEmbed,
725        path: *const FigPathSegment,
726        path_len: usize,
727        val: *const u8,
728        val_len: usize,
729    ) -> FigStatus;
730    pub fn fig_embed_remove_seq_item(
731        fm: *mut FigEmbed,
732        path: *const FigPathSegment,
733        path_len: usize,
734        index: usize,
735    ) -> FigStatus;
736    pub fn fig_embed_move_key(
737        fm: *mut FigEmbed,
738        src_path: *const FigPathSegment,
739        src_path_len: usize,
740        dest_path: *const FigPathSegment,
741        dest_path_len: usize,
742    ) -> FigStatus;
743    pub fn fig_embed_reorder_keys(
744        fm: *mut FigEmbed,
745        path: *const FigPathSegment,
746        path_len: usize,
747        keys: *const FigStr,
748        keys_len: usize,
749    ) -> FigStatus;
750    pub fn fig_embed_move_item(
751        fm: *mut FigEmbed,
752        path: *const FigPathSegment,
753        path_len: usize,
754        from: usize,
755        to: usize,
756    ) -> FigStatus;
757    pub fn fig_embed_reorder_items(
758        fm: *mut FigEmbed,
759        path: *const FigPathSegment,
760        path_len: usize,
761        indices: *const usize,
762        indices_len: usize,
763    ) -> FigStatus;
764    pub fn fig_embed_set_sequence(
765        fm: *mut FigEmbed,
766        path: *const FigPathSegment,
767        path_len: usize,
768        items: *const FigStr,
769        items_len: usize,
770    ) -> FigStatus;
771    pub fn fig_embed_replace_body(fm: *mut FigEmbed, body: *const u8, body_len: usize)
772    -> FigStatus;
773    pub fn fig_embed_render(
774        fm: *mut FigEmbed,
775        out_ptr: *mut *const u8,
776        out_len: *mut usize,
777    ) -> FigStatus;
778}