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