libredwg-sys 0.15.0

Raw FFI bindings to the LibreDWG C sources (a vendored subset of upstream carrying four local patches, see NOTICE.md), built natively via cc + bindgen (no Emscripten/WASM).
Documentation
//! Raw FFI bindings to the LibreDWG C sources (a vendored subset of the
//! real upstream project at `lib/libredwg`, GPLv3+, carrying five local
//! patches marked `uncad local patch`; see `NOTICE.md` in this crate and
//! docs/THIRD_PARTY_NOTICES.md).
//! Generated by `build.rs` via `bindgen` against the public
//! `dwg.h`/`dwg_api.h` headers plus this crate's own `uncad_*` C shims
//! (see `shim/uncad_shim.h`).
//!
//! This crate is intentionally low-level and `unsafe`-heavy -- it exists to
//! be wrapped by the `uncad` crate, not used directly.
//!
//! # Not thread-safe -- callers must serialize every call themselves
//!
//! The underlying LibreDWG C library has non-reentrant global state (e.g.
//! the `loglevel` global read/written throughout `decode.c`/`bits.c`, and
//! likely more that hasn't been individually catalogued). Calling into any
//! function in this crate concurrently from multiple threads -- even two
//! calls that never touch the same `Dwg_Data`/`Dwg_Object` -- has
//! reproducibly caused `STATUS_HEAP_CORRUPTION` once both threads' work
//! overlapped enough for the shared C-side state to race. **This crate does
//! nothing to prevent that**; every FFI entry point here is exactly as
//! unsynchronized as the C library it binds.
//!
//! The `uncad` crate's own public API (`uncad::parse()` and friends) is
//! safe to call from multiple threads because it serializes every call
//! through a single process-wide `Mutex` before reaching this crate --
//! see `uncad`'s top-level doc comment / `docs/ARCHITECTURE.md`'s "Thread
//! safety" section. Any other consumer of `libredwg-sys` directly must
//! implement that same serialization itself (a single global lock around
//! every call into this crate, held for the call's entire duration) or
//! risk memory corruption under concurrent use.

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
// bindgen emits `mem::transmute(x)` for every bitfield accessor regardless
// of whether the source and target types happen to coincide (they do for
// every current `BITCODE_B`/`_BS`-backed bitfield in dwg.h) -- harmless,
// and not something editing generated code (re-generated fresh on every
// build) could fix. See docs/CAVEATS.md's "Clippy" note.
#![allow(clippy::useless_transmute)]
// Same rationale, for bindgen's generated `BindgenUninitializedField` helper
// (`as_slice`/`as_mut_slice`/`as_ref`/`as_mut`) -- its `unsafe fn`s have no
// `# Safety` doc section because bindgen doesn't emit one, not because this
// crate's own unsafe code is undocumented (see `dynapi.rs` in `uncad` for
// this project's own actual safety-doc convention).
#![allow(clippy::missing_safety_doc)]
// Same rationale again: bindgen's generated helper methods call other
// unsafe functions (`slice::from_raw_parts`, `mem::transmute`) without
// wrapping each one in its own `unsafe { }` block, relying on the whole
// `unsafe fn` body being implicitly unsafe (2021 edition default) --
// harmless and, again, not this crate's own code to restyle.
#![allow(unsafe_op_in_unsafe_fn)]
// bindgen 0.72 changed the bitfield accessors it emits to compute a byte
// offset as `usize` and then cast it to `isize` for `.offset()`. clippy asks
// for `.add()` instead, which is the right advice for hand-written code and
// unactionable here: these bodies are regenerated from dwg.h on every build.
// Same rationale as the three allows above.
#![allow(clippy::ptr_offset_with_cast)]
// bindgen 0.73 emits `(bits + 7) / 8` in the same bitfield accessors, which
// clippy asks to write as `.div_ceil(8)`. Right for hand-written code, and
// unactionable here for the same reason as the allows above: this file is
// regenerated from dwg.h on every build.
#![allow(clippy::manual_div_ceil)]

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

// --- Hand-written struct mirrors ---------------------------------------
//
// bindgen cannot generate real field access for the types below, and this
// crate needs it (see build.rs's blocklist_type calls for the failure mode).
// Each one mirrors dwg.h's field order and types exactly; #[repr(C)] then
// reproduces C's alignment and padding rules, and the compile-time size
// assertions at the end of this section check the result against clang's own
// sizeof() -- a safety net against a transcription mistake here.

/// `_dwg_HATCH_ControlPoint` (dwg.h) -- a SPLINE-type boundary edge's
/// control point.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_HATCH_ControlPoint {
    pub parent: *mut std::ffi::c_void,
    pub point: BITCODE_2RD,
    pub weight: BITCODE_BD,
}

/// `_dwg_HATCH_PathSeg` (dwg.h) -- one edge of a non-polyline HATCH boundary
/// path. Not a real C union despite dwg.h's "could be a union" comment: every
/// field is present regardless of `curve_type`, and only the ones relevant to
/// that curve type are meaningfully populated.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_HATCH_PathSeg {
    pub parent: *mut std::ffi::c_void,
    pub curve_type: BITCODE_RC,
    /* LINE */
    pub first_endpoint: BITCODE_2RD,
    pub second_endpoint: BITCODE_2RD,
    /* CIRCULAR ARC */
    pub center: BITCODE_2RD,
    pub radius: BITCODE_BD,
    pub start_angle: BITCODE_BD,
    pub end_angle: BITCODE_BD,
    pub is_ccw: BITCODE_B,
    /* ELLIPTICAL ARC */
    pub endpoint: BITCODE_2RD,
    pub minor_major_ratio: BITCODE_BD,
    /* SPLINE */
    pub degree: BITCODE_BL,
    pub is_rational: BITCODE_B,
    pub is_periodic: BITCODE_B,
    pub num_knots: BITCODE_BL,
    pub num_control_points: BITCODE_BL,
    pub knots: *mut BITCODE_BD,
    pub control_points: *mut Dwg_HATCH_ControlPoint,
    pub num_fitpts: BITCODE_BL,
    pub fitpts: *mut BITCODE_2RD,
    pub start_tangent: BITCODE_2RD,
    pub end_tangent: BITCODE_2RD,
}

