libredwg_sys/lib.rs
1//! Raw FFI bindings to the LibreDWG C sources (vendored, unmodified, from
2//! the real upstream project at `lib/libredwg`, GPLv3+; see
3//! docs/THIRD_PARTY_NOTICES.md).
4//! Generated by `build.rs` via `bindgen` against the public
5//! `dwg.h`/`dwg_api.h` headers plus this crate's own `uncad_*` C shims
6//! (see `shim/uncad_shim.h`).
7//!
8//! This crate is intentionally low-level and `unsafe`-heavy -- it exists to
9//! be wrapped by the `uncad` crate, not used directly.
10//!
11//! # Not thread-safe -- callers must serialize every call themselves
12//!
13//! The underlying LibreDWG C library has non-reentrant global state (e.g.
14//! the `loglevel` global read/written throughout `decode.c`/`bits.c`, and
15//! likely more that hasn't been individually catalogued). Calling into any
16//! function in this crate concurrently from multiple threads -- even two
17//! calls that never touch the same `Dwg_Data`/`Dwg_Object` -- has
18//! reproducibly caused `STATUS_HEAP_CORRUPTION` once both threads' work
19//! overlapped enough for the shared C-side state to race. **This crate does
20//! nothing to prevent that**; every FFI entry point here is exactly as
21//! unsynchronized as the C library it binds.
22//!
23//! The `uncad` crate's own public API (`uncad::parse()` and friends) is
24//! safe to call from multiple threads because it serializes every call
25//! through a single process-wide `Mutex` before reaching this crate --
26//! see `uncad`'s top-level doc comment / `docs/ARCHITECTURE.md`'s "Thread
27//! safety" section. Any other consumer of `libredwg-sys` directly must
28//! implement that same serialization itself (a single global lock around
29//! every call into this crate, held for the call's entire duration) or
30//! risk memory corruption under concurrent use.
31
32#![allow(non_upper_case_globals)]
33#![allow(non_camel_case_types)]
34#![allow(non_snake_case)]
35#![allow(dead_code)]
36// bindgen emits `mem::transmute(x)` for every bitfield accessor regardless
37// of whether the source and target types happen to coincide (they do for
38// every current `BITCODE_B`/`_BS`-backed bitfield in dwg.h) -- harmless,
39// and not something editing generated code (re-generated fresh on every
40// build) could fix. See docs/CAVEATS.md's "Clippy" note.
41#![allow(clippy::useless_transmute)]
42// Same rationale, for bindgen's generated `BindgenUninitializedField` helper
43// (`as_slice`/`as_mut_slice`/`as_ref`/`as_mut`) -- its `unsafe fn`s have no
44// `# Safety` doc section because bindgen doesn't emit one, not because this
45// crate's own unsafe code is undocumented (see `dynapi.rs` in `uncad` for
46// this project's own actual safety-doc convention).
47#![allow(clippy::missing_safety_doc)]
48// Same rationale again: bindgen's generated helper methods call other
49// unsafe functions (`slice::from_raw_parts`, `mem::transmute`) without
50// wrapping each one in its own `unsafe { }` block, relying on the whole
51// `unsafe fn` body being implicitly unsafe (2021 edition default) --
52// harmless and, again, not this crate's own code to restyle.
53#![allow(unsafe_op_in_unsafe_fn)]
54// bindgen 0.72 changed the bitfield accessors it emits to compute a byte
55// offset as `usize` and then cast it to `isize` for `.offset()`. clippy asks
56// for `.add()` instead, which is the right advice for hand-written code and
57// unactionable here: these bodies are regenerated from dwg.h on every build.
58// Same rationale as the three allows above.
59#![allow(clippy::ptr_offset_with_cast)]
60
61include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
62
63// --- Hand-written struct mirrors ---------------------------------------
64//
65// bindgen cannot generate real field access for the types below, and this
66// crate needs it (see build.rs's blocklist_type calls for the failure mode).
67// Each one mirrors dwg.h's field order and types exactly; #[repr(C)] then
68// reproduces C's alignment and padding rules, and the compile-time size
69// assertions at the end of this section check the result against clang's own
70// sizeof() -- a safety net against a transcription mistake here.
71
72/// `_dwg_HATCH_ControlPoint` (dwg.h) -- a SPLINE-type boundary edge's
73/// control point.
74#[repr(C)]
75#[derive(Debug, Clone, Copy)]
76pub struct Dwg_HATCH_ControlPoint {
77 pub parent: *mut std::ffi::c_void,
78 pub point: BITCODE_2RD,
79 pub weight: BITCODE_BD,
80}
81
82/// `_dwg_HATCH_PathSeg` (dwg.h) -- one edge of a non-polyline HATCH boundary
83/// path. Not a real C union despite dwg.h's "could be a union" comment: every
84/// field is present regardless of `curve_type`, and only the ones relevant to
85/// that curve type are meaningfully populated.
86#[repr(C)]
87#[derive(Debug, Clone, Copy)]
88pub struct Dwg_HATCH_PathSeg {
89 pub parent: *mut std::ffi::c_void,
90 pub curve_type: BITCODE_RC,
91 /* LINE */
92 pub first_endpoint: BITCODE_2RD,
93 pub second_endpoint: BITCODE_2RD,
94 /* CIRCULAR ARC */
95 pub center: BITCODE_2RD,
96 pub radius: BITCODE_BD,
97 pub start_angle: BITCODE_BD,
98 pub end_angle: BITCODE_BD,
99 pub is_ccw: BITCODE_B,
100 /* ELLIPTICAL ARC */
101 pub endpoint: BITCODE_2RD,
102 pub minor_major_ratio: BITCODE_BD,
103 /* SPLINE */
104 pub degree: BITCODE_BL,
105 pub is_rational: BITCODE_B,
106 pub is_periodic: BITCODE_B,
107 pub num_knots: BITCODE_BL,
108 pub num_control_points: BITCODE_BL,
109 pub knots: *mut BITCODE_BD,
110 pub control_points: *mut Dwg_HATCH_ControlPoint,
111 pub num_fitpts: BITCODE_BL,
112 pub fitpts: *mut BITCODE_2RD,
113 pub start_tangent: BITCODE_2RD,
114 pub end_tangent: BITCODE_2RD,
115}
116
117/// `_dwg_HATCH_Path` (dwg.h) -- one HATCH boundary path, either a
118/// polyline (`polyline_paths`, when `flag & 0x02`) or a list of curved/
119/// straight edges (`segs`).
120#[repr(C)]
121#[derive(Debug, Clone, Copy)]
122pub struct Dwg_HATCH_Path {
123 pub parent: *mut std::ffi::c_void,
124 pub flag: BITCODE_BL,
125 pub num_segs_or_paths: BITCODE_BL,
126 pub segs: *mut Dwg_HATCH_PathSeg,
127 pub bulges_present: BITCODE_B,
128 pub closed: BITCODE_B,
129 pub polyline_paths: *mut Dwg_HATCH_PolylinePath,
130 pub num_boundary_handles: BITCODE_BL,
131 pub boundary_handles: *mut *mut Dwg_Object_Ref,
132}
133
134// _dwg_HATCH_PolylinePath is still bindgen-generated and refers to the raw tag
135// name in its `parent` field, so the alias has to exist even though nothing
136// else here uses it.
137pub type _dwg_HATCH_Path = Dwg_HATCH_Path;
138
139/// `_dwg_HATCH_DefLine` (dwg.h) -- one pattern-fill "definition line": a family
140/// of parallel lines (`angle`/`pt0`/`offset`) plus an optional dash pattern
141/// (`dashes`: positive = dash length, negative = gap, empty = continuous). One
142/// of `Dwg_Entity_HATCH.deflines`.
143///
144/// `pt0`/`offset` are declared `BITCODE_2BD` in dwg.h but typed `BITCODE_2RD`
145/// here: both are two `double`s with no padding, and `BITCODE_2RD` is already
146/// bound elsewhere in this crate, so reusing it avoids pulling in a type
147/// bindgen would otherwise never generate.
148#[repr(C)]
149#[derive(Debug, Clone, Copy)]
150pub struct Dwg_HATCH_DefLine {
151 pub parent: *mut std::ffi::c_void,
152 pub angle: BITCODE_BD,
153 pub pt0: BITCODE_2RD,
154 pub offset: BITCODE_2RD,
155 pub num_dashes: BITCODE_BS,
156 pub dashes: *mut BITCODE_BD,
157}
158pub type _dwg_HATCH_DefLine = Dwg_HATCH_DefLine;
159
160/// `_dwg_HATCH_Color` (dwg.h) -- one gradient-fill color stop: `shift_value`
161/// (0.0-1.0, its position along the gradient) plus a plain `Dwg_Color`. One of
162/// `Dwg_Entity_HATCH.colors`.
163#[repr(C)]
164#[derive(Debug, Clone, Copy)]
165pub struct Dwg_HATCH_Color {
166 pub parent: *mut std::ffi::c_void,
167 pub shift_value: BITCODE_BD,
168 pub color: Dwg_Color,
169}
170pub type _dwg_HATCH_Color = Dwg_HATCH_Color;
171
172/// `_dwg_MLINE_vertex` (dwg.h). Its `vertex`/`vertex_direction`/
173/// `miter_direction` fields are declared `BITCODE_3BD`, which bindgen never
174/// generates on its own; `dwg_point_3d` stands in, being the same three
175/// `double`s with no padding. `lines` (the per-vertex parallel-line array) is
176/// left as an untyped `*mut c_void` because nothing dereferences it, which
177/// saves hand-writing `Dwg_MLINE_line` as well.
178#[repr(C)]
179#[derive(Debug, Clone, Copy)]
180pub struct Dwg_MLINE_vertex {
181 pub parent: *mut std::ffi::c_void,
182 pub vertex: dwg_point_3d,
183 pub vertex_direction: dwg_point_3d,
184 pub miter_direction: dwg_point_3d,
185 pub num_lines: BITCODE_RC,
186 pub lines: *mut std::ffi::c_void,
187}
188
189/// `_dwg_MLINESTYLE_line` (dwg.h) -- one parallel-line definition in an
190/// MLINESTYLE object: `offset` (distance from the MLINE centerline, combined
191/// with each vertex's `miter_direction` to get that line's actual point) plus
192/// `color`/`lt_index`/`lt_ltype`, none of which this workspace renders.
193/// `lt_ltype` is typed properly rather than left opaque, `Dwg_Object_Ref`
194/// already being a bound type here.
195#[repr(C)]
196#[derive(Debug, Clone, Copy)]
197pub struct Dwg_MLINESTYLE_line {
198 pub parent: *mut std::ffi::c_void,
199 pub offset: BITCODE_BD,
200 pub color: Dwg_Color,
201 pub lt_index: BITCODE_BSd,
202 pub lt_ltype: *mut Dwg_Object_Ref,
203}
204pub type _dwg_MLINESTYLE_line = Dwg_MLINESTYLE_line;
205
206#[allow(clippy::unnecessary_operation, clippy::identity_op)]
207const _: () = {
208 ["Size of Dwg_HATCH_ControlPoint"][std::mem::size_of::<Dwg_HATCH_ControlPoint>() - 32];
209 ["Size of Dwg_HATCH_PathSeg"][std::mem::size_of::<Dwg_HATCH_PathSeg>() - 200];
210 ["Size of Dwg_HATCH_Path"][std::mem::size_of::<Dwg_HATCH_Path>() - 56];
211 ["Size of Dwg_HATCH_DefLine"][std::mem::size_of::<Dwg_HATCH_DefLine>() - 64];
212 ["Size of Dwg_HATCH_Color"][std::mem::size_of::<Dwg_HATCH_Color>() - 64];
213 ["Size of Dwg_MLINE_vertex"][std::mem::size_of::<Dwg_MLINE_vertex>() - 96];
214 ["Size of Dwg_MLINESTYLE_line"][std::mem::size_of::<Dwg_MLINESTYLE_line>() - 80];
215};