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_add_dangling_comment(
507        editor: *mut FigEditor,
508        path: *const FigPathSegment,
509        path_len: usize,
510        text: *const u8,
511        text_len: usize,
512    ) -> FigStatus;
513    pub fn fig_editor_delete_dangling_comments(
514        editor: *mut FigEditor,
515        path: *const FigPathSegment,
516        path_len: usize,
517    ) -> FigStatus;
518    pub fn fig_editor_get_dangling_comment(
519        editor: *mut FigEditor,
520        path: *const FigPathSegment,
521        path_len: usize,
522        out_ptr: *mut *const u8,
523        out_len: *mut usize,
524    ) -> FigStatus;
525    pub fn fig_editor_comment_out(
526        editor: *mut FigEditor,
527        path: *const FigPathSegment,
528        path_len: usize,
529    ) -> FigStatus;
530    pub fn fig_editor_uncomment_leading(
531        editor: *mut FigEditor,
532        path: *const FigPathSegment,
533        path_len: usize,
534        first_line: usize,
535        line_count: usize,
536    ) -> FigStatus;
537    pub fn fig_editor_uncomment_dangling(
538        editor: *mut FigEditor,
539        path: *const FigPathSegment,
540        path_len: usize,
541        first_line: usize,
542        line_count: usize,
543    ) -> FigStatus;
544    pub fn fig_editor_insert_key(
545        editor: *mut FigEditor,
546        path: *const FigPathSegment,
547        path_len: usize,
548        key: *const u8,
549        key_len: usize,
550        val: *const u8,
551        val_len: usize,
552    ) -> FigStatus;
553    pub fn fig_editor_delete_key(
554        editor: *mut FigEditor,
555        path: *const FigPathSegment,
556        path_len: usize,
557    ) -> FigStatus;
558    pub fn fig_editor_append_seq(
559        editor: *mut FigEditor,
560        path: *const FigPathSegment,
561        path_len: usize,
562        val: *const u8,
563        val_len: usize,
564    ) -> FigStatus;
565    pub fn fig_editor_prepend_seq(
566        editor: *mut FigEditor,
567        path: *const FigPathSegment,
568        path_len: usize,
569        val: *const u8,
570        val_len: usize,
571    ) -> FigStatus;
572    pub fn fig_editor_remove_seq_item(
573        editor: *mut FigEditor,
574        path: *const FigPathSegment,
575        path_len: usize,
576        index: usize,
577    ) -> FigStatus;
578    pub fn fig_editor_move_key(
579        editor: *mut FigEditor,
580        src_path: *const FigPathSegment,
581        src_path_len: usize,
582        dest_path: *const FigPathSegment,
583        dest_path_len: usize,
584    ) -> FigStatus;
585    pub fn fig_editor_reorder_keys(
586        editor: *mut FigEditor,
587        path: *const FigPathSegment,
588        path_len: usize,
589        keys: *const FigStr,
590        keys_len: usize,
591    ) -> FigStatus;
592    pub fn fig_editor_move_item(
593        editor: *mut FigEditor,
594        path: *const FigPathSegment,
595        path_len: usize,
596        from: usize,
597        to: usize,
598    ) -> FigStatus;
599    pub fn fig_editor_reorder_items(
600        editor: *mut FigEditor,
601        path: *const FigPathSegment,
602        path_len: usize,
603        indices: *const usize,
604        indices_len: usize,
605    ) -> FigStatus;
606    pub fn fig_editor_set_sequence(
607        editor: *mut FigEditor,
608        path: *const FigPathSegment,
609        path_len: usize,
610        items: *const FigStr,
611        items_len: usize,
612    ) -> FigStatus;
613    // Whole-container ops, for containers scattered through the source (a TOML
614    // `[header]` table, an INI `[section]`, a fig block container). The key ops
615    // above cannot address one, and refuse with `INVALID_ARGUMENT` at such a
616    // path. A format that does not support the op answers `UNSUPPORTED_FORMAT`.
617    pub fn fig_editor_delete_container(
618        editor: *mut FigEditor,
619        path: *const FigPathSegment,
620        path_len: usize,
621    ) -> FigStatus;
622    pub fn fig_editor_insert_container(
623        editor: *mut FigEditor,
624        path: *const FigPathSegment,
625        path_len: usize,
626        body: *const u8,
627        body_len: usize,
628    ) -> FigStatus;
629    pub fn fig_editor_rename_container(
630        editor: *mut FigEditor,
631        path: *const FigPathSegment,
632        path_len: usize,
633        new_leaf: *const u8,
634        new_leaf_len: usize,
635    ) -> FigStatus;
636    /// A NULL `dest_path` means "to the end of the document" — distinct from a
637    /// zero-length path, which every other entry point reads as the root.
638    pub fn fig_editor_move_container(
639        editor: *mut FigEditor,
640        src_path: *const FigPathSegment,
641        src_path_len: usize,
642        dest_path: *const FigPathSegment,
643        dest_path_len: usize,
644    ) -> FigStatus;
645    pub fn fig_editor_reorder_containers(
646        editor: *mut FigEditor,
647        order: *const FigStr,
648        order_len: usize,
649    ) -> FigStatus;
650    pub fn fig_editor_append_container_to_seq(
651        editor: *mut FigEditor,
652        path: *const FigPathSegment,
653        path_len: usize,
654        body: *const u8,
655        body_len: usize,
656    ) -> FigStatus;
657    pub fn fig_editor_source(
658        editor: *const FigEditor,
659        out_ptr: *mut *const u8,
660        out_len: *mut usize,
661    ) -> FigStatus;
662
663    pub fn fig_embed_extract(
664        input: *const u8,
665        input_len: usize,
666        embed_type: c_int,
667        out_region: *mut FigRegion,
668    ) -> FigStatus;
669
670    pub fn fig_embed_detect(
671        input: *const u8,
672        input_len: usize,
673        out_embed_type: *mut c_int,
674    ) -> FigStatus;
675
676    /// Re-house an embedded region under a different archetype's fences. On
677    /// `OK` the result is an OWNED buffer — release it with `fig_free`, passing
678    /// back the exact `out_len`. Added in core 2.7.0.
679    pub fn fig_embed_retype(
680        input: *const u8,
681        input_len: usize,
682        from_embed_type: c_int,
683        to_embed_type: c_int,
684        content: *const u8,
685        content_len: usize,
686        out_ptr: *mut *mut u8,
687        out_len: *mut usize,
688    ) -> FigStatus;
689
690    /// Sized free for a buffer fig allocated (`fig_embed_retype`'s result) or
691    /// that the caller obtained from `fig_alloc`. `len` must be exact.
692    pub fn fig_free(ptr: *mut u8, len: usize);
693
694    pub fn fig_embed_open(
695        input: *const u8,
696        input_len: usize,
697        embed_type: c_int,
698        out_embed: *mut *mut FigEmbed,
699    ) -> FigStatus;
700    pub fn fig_embed_open_or_init(
701        input: *const u8,
702        input_len: usize,
703        embed_type: c_int,
704        out_embed: *mut *mut FigEmbed,
705    ) -> FigStatus;
706    pub fn fig_embed_destroy(fm: *mut FigEmbed);
707
708    pub fn fig_embed_replace_val(
709        fm: *mut FigEmbed,
710        path: *const FigPathSegment,
711        path_len: usize,
712        repl: *const u8,
713        repl_len: usize,
714    ) -> FigStatus;
715    pub fn fig_embed_replace_key(
716        fm: *mut FigEmbed,
717        path: *const FigPathSegment,
718        path_len: usize,
719        repl: *const u8,
720        repl_len: usize,
721    ) -> FigStatus;
722    pub fn fig_embed_set(
723        fm: *mut FigEmbed,
724        path: *const FigPathSegment,
725        path_len: usize,
726        val: *const u8,
727        val_len: usize,
728    ) -> FigStatus;
729    pub fn fig_embed_add_leading_comment(
730        fm: *mut FigEmbed,
731        path: *const FigPathSegment,
732        path_len: usize,
733        text: *const u8,
734        text_len: usize,
735    ) -> FigStatus;
736    pub fn fig_embed_set_trailing_comment(
737        fm: *mut FigEmbed,
738        path: *const FigPathSegment,
739        path_len: usize,
740        text: *const u8,
741        text_len: usize,
742    ) -> FigStatus;
743    pub fn fig_embed_delete_leading_comments(
744        fm: *mut FigEmbed,
745        path: *const FigPathSegment,
746        path_len: usize,
747    ) -> FigStatus;
748    pub fn fig_embed_delete_trailing_comment(
749        fm: *mut FigEmbed,
750        path: *const FigPathSegment,
751        path_len: usize,
752    ) -> FigStatus;
753    pub fn fig_embed_get_leading_comment(
754        fm: *mut FigEmbed,
755        path: *const FigPathSegment,
756        path_len: usize,
757        out_ptr: *mut *const u8,
758        out_len: *mut usize,
759    ) -> FigStatus;
760    pub fn fig_embed_get_trailing_comment(
761        fm: *mut FigEmbed,
762        path: *const FigPathSegment,
763        path_len: usize,
764        out_ptr: *mut *const u8,
765        out_len: *mut usize,
766    ) -> FigStatus;
767    pub fn fig_embed_add_dangling_comment(
768        fm: *mut FigEmbed,
769        path: *const FigPathSegment,
770        path_len: usize,
771        text: *const u8,
772        text_len: usize,
773    ) -> FigStatus;
774    pub fn fig_embed_delete_dangling_comments(
775        fm: *mut FigEmbed,
776        path: *const FigPathSegment,
777        path_len: usize,
778    ) -> FigStatus;
779    pub fn fig_embed_get_dangling_comment(
780        fm: *mut FigEmbed,
781        path: *const FigPathSegment,
782        path_len: usize,
783        out_ptr: *mut *const u8,
784        out_len: *mut usize,
785    ) -> FigStatus;
786    pub fn fig_embed_comment_out(
787        fm: *mut FigEmbed,
788        path: *const FigPathSegment,
789        path_len: usize,
790    ) -> FigStatus;
791    pub fn fig_embed_uncomment_leading(
792        fm: *mut FigEmbed,
793        path: *const FigPathSegment,
794        path_len: usize,
795        first_line: usize,
796        line_count: usize,
797    ) -> FigStatus;
798    pub fn fig_embed_uncomment_dangling(
799        fm: *mut FigEmbed,
800        path: *const FigPathSegment,
801        path_len: usize,
802        first_line: usize,
803        line_count: usize,
804    ) -> FigStatus;
805    pub fn fig_embed_insert_key(
806        fm: *mut FigEmbed,
807        path: *const FigPathSegment,
808        path_len: usize,
809        key: *const u8,
810        key_len: usize,
811        val: *const u8,
812        val_len: usize,
813    ) -> FigStatus;
814    pub fn fig_embed_delete_key(
815        fm: *mut FigEmbed,
816        path: *const FigPathSegment,
817        path_len: usize,
818    ) -> FigStatus;
819    pub fn fig_embed_append_seq(
820        fm: *mut FigEmbed,
821        path: *const FigPathSegment,
822        path_len: usize,
823        val: *const u8,
824        val_len: usize,
825    ) -> FigStatus;
826    pub fn fig_embed_prepend_seq(
827        fm: *mut FigEmbed,
828        path: *const FigPathSegment,
829        path_len: usize,
830        val: *const u8,
831        val_len: usize,
832    ) -> FigStatus;
833    pub fn fig_embed_remove_seq_item(
834        fm: *mut FigEmbed,
835        path: *const FigPathSegment,
836        path_len: usize,
837        index: usize,
838    ) -> FigStatus;
839    pub fn fig_embed_move_key(
840        fm: *mut FigEmbed,
841        src_path: *const FigPathSegment,
842        src_path_len: usize,
843        dest_path: *const FigPathSegment,
844        dest_path_len: usize,
845    ) -> FigStatus;
846    pub fn fig_embed_reorder_keys(
847        fm: *mut FigEmbed,
848        path: *const FigPathSegment,
849        path_len: usize,
850        keys: *const FigStr,
851        keys_len: usize,
852    ) -> FigStatus;
853    pub fn fig_embed_move_item(
854        fm: *mut FigEmbed,
855        path: *const FigPathSegment,
856        path_len: usize,
857        from: usize,
858        to: usize,
859    ) -> FigStatus;
860    pub fn fig_embed_reorder_items(
861        fm: *mut FigEmbed,
862        path: *const FigPathSegment,
863        path_len: usize,
864        indices: *const usize,
865        indices_len: usize,
866    ) -> FigStatus;
867    pub fn fig_embed_set_sequence(
868        fm: *mut FigEmbed,
869        path: *const FigPathSegment,
870        path_len: usize,
871        items: *const FigStr,
872        items_len: usize,
873    ) -> FigStatus;
874    pub fn fig_embed_replace_body(fm: *mut FigEmbed, body: *const u8, body_len: usize)
875    -> FigStatus;
876    pub fn fig_embed_render(
877        fm: *mut FigEmbed,
878        out_ptr: *mut *const u8,
879        out_len: *mut usize,
880    ) -> FigStatus;
881}