/// `_dwg_HATCH_Path` (dwg.h) -- one HATCH boundary path, either a
/// polyline (`polyline_paths`, when `flag & 0x02`) or a list of curved/
/// straight edges (`segs`).
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_HATCH_Path {
    pub parent: *mut std::ffi::c_void,
    pub flag: BITCODE_BL,
    pub num_segs_or_paths: BITCODE_BL,
    pub segs: *mut Dwg_HATCH_PathSeg,
    pub bulges_present: BITCODE_B,
    pub closed: BITCODE_B,
    pub polyline_paths: *mut Dwg_HATCH_PolylinePath,
    pub num_boundary_handles: BITCODE_BL,
    pub boundary_handles: *mut *mut Dwg_Object_Ref,
}

// _dwg_HATCH_PolylinePath is still bindgen-generated and refers to the raw tag
// name in its `parent` field, so the alias has to exist even though nothing
// else here uses it.
pub type _dwg_HATCH_Path = Dwg_HATCH_Path;

/// `_dwg_HATCH_DefLine` (dwg.h) -- one pattern-fill "definition line": a family
/// of parallel lines (`angle`/`pt0`/`offset`) plus an optional dash pattern
/// (`dashes`: positive = dash length, negative = gap, empty = continuous). One
/// of `Dwg_Entity_HATCH.deflines`.
///
/// `pt0`/`offset` are declared `BITCODE_2BD` in dwg.h but typed `BITCODE_2RD`
/// here: both are two `double`s with no padding, and `BITCODE_2RD` is already
/// bound elsewhere in this crate, so reusing it avoids pulling in a type
/// bindgen would otherwise never generate.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_HATCH_DefLine {
    pub parent: *mut std::ffi::c_void,
    pub angle: BITCODE_BD,
    pub pt0: BITCODE_2RD,
    pub offset: BITCODE_2RD,
    pub num_dashes: BITCODE_BS,
    pub dashes: *mut BITCODE_BD,
}
pub type _dwg_HATCH_DefLine = Dwg_HATCH_DefLine;

/// `_dwg_HATCH_Color` (dwg.h) -- one gradient-fill color stop: `shift_value`
/// (0.0-1.0, its position along the gradient) plus a plain `Dwg_Color`. One of
/// `Dwg_Entity_HATCH.colors`.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_HATCH_Color {
    pub parent: *mut std::ffi::c_void,
    pub shift_value: BITCODE_BD,
    pub color: Dwg_Color,
}
pub type _dwg_HATCH_Color = Dwg_HATCH_Color;

/// `_dwg_MLINE_vertex` (dwg.h). Its `vertex`/`vertex_direction`/
/// `miter_direction` fields are declared `BITCODE_3BD`, which bindgen never
/// generates on its own; `dwg_point_3d` stands in, being the same three
/// `double`s with no padding. `lines` (the per-vertex parallel-line array) is
/// left as an untyped `*mut c_void` because nothing dereferences it, which
/// saves hand-writing `Dwg_MLINE_line` as well.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_MLINE_vertex {
    pub parent: *mut std::ffi::c_void,
    pub vertex: dwg_point_3d,
    pub vertex_direction: dwg_point_3d,
    pub miter_direction: dwg_point_3d,
    pub num_lines: BITCODE_RC,
    pub lines: *mut std::ffi::c_void,
}

/// `_dwg_MLINESTYLE_line` (dwg.h) -- one parallel-line definition in an
/// MLINESTYLE object: `offset` (distance from the MLINE centerline, combined
/// with each vertex's `miter_direction` to get that line's actual point) plus
/// `color`/`lt_index`/`lt_ltype`, none of which this workspace renders.
/// `lt_ltype` is typed properly rather than left opaque, `Dwg_Object_Ref`
/// already being a bound type here.
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Dwg_MLINESTYLE_line {
    pub parent: *mut std::ffi::c_void,
    pub offset: BITCODE_BD,
    pub color: Dwg_Color,
    pub lt_index: BITCODE_BSd,
    pub lt_ltype: *mut Dwg_Object_Ref,
}
pub type _dwg_MLINESTYLE_line = Dwg_MLINESTYLE_line;

#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of Dwg_HATCH_ControlPoint"][std::mem::size_of::<Dwg_HATCH_ControlPoint>() - 32];
    ["Size of Dwg_HATCH_PathSeg"][std::mem::size_of::<Dwg_HATCH_PathSeg>() - 200];
    ["Size of Dwg_HATCH_Path"][std::mem::size_of::<Dwg_HATCH_Path>() - 56];
    ["Size of Dwg_HATCH_DefLine"][std::mem::size_of::<Dwg_HATCH_DefLine>() - 64];
    ["Size of Dwg_HATCH_Color"][std::mem::size_of::<Dwg_HATCH_Color>() - 64];
    ["Size of Dwg_MLINE_vertex"][std::mem::size_of::<Dwg_MLINE_vertex>() - 96];
    ["Size of Dwg_MLINESTYLE_line"][std::mem::size_of::<Dwg_MLINESTYLE_line>() - 80];
};