Skip to main content

spice/core/
raw.rs

1/*!
2A Rust idiomatic CSPICE wrapper built with [procedural macros][`spice_derive`].
3
4## Description
5
6Every routine here mirrors its CSPICE counterpart one for one: the C inputs stay inputs, and the
7values the C routine writes through pointers become the Rust return value, in the order CSPICE
8declares them. Wrappers that need an explicit buffer size, or a caller allocated
9[cell][crate::core::cell::Cell], have a friendlier counterpart in [`neat`][crate::core::neat].
10*/
11
12use crate::c::{SpiceChar, SpiceDouble, SpiceInt};
13use crate::core::cell::{Cell, CellItem};
14use crate::core::ffi::{from_cbuf, from_strided, to_cstring, to_strided};
15use crate::core::ffi::{UdBail, UdFunb, UdFunc, UdFuns, UdRefn, UdRepf, UdRepi, UdRepu, UdStep};
16use spice_derive::cspice_proc;
17
18#[cfg(any(feature = "lock", doc))]
19use {crate::core::lock::SpiceLock, spice_derive::impl_for};
20
21/// A DLA segment descriptor.
22#[allow(clippy::upper_case_acronyms)]
23pub type DLADSC = crate::c::SpiceDLADescr;
24
25/// A DSK segment descriptor.
26#[allow(clippy::upper_case_acronyms)]
27pub type DSKDSC = crate::c::SpiceDSKDescr;
28
29/// A plane, as a unit normal and the constant of the plane equation.
30#[allow(clippy::upper_case_acronyms)]
31pub type PLANE = crate::c::SpicePlane;
32
33/// An ellipse, as a centre and two generating vectors.
34#[allow(clippy::upper_case_acronyms)]
35pub type ELLIPSE = crate::c::SpiceEllipse;
36
37/// The raw CSPICE cell descriptor; see [`Cell`] for the owning Rust type.
38#[allow(clippy::upper_case_acronyms, dead_code)]
39pub type CELL = crate::c::SpiceCell;
40
41/* -------------------------------------------------------------------------------------------- */
42/* Bodies, names and identifiers                                                                  */
43/* -------------------------------------------------------------------------------------------- */
44
45cspice_proc! {
46    /**
47    Translate the SPICE integer code of a body into a common name for that body.
48
49    This function has a [neat version][crate::neat::bodc2n].
50    */
51    pub fn bodc2n(code: i32, #[lenout] lenout: i32) -> (String, bool) {}
52}
53
54cspice_proc! {
55    /**
56    Translate a body ID code to either the corresponding name or, if no name exists, the string
57    representation of the code.
58
59    This function has a [neat version][crate::neat::bodc2s].
60    */
61    pub fn bodc2s(code: i32, #[lenout] lenout: i32) -> String {}
62}
63
64cspice_proc! {
65    /**
66    Determine whether values exist for some item for any body in the kernel pool.
67    */
68    #[return_output]
69    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
70    pub fn bodfnd(body: i32, item: &str) -> bool {}
71}
72
73cspice_proc! {
74    /**
75    Translate the name of a body or object to the corresponding SPICE integer ID code.
76    */
77    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
78    pub fn bodn2c(name: &str) -> (i32, bool) {}
79}
80
81cspice_proc! {
82    /**
83    Translate a string containing a body name or ID code to an integer code.
84    */
85    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
86    pub fn bods2c(name: &str) -> (i32, bool) {}
87}
88
89/**
90Fetch from the kernel pool the double precision values of an item associated with a body.
91
92At most `maxn` values are returned; the vector is truncated to the number actually found, and is
93empty when the item is not in the pool.
94*/
95#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
96pub fn bodvrd(bodynm: &str, item: &str, maxn: usize) -> Vec<f64> {
97    let bodynm = to_cstring(bodynm);
98    let item = to_cstring(item);
99    let mut dim = 0;
100    let mut values = vec![0.0; maxn];
101    unsafe {
102        crate::c::bodvrd_c(
103            bodynm.as_ptr() as *mut SpiceChar,
104            item.as_ptr() as *mut SpiceChar,
105            maxn as SpiceInt,
106            &mut dim,
107            values.as_mut_ptr(),
108        )
109    };
110    values.truncate(dim.max(0) as usize);
111    values
112}
113
114/**
115Fetch from the kernel pool the double precision values of an item associated with a body.
116
117Deprecated by CSPICE in favour of [`bodvcd`] and [`bodvrd`]: it takes no bound on how much it may
118write, so the caller has to know how many values to make room for.
119*/
120#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
121pub fn bodvar(body: i32, item: &str, maxn: usize) -> Vec<f64> {
122    let item = to_cstring(item);
123    let mut dim = 0;
124    let mut values = vec![0.0; maxn];
125    unsafe {
126        crate::c::bodvar_c(
127            body,
128            item.as_ptr() as *mut SpiceChar,
129            &mut dim,
130            values.as_mut_ptr(),
131        )
132    };
133    values.truncate(dim.max(0) as usize);
134    values
135}
136
137/**
138Fetch from the kernel pool the double precision values of an item associated with a body, using the
139body's integer ID code.
140*/
141#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
142pub fn bodvcd(bodyid: i32, item: &str, maxn: usize) -> Vec<f64> {
143    let item = to_cstring(item);
144    let mut dim = 0;
145    let mut values = vec![0.0; maxn];
146    unsafe {
147        crate::c::bodvcd_c(
148            bodyid,
149            item.as_ptr() as *mut SpiceChar,
150            maxn as SpiceInt,
151            &mut dim,
152            values.as_mut_ptr(),
153        )
154    };
155    values.truncate(dim.max(0) as usize);
156    values
157}
158
159/* -------------------------------------------------------------------------------------------- */
160/* C-kernels                                                                                      */
161/* -------------------------------------------------------------------------------------------- */
162
163cspice_proc! {
164    /**
165    Find the coverage window for a specified object in a specified CK file.
166
167    This function has a [neat version][crate::neat::ckcov].
168    */
169    #[allow(clippy::too_many_arguments)]
170    pub fn ckcov(
171        ck: &str,
172        idcode: i32,
173        needav: bool,
174        level: &str,
175        tol: f64,
176        timsys: &str,
177        cover: &mut Cell<f64>
178    ) {}
179}
180
181cspice_proc! {
182    /**
183    Get pointing (attitude) for a specified spacecraft clock time.
184    */
185    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
186    pub fn ckgp(inst: i32, sclkdp: f64, tol: f64, frame: &str) -> ([[f64; 3]; 3], f64, bool) {}
187}
188
189cspice_proc! {
190    /**
191    Get pointing (attitude) and angular velocity for a spacecraft clock time.
192    */
193    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
194    pub fn ckgpav(
195        inst: i32,
196        sclkdp: f64,
197        tol: f64,
198        frame: &str
199    ) -> ([[f64; 3]; 3], [f64; 3], f64, bool) {
200    }
201}
202
203cspice_proc! {
204    /**
205    Find the set of ID codes of all objects in a specified CK file.
206
207    This function has a [neat version][crate::neat::ckobj].
208    */
209    pub fn ckobj(ck: &str, ids: &mut Cell<i32>) {}
210}
211
212cspice_proc! {
213    /**
214    Open a new CK file, returning the handle of the opened file.
215    */
216    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
217    pub fn ckopn(fname: &str, ifname: &str, ncomch: i32) -> i32 {}
218}
219
220cspice_proc! {
221    /**
222    Close an open CK file.
223    */
224    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
225    pub fn ckcls(handle: i32) {}
226}
227
228/**
229Add a type 3 segment to a CK file.
230
231# Panics
232
233Panics if `nrec` or `nints` is negative, or larger than the arrays it counts: CSPICE reads exactly
234that many records and has no way of knowing how long they are.
235*/
236#[allow(clippy::too_many_arguments)]
237#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
238pub fn ckw03(
239    handle: i32,
240    begtim: f64,
241    endtim: f64,
242    inst: i32,
243    frame: &str,
244    avflag: bool,
245    segid: &str,
246    nrec: i32,
247    sclkdp: &[f64],
248    quats: &[[f64; 4]],
249    avvs: &[[f64; 3]],
250    nints: i32,
251    starts: &[f64],
252) {
253    let records = usize::try_from(nrec).expect("the number of records cannot be negative");
254    let intervals = usize::try_from(nints).expect("the number of intervals cannot be negative");
255    assert!(
256        records <= sclkdp.len() && records <= quats.len(),
257        "ckw03 was asked for {records} records but got {} clock times and {} quaternions",
258        sclkdp.len(),
259        quats.len()
260    );
261    assert!(
262        !avflag || records <= avvs.len(),
263        "ckw03 was asked for {records} angular velocities but got {}",
264        avvs.len()
265    );
266    assert!(
267        intervals <= starts.len(),
268        "ckw03 was asked for {intervals} intervals but got {} start times",
269        starts.len()
270    );
271
272    let frame = to_cstring(frame);
273    let segid = to_cstring(segid);
274
275    unsafe {
276        crate::c::ckw03_c(
277            handle,
278            begtim,
279            endtim,
280            inst,
281            frame.as_ptr() as *mut SpiceChar,
282            avflag as crate::c::SpiceBoolean,
283            segid.as_ptr() as *mut SpiceChar,
284            nrec,
285            sclkdp.as_ptr() as *mut SpiceDouble,
286            quats.as_ptr() as *mut [SpiceDouble; 4],
287            avvs.as_ptr() as *mut [SpiceDouble; 3],
288            nints,
289            starts.as_ptr() as *mut SpiceDouble,
290        );
291    }
292}
293
294/* -------------------------------------------------------------------------------------------- */
295/* DAS, DLA and DSK                                                                               */
296/* -------------------------------------------------------------------------------------------- */
297
298cspice_proc! {
299    /**
300    Close a DAS file.
301    */
302    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
303    pub fn dascls(handle: i32) {}
304}
305
306cspice_proc! {
307    /**
308    Open a DAS file for reading.
309    */
310    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
311    pub fn dasopr(fname: &str) -> i32 {}
312}
313
314cspice_proc! {
315    /**
316    Begin a forward segment search in a DLA file.
317    */
318    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
319    pub fn dlabfs(handle: i32) -> (DLADSC, bool) {}
320}
321
322cspice_proc! {
323    /**
324    Begin a backward segment search in a DLA file.
325    */
326    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
327    pub fn dlabbs(handle: i32) -> (DLADSC, bool) {}
328}
329
330cspice_proc! {
331    /**
332    Find the segment following a specified segment in a DLA file.
333    */
334    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
335    pub fn dlafns(handle: i32, dladsc: DLADSC) -> (DLADSC, bool) {}
336}
337
338cspice_proc! {
339    /**
340    Return the DSK descriptor from a DSK segment identified by a DAS handle and DLA descriptor.
341    */
342    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
343    pub fn dskgd(handle: i32, dladsc: DLADSC) -> DSKDSC {}
344}
345
346cspice_proc! {
347    /**
348    Compute the unit normal vector for a specified plate from a type 2 DSK segment.
349    */
350    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
351    pub fn dskn02(handle: i32, dladsc: DLADSC, plid: i32) -> [f64; 3] {}
352}
353
354cspice_proc! {
355    /**
356    Find the set of body ID codes of all objects for which topographic data are provided in a
357    specified DSK file.
358
359    This function has a [neat version][crate::neat::dskobj].
360    */
361    pub fn dskobj(dsk: &str, bodids: &mut Cell<i32>) {}
362}
363
364cspice_proc! {
365    /**
366    Find the set of surface ID codes for all surfaces associated with a given body in a specified
367    DSK file.
368
369    This function has a [neat version][crate::neat::dsksrf].
370    */
371    pub fn dsksrf(dsk: &str, bodyid: i32, srfids: &mut Cell<i32>) {}
372}
373
374/**
375Fetch triangular plates from a type 2 DSK segment.
376
377This function has a [neat version][crate::neat::dskp02].
378*/
379pub fn dskp02(handle: i32, dladsc: DLADSC, start: usize, room: usize) -> Vec<[i32; 3]> {
380    let mut dladsc = dladsc;
381    let mut n = 0;
382    let mut plates = vec![[0; 3]; room];
383
384    unsafe {
385        crate::c::dskp02_c(
386            handle,
387            &mut dladsc,
388            start as SpiceInt,
389            room as SpiceInt,
390            &mut n,
391            plates.as_mut_ptr(),
392        );
393    }
394
395    plates.truncate(n.max(0) as usize);
396    plates
397}
398
399/**
400Fetch vertices from a type 2 DSK segment.
401
402This function has a [neat version][crate::neat::dskv02].
403*/
404pub fn dskv02(handle: i32, dladsc: DLADSC, start: usize, room: usize) -> Vec<[f64; 3]> {
405    let mut dladsc = dladsc;
406    let mut n = 0;
407    let mut vrtces = vec![[0.0; 3]; room];
408
409    unsafe {
410        crate::c::dskv02_c(
411            handle,
412            &mut dladsc,
413            start as SpiceInt,
414            room as SpiceInt,
415            &mut n,
416            vrtces.as_mut_ptr(),
417        );
418    }
419
420    vrtces.truncate(n.max(0) as usize);
421    vrtces
422}
423
424cspice_proc! {
425    /**
426    Determine the plate ID and body-fixed coordinates of the intersection of a specified ray with
427    the surface defined by a type 2 DSK plate model.
428    */
429    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
430    pub fn dskx02(
431        handle: i32,
432        dladsc: DLADSC,
433        vertex: [f64; 3],
434        raydir: [f64; 3]
435    ) -> (i32, [f64; 3], bool) {
436    }
437}
438
439cspice_proc! {
440    /**
441    Return plate model size parameters---vertex count and plate count---for a type 2 DSK segment.
442
443    Vertices first, plates second.
444    */
445    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
446    pub fn dskz02(handle: i32, dladsc: DLADSC) -> (i32, i32) {}
447}
448
449/// Size of the `dc` output of [`dskxsi`].
450pub const DSKXSI_DCSIZE: usize = 1;
451/// Size of the `ic` output of [`dskxsi`]; for a type 2 segment `ic[0]` is the plate ID.
452pub const DSKXSI_ICSIZE: usize = 1;
453
454/**
455Compute a ray-surface intercept using data provided by multiple loaded DSK segments, and return
456information about the source of the data defining the surface on which the intercept was found.
457
458`srflst` is the list of surface IDs to consider; leave it empty to let CSPICE choose.
459*/
460#[allow(clippy::too_many_arguments, clippy::type_complexity)]
461#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
462pub fn dskxsi(
463    pri: bool,
464    target: &str,
465    srflst: &[i32],
466    et: f64,
467    fixref: &str,
468    vertex: [f64; 3],
469    raydir: [f64; 3],
470) -> (
471    [f64; 3],
472    i32,
473    DLADSC,
474    DSKDSC,
475    [f64; DSKXSI_DCSIZE],
476    [i32; DSKXSI_ICSIZE],
477    bool,
478) {
479    let target = to_cstring(target);
480    let fixref = to_cstring(fixref);
481
482    let mut xpt = [0.0; 3];
483    let mut handle = 0;
484    // SAFETY: both descriptors are plain old data, for which all-zero is a valid value.
485    let mut dladsc: DLADSC = unsafe { std::mem::zeroed() };
486    let mut dskdsc: DSKDSC = unsafe { std::mem::zeroed() };
487    let mut dc = [0.0; DSKXSI_DCSIZE];
488    let mut ic = [0; DSKXSI_ICSIZE];
489    let mut found = 0;
490
491    unsafe {
492        crate::c::dskxsi_c(
493            pri as crate::c::SpiceBoolean,
494            target.as_ptr() as *mut SpiceChar,
495            srflst.len() as SpiceInt,
496            srflst.as_ptr() as *mut SpiceInt,
497            et,
498            fixref.as_ptr() as *mut SpiceChar,
499            vertex.as_ptr() as *mut SpiceDouble,
500            raydir.as_ptr() as *mut SpiceDouble,
501            DSKXSI_DCSIZE as SpiceInt,
502            DSKXSI_ICSIZE as SpiceInt,
503            xpt.as_mut_ptr(),
504            &mut handle,
505            &mut dladsc,
506            &mut dskdsc,
507            dc.as_mut_ptr(),
508            ic.as_mut_ptr(),
509            &mut found,
510        );
511    }
512
513    (xpt, handle, dladsc, dskdsc, dc, ic, found != 0)
514}
515
516/**
517Compute ray-surface intercepts for a set of rays, using data provided by multiple loaded DSK
518segments.
519
520Returns one intercept and one flag per ray.
521*/
522#[allow(clippy::too_many_arguments)]
523#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
524pub fn dskxv(
525    pri: bool,
526    target: &str,
527    srflst: &[i32],
528    et: f64,
529    fixref: &str,
530    vtxarr: &[[f64; 3]],
531    dirarr: &[[f64; 3]],
532) -> (Vec<[f64; 3]>, Vec<bool>) {
533    let rays = vtxarr.len().min(dirarr.len());
534    let target = to_cstring(target);
535    let fixref = to_cstring(fixref);
536
537    let mut xptarr = vec![[0.0; 3]; rays];
538    let mut fndarr = vec![0 as crate::c::SpiceBoolean; rays];
539
540    unsafe {
541        crate::c::dskxv_c(
542            pri as crate::c::SpiceBoolean,
543            target.as_ptr() as *mut SpiceChar,
544            srflst.len() as SpiceInt,
545            srflst.as_ptr() as *mut SpiceInt,
546            et,
547            fixref.as_ptr() as *mut SpiceChar,
548            rays as SpiceInt,
549            vtxarr.as_ptr() as *mut [f64; 3],
550            dirarr.as_ptr() as *mut [f64; 3],
551            xptarr.as_mut_ptr(),
552            fndarr.as_mut_ptr(),
553        );
554    }
555
556    (xptarr, fndarr.into_iter().map(|flag| flag != 0).collect())
557}
558
559cspice_proc! {
560    /**
561    Open a new DSK file for subsequent write operations.
562    */
563    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
564    pub fn dskopn(fname: &str, ifname: &str, ncomch: i32) -> i32 {}
565}
566
567cspice_proc! {
568    /**
569    Close a DSK file, optionally segregating it for faster access.
570    */
571    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
572    pub fn dskcls(handle: i32, optmiz: bool) {}
573}
574
575/// Keyword of the plate expansion fraction, for [`dskgtl`] and [`dskstl`].
576pub const DSK_KEYXFR: i32 = 1;
577/// Keyword of the greedy segment selection factor.
578pub const DSK_KEYSGR: i32 = 2;
579/// Keyword of the segment pad margin.
580pub const DSK_KEYSPM: i32 = 3;
581/// Keyword of the surface point membership margin.
582pub const DSK_KEYPTM: i32 = 4;
583/// Keyword of the angular rounding margin.
584pub const DSK_KEYAMG: i32 = 5;
585/// Keyword of the longitude alias margin.
586pub const DSK_KEYLAL: i32 = 6;
587
588cspice_proc! {
589    /**
590    Retrieve the value of a specified DSK tolerance or margin parameter.
591
592    The keyword is one of the `DSK_KEY*` constants of this module.
593    */
594    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
595    pub fn dskgtl(keywrd: i32) -> f64 {}
596}
597
598cspice_proc! {
599    /**
600    Set the value of a specified DSK tolerance or margin parameter.
601    */
602    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
603    pub fn dskstl(keywrd: i32, dpval: f64) {}
604}
605
606/// Type 2 DSK keywords for [`dskd02`] and [`dski02`]; each belongs to one of the two.
607pub mod dsk02 {
608    /// Number of vertices in the model, an integer item.
609    pub const KWNV: i32 = 1;
610    /// Number of plates in the model, an integer item.
611    pub const KWNP: i32 = 2;
612    /// Total number of voxels in the fine grid, an integer item.
613    pub const KWNVXT: i32 = 3;
614    /// Voxel grid extent, an integer item.
615    pub const KWVGRX: i32 = 4;
616    /// Coarse voxel grid scale, an integer item.
617    pub const KWCGSC: i32 = 5;
618    /// Size of the voxel to plate pointer array, an integer item.
619    pub const KWVXPS: i32 = 6;
620    /// Voxel-plate correspondence list size, an integer item.
621    pub const KWVXLS: i32 = 7;
622    /// Vertex-plate correspondence list size, an integer item.
623    pub const KWVTLS: i32 = 8;
624    /// Plate array, an integer item.
625    pub const KWPLAT: i32 = 9;
626    /// Voxel-plate pointer list, an integer item.
627    pub const KWVXPT: i32 = 10;
628    /// Voxel-plate correspondence list, an integer item.
629    pub const KWVXPL: i32 = 11;
630    /// Vertex-plate pointer list, an integer item.
631    pub const KWVTPT: i32 = 12;
632    /// Vertex-plate correspondence list, an integer item.
633    pub const KWVTPL: i32 = 13;
634    /// Coarse voxel grid pointers, an integer item.
635    pub const KWCGPT: i32 = 14;
636    /// The segment descriptor, a double precision item.
637    pub const KWDSC: i32 = 15;
638    /// Vertex bounds, a double precision item.
639    pub const KWVTBD: i32 = 16;
640    /// Voxel grid origin, a double precision item.
641    pub const KWVXOR: i32 = 17;
642    /// Voxel size, a double precision item.
643    pub const KWVXSZ: i32 = 18;
644    /// Vertex coordinates, a double precision item.
645    pub const KWVERT: i32 = 19;
646}
647
648/// Size of the double precision component of a type 2 DSK spatial index.
649pub const DSK02_SPADSZ: usize = 10;
650
651/**
652Make a spatial index for a DSK type 2 segment, returning its double precision and integer
653components.
654
655`spxisz` is the size to allocate for the integer component; see the
656[C documentation](https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/dskmi2_c.html) for how to
657size it and the work array.
658*/
659#[allow(clippy::too_many_arguments)]
660#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
661pub fn dskmi2(
662    vrtces: &[[f64; 3]],
663    plates: &[[i32; 3]],
664    finscl: f64,
665    corscl: i32,
666    worksz: usize,
667    voxpsz: usize,
668    voxlsz: usize,
669    makvtl: bool,
670    spxisz: usize,
671) -> (Vec<f64>, Vec<i32>) {
672    let mut work = vec![[0; 2]; worksz.max(1)];
673    let mut spaixd = vec![0.0; DSK02_SPADSZ];
674    let mut spaixi = vec![0; spxisz.max(1)];
675
676    unsafe {
677        crate::c::dskmi2_c(
678            vrtces.len() as SpiceInt,
679            vrtces.as_ptr() as *mut [f64; 3],
680            plates.len() as SpiceInt,
681            plates.as_ptr() as *mut [SpiceInt; 3],
682            finscl,
683            corscl,
684            worksz as SpiceInt,
685            voxpsz as SpiceInt,
686            voxlsz as SpiceInt,
687            makvtl as SpiceInt,
688            spxisz as SpiceInt,
689            work.as_mut_ptr(),
690            spaixd.as_mut_ptr(),
691            spaixi.as_mut_ptr(),
692        );
693    }
694
695    (spaixd, spaixi)
696}
697
698/// Number of coordinate system parameters a DSK descriptor holds.
699pub const DSK_NSYPAR: usize = 10;
700
701/**
702Write a type 2 segment to a DSK file.
703
704# Panics
705
706Panics if `corpar` holds fewer than [`DSK_NSYPAR`] values: CSPICE reads that many whatever the
707coordinate system.
708*/
709#[allow(clippy::too_many_arguments)]
710#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
711pub fn dskw02(
712    handle: i32,
713    center: i32,
714    surfce: i32,
715    dclass: i32,
716    frame: &str,
717    corsys: i32,
718    corpar: &[f64],
719    mncor1: f64,
720    mxcor1: f64,
721    mncor2: f64,
722    mxcor2: f64,
723    mncor3: f64,
724    mxcor3: f64,
725    first: f64,
726    last: f64,
727    vrtces: &[[f64; 3]],
728    plates: &[[i32; 3]],
729    spaixd: &[f64],
730    spaixi: &[i32],
731) {
732    assert!(
733        corpar.len() >= DSK_NSYPAR,
734        "dskw02 needs {DSK_NSYPAR} coordinate parameters but got {}",
735        corpar.len()
736    );
737
738    let frame = to_cstring(frame);
739
740    unsafe {
741        crate::c::dskw02_c(
742            handle,
743            center,
744            surfce,
745            dclass,
746            frame.as_ptr() as *mut SpiceChar,
747            corsys,
748            corpar.as_ptr() as *mut SpiceDouble,
749            mncor1,
750            mxcor1,
751            mncor2,
752            mxcor2,
753            mncor3,
754            mxcor3,
755            first,
756            last,
757            vrtces.len() as SpiceInt,
758            vrtces.as_ptr() as *mut [f64; 3],
759            plates.len() as SpiceInt,
760            plates.as_ptr() as *mut [SpiceInt; 3],
761            spaixd.as_ptr() as *mut SpiceDouble,
762            spaixi.as_ptr() as *mut SpiceInt,
763        );
764    }
765}
766
767/* -------------------------------------------------------------------------------------------- */
768/* Kernel pool                                                                                    */
769/* -------------------------------------------------------------------------------------------- */
770
771cspice_proc! {
772    /**
773    Load one or more SPICE kernels into a program.
774    */
775    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
776    pub fn furnsh(name: &str) {}
777}
778
779cspice_proc! {
780    /**
781    Unload a SPICE kernel.
782    */
783    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
784    pub fn unload(name: &str) {}
785}
786
787cspice_proc! {
788    /**
789    Clear the KEEPER subsystem: unload all kernels, clear the kernel pool, and re-initialize the
790    subsystem. Existing watches on kernel variables are retained.
791    */
792    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
793    pub fn kclear() {}
794}
795
796cspice_proc! {
797    /**
798    Return the current number of kernels that have been loaded via the KEEPER interface that are of
799    a specified type.
800    */
801    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
802    pub fn ktotal(kind: &str) -> i32 {}
803}
804
805cspice_proc! {
806    /**
807    Load the variables contained in a text kernel into the kernel pool.
808    */
809    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
810    pub fn ldpool(filename: &str) {}
811}
812
813cspice_proc! {
814    /**
815    Remove all variables from the kernel pool.
816    */
817    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
818    pub fn clpool() {}
819}
820
821cspice_proc! {
822    /**
823    Confirm the existence of a kernel variable in the kernel pool.
824    */
825    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
826    pub fn expool(name: &str) -> bool {}
827}
828
829cspice_proc! {
830    /**
831    Return the data about a kernel pool variable: whether it exists, how many components it has,
832    and whether it is numeric (`"N"`) or character (`"C"`).
833    */
834    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
835    pub fn dtpool(name: &str) -> (bool, i32, String) {}
836}
837
838/**
839Return the file name, type, source and handle of a loaded kernel.
840
841This function has a [neat version][crate::neat::kdata].
842*/
843#[allow(clippy::too_many_arguments)]
844pub fn kdata(
845    which: i32,
846    kind: &str,
847    fillen: i32,
848    typlen: i32,
849    srclen: i32,
850) -> (String, String, String, i32, bool) {
851    let kind = to_cstring(kind);
852    let mut file = vec![0 as SpiceChar; fillen.max(1) as usize];
853    let mut filtyp = vec![0 as SpiceChar; typlen.max(1) as usize];
854    let mut source = vec![0 as SpiceChar; srclen.max(1) as usize];
855    let mut handle = 0;
856    let mut found = 0;
857
858    unsafe {
859        crate::c::kdata_c(
860            which,
861            kind.as_ptr() as *mut SpiceChar,
862            fillen,
863            typlen,
864            srclen,
865            file.as_mut_ptr(),
866            filtyp.as_mut_ptr(),
867            source.as_mut_ptr(),
868            &mut handle,
869            &mut found,
870        );
871    }
872
873    (
874        from_cbuf(&file),
875        from_cbuf(&filtyp),
876        from_cbuf(&source),
877        handle,
878        found != 0,
879    )
880}
881
882/**
883Return the type, source and handle of a loaded kernel, given its name.
884
885This function has a [neat version][crate::neat::kinfo].
886*/
887pub fn kinfo(file: &str, typlen: i32, srclen: i32) -> (String, String, i32, bool) {
888    let file = to_cstring(file);
889    let mut filtyp = vec![0 as SpiceChar; typlen.max(1) as usize];
890    let mut source = vec![0 as SpiceChar; srclen.max(1) as usize];
891    let mut handle = 0;
892    let mut found = 0;
893
894    unsafe {
895        crate::c::kinfo_c(
896            file.as_ptr() as *mut SpiceChar,
897            typlen,
898            srclen,
899            filtyp.as_mut_ptr(),
900            source.as_mut_ptr(),
901            &mut handle,
902            &mut found,
903        );
904    }
905
906    (from_cbuf(&filtyp), from_cbuf(&source), handle, found != 0)
907}
908
909/**
910Return the double precision values of a kernel pool variable.
911
912The vector is empty when the variable is absent from the pool.
913*/
914#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
915pub fn gdpool(name: &str, start: usize, room: usize) -> Vec<f64> {
916    let name = to_cstring(name);
917    let mut n = 0;
918    let mut values = vec![0.0; room];
919    let mut found = 0;
920
921    unsafe {
922        crate::c::gdpool_c(
923            name.as_ptr() as *mut SpiceChar,
924            start as SpiceInt,
925            room as SpiceInt,
926            &mut n,
927            values.as_mut_ptr(),
928            &mut found,
929        )
930    }
931
932    values.truncate(if found != 0 { n.max(0) as usize } else { 0 });
933    values
934}
935
936/**
937Return the integer values of a kernel pool variable.
938
939The vector is empty when the variable is absent from the pool.
940*/
941#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
942pub fn gipool(name: &str, start: usize, room: usize) -> Vec<i32> {
943    let name = to_cstring(name);
944    let mut n = 0;
945    let mut values = vec![0; room];
946    let mut found = 0;
947
948    unsafe {
949        crate::c::gipool_c(
950            name.as_ptr() as *mut SpiceChar,
951            start as SpiceInt,
952            room as SpiceInt,
953            &mut n,
954            values.as_mut_ptr(),
955            &mut found,
956        )
957    }
958
959    values.truncate(if found != 0 { n.max(0) as usize } else { 0 });
960    values
961}
962
963/**
964Return the character values of a kernel pool variable.
965
966The vector is empty when the variable is absent from the pool.
967
968This function has a [neat version][crate::neat::gcpool].
969*/
970pub fn gcpool(name: &str, start: usize, room: usize, lenout: usize) -> Vec<String> {
971    let name = to_cstring(name);
972    let lenout = lenout.max(1);
973    let mut n = 0;
974    let mut values = vec![0 as SpiceChar; room * lenout];
975    let mut found = 0;
976
977    unsafe {
978        crate::c::gcpool_c(
979            name.as_ptr() as *mut SpiceChar,
980            start as SpiceInt,
981            room as SpiceInt,
982            lenout as SpiceInt,
983            &mut n,
984            values.as_mut_ptr().cast(),
985            &mut found,
986        )
987    }
988
989    let count = if found != 0 { n.max(0) as usize } else { 0 };
990    (0..count)
991        .map(|index| from_cbuf(&values[index * lenout..(index + 1) * lenout]))
992        .collect()
993}
994
995/**
996Set a watch on a set of kernel pool variables for a named agent.
997
998[`cvpool`] then reports whether any of them have been updated since the agent last asked.
999*/
1000#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1001pub fn swpool<S: AsRef<str>>(agent: &str, names: &[S]) {
1002    let agent = to_cstring(agent);
1003    let (buffer, lenvals) = to_strided(names);
1004    unsafe {
1005        crate::c::swpool_c(
1006            agent.as_ptr() as *mut SpiceChar,
1007            names.len() as SpiceInt,
1008            lenvals as SpiceInt,
1009            buffer.as_ptr().cast(),
1010        )
1011    }
1012}
1013
1014/**
1015Return the names of the kernel pool variables matching a template.
1016
1017The vector is empty when nothing matches.
1018
1019This function has a [neat version][crate::neat::gnpool].
1020*/
1021pub fn gnpool(name: &str, start: usize, room: usize, lenout: usize) -> Vec<String> {
1022    let name = to_cstring(name);
1023    let lenout = lenout.max(1);
1024    let mut buffer = vec![0 as SpiceChar; room.max(1) * lenout];
1025    let mut n = 0;
1026    let mut found = 0;
1027
1028    unsafe {
1029        crate::c::gnpool_c(
1030            name.as_ptr() as *mut SpiceChar,
1031            start as SpiceInt,
1032            room as SpiceInt,
1033            lenout as SpiceInt,
1034            &mut n,
1035            buffer.as_mut_ptr().cast(),
1036            &mut found,
1037        )
1038    };
1039
1040    let count = if found != 0 { n.max(0) as usize } else { 0 };
1041    from_strided(&buffer, lenout, count)
1042}
1043
1044/**
1045Insert double precision values into the kernel pool.
1046*/
1047#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1048pub fn pdpool(name: &str, values: &[f64]) {
1049    let name = to_cstring(name);
1050    unsafe {
1051        crate::c::pdpool_c(
1052            name.as_ptr() as *mut SpiceChar,
1053            values.len() as SpiceInt,
1054            values.as_ptr() as *mut SpiceDouble,
1055        )
1056    }
1057}
1058
1059/**
1060Insert integer values into the kernel pool.
1061*/
1062#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1063pub fn pipool(name: &str, values: &[i32]) {
1064    let name = to_cstring(name);
1065    unsafe {
1066        crate::c::pipool_c(
1067            name.as_ptr() as *mut SpiceChar,
1068            values.len() as SpiceInt,
1069            values.as_ptr() as *mut SpiceInt,
1070        )
1071    }
1072}
1073
1074/**
1075Insert character values into the kernel pool.
1076*/
1077#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1078pub fn pcpool<S: AsRef<str>>(name: &str, values: &[S]) {
1079    let name = to_cstring(name);
1080    let (buffer, lenvals) = to_strided(values);
1081
1082    unsafe {
1083        crate::c::pcpool_c(
1084            name.as_ptr() as *mut SpiceChar,
1085            values.len() as SpiceInt,
1086            lenvals as SpiceInt,
1087            buffer.as_ptr().cast(),
1088        )
1089    }
1090}
1091
1092/* -------------------------------------------------------------------------------------------- */
1093/* Time                                                                                           */
1094/* -------------------------------------------------------------------------------------------- */
1095
1096cspice_proc! {
1097    /**
1098    Convert a string representing an epoch to a double precision value representing the number of
1099    TDB seconds past the J2000 epoch corresponding to the input epoch.
1100    */
1101    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1102    pub fn str2et(targ: &str) -> f64 {}
1103}
1104
1105cspice_proc! {
1106    /**
1107    Convert an input time from UTC seconds past the J2000 epoch to ephemeris seconds past J2000.
1108    */
1109    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1110    pub fn utc2et(utcstr: &str) -> f64 {}
1111}
1112
1113cspice_proc! {
1114    /**
1115    Convert an input epoch, in ephemeris seconds past J2000, to a UTC string.
1116
1117    This function has a [neat version][crate::neat::et2utc].
1118    */
1119    pub fn et2utc(et: f64, format: &str, prec: i32, #[lenout] lenout: i32) -> String {}
1120}
1121
1122cspice_proc! {
1123    /**
1124    Convert an input epoch represented in TDB seconds past the TDB epoch of J2000 to a character
1125    string formatted to the specifications of a user's format picture.
1126
1127    This function has a [neat version][crate::neat::timout].
1128    */
1129    pub fn timout(et: f64, pictur: &str, #[lenout] lenout: i32) -> String {}
1130}
1131
1132cspice_proc! {
1133    /**
1134    Parse a time string and return the number of seconds past the J2000 epoch on a formal calendar,
1135    together with the error message CSPICE produced, empty when the parse succeeded.
1136
1137    This function has a [neat version][crate::neat::tparse].
1138    */
1139    pub fn tparse(string: &str, #[lenout] lenout: i32) -> (f64, String) {}
1140}
1141
1142cspice_proc! {
1143    /**
1144    Return the value of Delta ET (ET-UTC) for an input epoch.
1145    */
1146    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1147    pub fn deltet(epoch: f64, eptype: &str) -> f64 {}
1148}
1149
1150cspice_proc! {
1151    /**
1152    Transform time from one uniform scale to another. The uniform time scales are TAI, GPS, TT, TDT,
1153    TDB, ET, JED, JDTDB, JDTDT.
1154    */
1155    #[return_output]
1156    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1157    pub fn unitim(epoch: f64, insys: &str, outsys: &str) -> f64 {}
1158}
1159
1160cspice_proc! {
1161    /**
1162    Convert ephemeris seconds past J2000 to continuous encoded spacecraft clock ticks.
1163    */
1164    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1165    pub fn sce2c(sc: i32, et: f64) -> f64 {}
1166}
1167
1168cspice_proc! {
1169    /**
1170    Convert ephemeris seconds past J2000 to a spacecraft clock string.
1171
1172    This function has a [neat version][crate::neat::sce2s].
1173    */
1174    pub fn sce2s(sc: i32, et: f64, #[lenout] sclklen: i32) -> String {}
1175}
1176
1177cspice_proc! {
1178    /**
1179    Encode a character representation of spacecraft clock time into a double precision number.
1180    */
1181    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1182    pub fn scencd(sc: i32, sclkch: &str) -> f64 {}
1183}
1184
1185cspice_proc! {
1186    /**
1187    Convert a double precision encoding of spacecraft clock time into a character representation.
1188
1189    This function has a [neat version][crate::neat::scdecd].
1190    */
1191    pub fn scdecd(sc: i32, sclkdp: f64, #[lenout] sclklen: i32) -> String {}
1192}
1193
1194cspice_proc! {
1195    /**
1196    Convert a spacecraft clock string to ephemeris seconds past J2000.
1197    */
1198    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1199    pub fn scs2e(sc: i32, sclkch: &str) -> f64 {}
1200}
1201
1202cspice_proc! {
1203    /**
1204    Convert encoded spacecraft clock ticks to ephemeris seconds past J2000.
1205    */
1206    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1207    pub fn sct2e(sc: i32, sclkdp: f64) -> f64 {}
1208}
1209
1210cspice_proc! {
1211    /**
1212    Compute L_s, the planetocentric longitude of the sun, as seen from a specified body.
1213    */
1214    #[return_output]
1215    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1216    pub fn lspcn(body: &str, et: f64, abcorr: &str) -> f64 {}
1217}
1218
1219/* -------------------------------------------------------------------------------------------- */
1220/* Frames                                                                                         */
1221/* -------------------------------------------------------------------------------------------- */
1222
1223cspice_proc! {
1224    /**
1225    Return the matrix that transforms position vectors from one specified frame to another at a
1226    specified epoch.
1227    */
1228    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1229    pub fn pxform(from: &str, to: &str, et: f64) -> [[f64; 3]; 3] {}
1230}
1231
1232cspice_proc! {
1233    /**
1234    Return the 3x3 matrix that transforms position vectors from one specified frame at a specified
1235    epoch to another specified frame at another specified epoch.
1236    */
1237    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1238    pub fn pxfrm2(from: &str, to: &str, etfrom: f64, etto: f64) -> [[f64; 3]; 3] {}
1239}
1240
1241cspice_proc! {
1242    /**
1243    Return the 6x6 state transformation matrix from one frame to another at a specified epoch.
1244    */
1245    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1246    pub fn sxform(from: &str, to: &str, et: f64) -> [[f64; 6]; 6] {}
1247}
1248
1249cspice_proc! {
1250    /**
1251    Look up the frame ID code associated with a frame name; zero when the name is not recognised.
1252    */
1253    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1254    pub fn namfrm(frname: &str) -> i32 {}
1255}
1256
1257cspice_proc! {
1258    /**
1259    Look up the name of a reference frame associated with an ID code.
1260
1261    This function has a [neat version][crate::neat::frmnam].
1262    */
1263    pub fn frmnam(frcode: i32, #[lenout] lenout: i32) -> String {}
1264}
1265
1266/* -------------------------------------------------------------------------------------------- */
1267/* Coordinates                                                                                    */
1268/* -------------------------------------------------------------------------------------------- */
1269
1270cspice_proc! {
1271    /**
1272    Convert geodetic coordinates to rectangular coordinates.
1273    */
1274    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1275    pub fn georec(lon: f64, lat: f64, alt: f64, re: f64, f: f64) -> [f64; 3] {}
1276}
1277
1278cspice_proc! {
1279    /**
1280    Convert rectangular coordinates to geodetic coordinates, as longitude, latitude and altitude.
1281    */
1282    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1283    pub fn recgeo(rectan: [f64; 3], re: f64, f: f64) -> (f64, f64, f64) {}
1284}
1285
1286cspice_proc! {
1287    /**
1288    Convert from latitudinal coordinates to rectangular coordinates.
1289    */
1290    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1291    pub fn latrec(radius: f64, longitude: f64, latitude: f64) -> [f64; 3] {}
1292}
1293
1294cspice_proc! {
1295    /**
1296    Convert from rectangular coordinates to latitudinal coordinates, as radius, longitude and
1297    latitude.
1298    */
1299    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1300    pub fn reclat(rectan: [f64; 3]) -> (f64, f64, f64) {}
1301}
1302
1303cspice_proc! {
1304    /**
1305    Convert from spherical coordinates to rectangular coordinates.
1306    */
1307    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1308    pub fn sphrec(r: f64, colat: f64, lon: f64) -> [f64; 3] {}
1309}
1310
1311cspice_proc! {
1312    /**
1313    Convert from rectangular coordinates to spherical coordinates, as radius, colatitude and
1314    longitude.
1315    */
1316    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1317    pub fn recsph(rectan: [f64; 3]) -> (f64, f64, f64) {}
1318}
1319
1320cspice_proc! {
1321    /**
1322    Convert from cylindrical coordinates to rectangular coordinates.
1323    */
1324    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1325    pub fn cylrec(r: f64, lon: f64, z: f64) -> [f64; 3] {}
1326}
1327
1328cspice_proc! {
1329    /**
1330    Convert from rectangular coordinates to cylindrical coordinates, as radius, longitude and `z`.
1331    */
1332    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1333    pub fn reccyl(rectan: [f64; 3]) -> (f64, f64, f64) {}
1334}
1335
1336cspice_proc! {
1337    /**
1338    Convert planetographic coordinates to rectangular coordinates.
1339    */
1340    #[allow(clippy::too_many_arguments)]
1341    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1342    pub fn pgrrec(body: &str, lon: f64, lat: f64, alt: f64, re: f64, f: f64) -> [f64; 3] {}
1343}
1344
1345cspice_proc! {
1346    /**
1347    Convert rectangular coordinates to planetographic coordinates, as longitude, latitude and
1348    altitude.
1349    */
1350    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1351    pub fn recpgr(body: &str, rectan: [f64; 3], re: f64, f: f64) -> (f64, f64, f64) {}
1352}
1353
1354cspice_proc! {
1355    /**
1356    Convert range, right ascension, and declination to rectangular coordinates.
1357    */
1358    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1359    pub fn radrec(range: f64, ra: f64, dec: f64) -> [f64; 3] {}
1360}
1361
1362cspice_proc! {
1363    /**
1364    Convert rectangular coordinates to range, right ascension, and declination.
1365    */
1366    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1367    pub fn recrad(rectan: [f64; 3]) -> (f64, f64, f64) {}
1368}
1369
1370cspice_proc! {
1371    /**
1372    Convert planetocentric latitude and longitude of a surface point on a specified body to
1373    rectangular coordinates.
1374    */
1375    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1376    pub fn srfrec(body: i32, lon: f64, lat: f64) -> [f64; 3] {}
1377}
1378
1379/* -------------------------------------------------------------------------------------------- */
1380/* Vectors and matrices                                                                           */
1381
1382cspice_proc! {
1383    /**
1384    Pack three scalars into a vector.
1385    */
1386    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1387    pub fn vpack(x: f64, y: f64, z: f64) -> [f64; 3] {}
1388}
1389
1390cspice_proc! {
1391    /**
1392    Unpack a vector into three scalars.
1393    */
1394    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1395    pub fn vupack(v: [f64; 3]) -> (f64, f64, f64) {}
1396}
1397
1398cspice_proc! {
1399    /**
1400    Whether a vector is the zero vector.
1401    */
1402    #[return_output]
1403    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1404    pub fn vzero(v: [f64; 3]) -> bool {}
1405}
1406
1407cspice_proc! {
1408    /**
1409    The component of `a` perpendicular to `b`.
1410    */
1411    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1412    pub fn vperp(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {}
1413}
1414
1415cspice_proc! {
1416    /**
1417    The projection of `a` onto `b`.
1418    */
1419    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1420    pub fn vproj(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {}
1421}
1422
1423cspice_proc! {
1424    /**
1425    Rotate a vector about an axis by a given angle.
1426    */
1427    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1428    pub fn vrotv(v: [f64; 3], axis: [f64; 3], theta: f64) -> [f64; 3] {}
1429}
1430
1431cspice_proc! {
1432    /**
1433    The linear combination `a * v1 + b * v2`.
1434    */
1435    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1436    pub fn vlcom(a: f64, v1: [f64; 3], b: f64, v2: [f64; 3]) -> [f64; 3] {}
1437}
1438
1439cspice_proc! {
1440    /**
1441    The linear combination `a * v1 + b * v2 + c * v3`.
1442    */
1443    #[allow(clippy::too_many_arguments)]
1444    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1445    pub fn vlcom3(
1446        a: f64,
1447        v1: [f64; 3],
1448        b: f64,
1449        v2: [f64; 3],
1450        c: f64,
1451        v3: [f64; 3]
1452    ) -> [f64; 3] {
1453    }
1454}
1455
1456cspice_proc! {
1457    /**
1458    The quadratic form `v1 * matrix * v2`.
1459    */
1460    #[return_output]
1461    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1462    pub fn vtmv(v1: [f64; 3], matrix: [[f64; 3]; 3], v2: [f64; 3]) -> f64 {}
1463}
1464
1465cspice_proc! {
1466    /**
1467    The 3x3 identity matrix.
1468    */
1469    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1470    pub fn ident() -> [[f64; 3]; 3] {}
1471}
1472
1473cspice_proc! {
1474    /**
1475    Copy a 3x3 matrix.
1476    */
1477    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1478    pub fn mequ(m1: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
1479}
1480
1481cspice_proc! {
1482    /**
1483    Transpose a 6x6 matrix.
1484    */
1485    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1486    pub fn xpose6(m1: [[f64; 6]; 6]) -> [[f64; 6]; 6] {}
1487}
1488
1489/* -------------------------------------------------------------------------------------------- */
1490/* Vectors and matrices of arbitrary dimension                                                    */
1491/* -------------------------------------------------------------------------------------------- */
1492
1493/*
1494CSPICE takes the dimensions as separate arguments and writes the result through a bare pointer, so
1495these cannot go through the macro: the length of the output is only known at run time. Each wrapper
1496takes the dimensions from the slices it is given and sizes the result itself.
1497*/
1498
1499/// Generate the wrappers of the `v*g` routines that map one or two vectors to another.
1500macro_rules! vector_g {
1501    ($($name:ident($($arg:ident),*) => $cname:ident, $doc:expr);* $(;)?) => {$(
1502        #[doc = $doc]
1503        ///
1504        /// # Panics
1505        ///
1506        /// Panics if the vectors have different lengths.
1507        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1508        pub fn $name($($arg: &[f64]),*) -> Vec<f64> {
1509            let ndim = same_length(&[$($arg),*]);
1510            let mut vout = vec![0.0; ndim];
1511            unsafe {
1512                crate::c::$cname(
1513                    $($arg.as_ptr() as *mut SpiceDouble,)*
1514                    ndim as SpiceInt,
1515                    vout.as_mut_ptr(),
1516                );
1517            }
1518            vout
1519        }
1520    )*};
1521}
1522
1523/// Generate the wrappers of the `v*g` routines that reduce one or two vectors to a scalar.
1524macro_rules! scalar_g {
1525    ($($name:ident($($arg:ident),*) -> $ret:ty => $cname:ident, $conv:expr, $doc:expr);* $(;)?) => {$(
1526        #[doc = $doc]
1527        ///
1528        /// # Panics
1529        ///
1530        /// Panics if the vectors have different lengths.
1531        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1532        pub fn $name($($arg: &[f64]),*) -> $ret {
1533            let ndim = same_length(&[$($arg),*]);
1534            let returned = unsafe {
1535                crate::c::$cname($($arg.as_ptr() as *mut SpiceDouble,)* ndim as SpiceInt)
1536            };
1537            #[allow(clippy::redundant_closure_call)]
1538            ($conv)(returned)
1539        }
1540    )*};
1541}
1542
1543/// The common length of a set of slices.
1544fn same_length(slices: &[&[f64]]) -> usize {
1545    let ndim = slices[0].len();
1546    assert!(
1547        slices.iter().all(|slice| slice.len() == ndim),
1548        "the vectors must all have the same length, got {:?}",
1549        slices.iter().map(|slice| slice.len()).collect::<Vec<_>>()
1550    );
1551    ndim
1552}
1553
1554vector_g! {
1555    vaddg(v1, v2) => vaddg_c, "Add two vectors of arbitrary dimension.";
1556    vsubg(v1, v2) => vsubg_c, "Subtract one vector of arbitrary dimension from another.";
1557    vhatg(v1) => vhatg_c, "The unit vector along a vector of arbitrary dimension.";
1558    vequg(vin) => vequg_c, "Copy a vector of arbitrary dimension.";
1559    vminug(vin) => vminug_c, "Negate a vector of arbitrary dimension.";
1560    vprojg(a, b) => vprojg_c, "The projection of one vector onto another, in arbitrary dimension.";
1561}
1562
1563scalar_g! {
1564    vdotg(v1, v2) -> f64 => vdotg_c, |value| value,
1565        "The dot product of two vectors of arbitrary dimension.";
1566    vnormg(v1) -> f64 => vnormg_c, |value| value,
1567        "The magnitude of a vector of arbitrary dimension.";
1568    vdistg(v1, v2) -> f64 => vdistg_c, |value| value,
1569        "The distance between two vectors of arbitrary dimension.";
1570    vrelg(v1, v2) -> f64 => vrelg_c, |value| value,
1571        "The relative difference between two vectors of arbitrary dimension.";
1572    vsepg(v1, v2) -> f64 => vsepg_c, |value| value,
1573        "The angular separation of two vectors of arbitrary dimension.";
1574    vzerog(v) -> bool => vzerog_c, |value: crate::c::SpiceBoolean| value != 0,
1575        "Whether a vector of arbitrary dimension is the zero vector.";
1576}
1577
1578/**
1579Scale a vector of arbitrary dimension.
1580*/
1581#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1582pub fn vsclg(s: f64, v1: &[f64]) -> Vec<f64> {
1583    let mut vout = vec![0.0; v1.len()];
1584    unsafe {
1585        crate::c::vsclg_c(
1586            s,
1587            v1.as_ptr() as *mut SpiceDouble,
1588            v1.len() as SpiceInt,
1589            vout.as_mut_ptr(),
1590        )
1591    };
1592    vout
1593}
1594
1595/**
1596Normalize a vector of arbitrary dimension, returning the unit vector and the original magnitude.
1597*/
1598#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1599pub fn unormg(v1: &[f64]) -> (Vec<f64>, f64) {
1600    let mut vout = vec![0.0; v1.len()];
1601    let mut vmag = 0.0;
1602    unsafe {
1603        crate::c::unormg_c(
1604            v1.as_ptr() as *mut SpiceDouble,
1605            v1.len() as SpiceInt,
1606            vout.as_mut_ptr(),
1607            &mut vmag,
1608        )
1609    };
1610    (vout, vmag)
1611}
1612
1613/**
1614The linear combination `a * v1 + b * v2`, in arbitrary dimension.
1615
1616# Panics
1617
1618Panics if the vectors have different lengths.
1619*/
1620#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1621pub fn vlcomg(a: f64, v1: &[f64], b: f64, v2: &[f64]) -> Vec<f64> {
1622    let ndim = same_length(&[v1, v2]);
1623    let mut sum = vec![0.0; ndim];
1624    unsafe {
1625        crate::c::vlcomg_c(
1626            ndim as SpiceInt,
1627            a,
1628            v1.as_ptr() as *mut SpiceDouble,
1629            b,
1630            v2.as_ptr() as *mut SpiceDouble,
1631            sum.as_mut_ptr(),
1632        )
1633    };
1634    sum
1635}
1636
1637/**
1638Copy `ndim` elements of an array.
1639*/
1640#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1641pub fn moved(arrfrm: &[f64]) -> Vec<f64> {
1642    let mut arrto = vec![0.0; arrfrm.len()];
1643    unsafe {
1644        crate::c::moved_c(
1645            arrfrm.as_ptr() as *mut SpiceDouble,
1646            arrfrm.len() as SpiceInt,
1647            arrto.as_mut_ptr(),
1648        )
1649    };
1650    arrto
1651}
1652
1653/**
1654The quadratic form `v1 * matrix * v2`, in arbitrary dimension.
1655
1656`matrix` is `nrow` by `ncol`, stored row by row.
1657
1658# Panics
1659
1660Panics if the lengths do not match the dimensions.
1661*/
1662#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1663pub fn vtmvg(v1: &[f64], matrix: &[f64], v2: &[f64], nrow: usize, ncol: usize) -> f64 {
1664    assert_matrix(matrix, nrow, ncol);
1665    assert!(
1666        v1.len() == nrow && v2.len() == ncol,
1667        "vtmvg needs a vector of {nrow} and one of {ncol}, got {} and {}",
1668        v1.len(),
1669        v2.len()
1670    );
1671
1672    unsafe {
1673        crate::c::vtmvg_c(
1674            v1.as_ptr().cast(),
1675            matrix.as_ptr().cast(),
1676            v2.as_ptr().cast(),
1677            nrow as SpiceInt,
1678            ncol as SpiceInt,
1679        )
1680    }
1681}
1682
1683/// Check that a slice holds a `rows` by `cols` matrix, stored row by row.
1684fn assert_matrix(matrix: &[f64], rows: usize, cols: usize) {
1685    assert!(
1686        matrix.len() == rows * cols,
1687        "a {rows}x{cols} matrix needs {} elements, got {}",
1688        rows * cols,
1689        matrix.len()
1690    );
1691}
1692
1693/*
1694CSPICE names the dimensions of these after what they mean rather than after their position, and
1695the meaning differs between the three. Spelling them out, and asserting the shapes, is the only way
1696a caller can tell what to pass: getting `mtxmg` wrong the other way round produces a plausible
1697looking matrix rather than an error.
1698*/
1699
1700/**
1701Multiply a `nr1` by `nc1r2` matrix with a `nc1r2` by `nc2` one, giving `nr1` by `nc2`.
1702
1703The matrices are stored row by row.
1704
1705# Panics
1706
1707Panics if the slice lengths do not match the dimensions.
1708*/
1709#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1710pub fn mxmg(m1: &[f64], m2: &[f64], nr1: usize, nc1r2: usize, nc2: usize) -> Vec<f64> {
1711    assert_matrix(m1, nr1, nc1r2);
1712    assert_matrix(m2, nc1r2, nc2);
1713    let mut mout = vec![0.0; nr1 * nc2];
1714    unsafe {
1715        crate::c::mxmg_c(
1716            m1.as_ptr().cast(),
1717            m2.as_ptr().cast(),
1718            nr1 as SpiceInt,
1719            nc1r2 as SpiceInt,
1720            nc2 as SpiceInt,
1721            mout.as_mut_ptr().cast(),
1722        )
1723    };
1724    mout
1725}
1726
1727/**
1728Multiply the transpose of a `nr1r2` by `nc1` matrix with a `nr1r2` by `nc2` one, giving `nc1` by
1729`nc2`.
1730
1731The matrices are stored row by row.
1732
1733# Panics
1734
1735Panics if the slice lengths do not match the dimensions.
1736*/
1737#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1738pub fn mtxmg(m1: &[f64], m2: &[f64], nc1: usize, nr1r2: usize, nc2: usize) -> Vec<f64> {
1739    assert_matrix(m1, nr1r2, nc1);
1740    assert_matrix(m2, nr1r2, nc2);
1741    let mut mout = vec![0.0; nc1 * nc2];
1742    unsafe {
1743        crate::c::mtxmg_c(
1744            m1.as_ptr().cast(),
1745            m2.as_ptr().cast(),
1746            nc1 as SpiceInt,
1747            nr1r2 as SpiceInt,
1748            nc2 as SpiceInt,
1749            mout.as_mut_ptr().cast(),
1750        )
1751    };
1752    mout
1753}
1754
1755/**
1756Multiply a `nr1` by `nc1c2` matrix with the transpose of a `nr2` by `nc1c2` one, giving `nr1` by
1757`nr2`.
1758
1759The matrices are stored row by row.
1760
1761# Panics
1762
1763Panics if the slice lengths do not match the dimensions.
1764*/
1765#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1766pub fn mxmtg(m1: &[f64], m2: &[f64], nr1: usize, nc1c2: usize, nr2: usize) -> Vec<f64> {
1767    assert_matrix(m1, nr1, nc1c2);
1768    assert_matrix(m2, nr2, nc1c2);
1769    let mut mout = vec![0.0; nr1 * nr2];
1770    unsafe {
1771        crate::c::mxmtg_c(
1772            m1.as_ptr().cast(),
1773            m2.as_ptr().cast(),
1774            nr1 as SpiceInt,
1775            nc1c2 as SpiceInt,
1776            nr2 as SpiceInt,
1777            mout.as_mut_ptr().cast(),
1778        )
1779    };
1780    mout
1781}
1782
1783/**
1784Multiply a matrix by a vector, in arbitrary dimension.
1785
1786`m1` is `nrow1` by `nc1r2`, stored row by row.
1787*/
1788#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1789pub fn mxvg(m1: &[f64], v2: &[f64], nrow1: usize, nc1r2: usize) -> Vec<f64> {
1790    assert_matrix(m1, nrow1, nc1r2);
1791    assert_matrix(v2, nc1r2, 1);
1792    let mut vout = vec![0.0; nrow1];
1793    unsafe {
1794        crate::c::mxvg_c(
1795            m1.as_ptr().cast(),
1796            v2.as_ptr().cast(),
1797            nrow1 as SpiceInt,
1798            nc1r2 as SpiceInt,
1799            vout.as_mut_ptr().cast(),
1800        )
1801    };
1802    vout
1803}
1804
1805/**
1806Multiply the transpose of a matrix by a vector, in arbitrary dimension.
1807
1808`m1` is `nr1r2` by `ncol1`, stored row by row.
1809*/
1810#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1811pub fn mtxvg(m1: &[f64], v2: &[f64], ncol1: usize, nr1r2: usize) -> Vec<f64> {
1812    assert_matrix(m1, nr1r2, ncol1);
1813    assert_matrix(v2, nr1r2, 1);
1814    let mut vout = vec![0.0; ncol1];
1815    unsafe {
1816        crate::c::mtxvg_c(
1817            m1.as_ptr().cast(),
1818            v2.as_ptr().cast(),
1819            ncol1 as SpiceInt,
1820            nr1r2 as SpiceInt,
1821            vout.as_mut_ptr().cast(),
1822        )
1823    };
1824    vout
1825}
1826
1827/**
1828Transpose a matrix of arbitrary dimension, stored row by row.
1829*/
1830#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1831pub fn xposeg(matrix: &[f64], nrow: usize, ncol: usize) -> Vec<f64> {
1832    assert_matrix(matrix, nrow, ncol);
1833    let mut xposem = vec![0.0; nrow * ncol];
1834    unsafe {
1835        crate::c::xposeg_c(
1836            matrix.as_ptr().cast(),
1837            nrow as SpiceInt,
1838            ncol as SpiceInt,
1839            xposem.as_mut_ptr().cast(),
1840        )
1841    };
1842    xposem
1843}
1844
1845/**
1846Copy a matrix of arbitrary dimension, stored row by row.
1847*/
1848#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1849pub fn mequg(m1: &[f64], nr: usize, nc: usize) -> Vec<f64> {
1850    assert_matrix(m1, nr, nc);
1851    let mut mout = vec![0.0; nr * nc];
1852    unsafe {
1853        crate::c::mequg_c(
1854            m1.as_ptr().cast(),
1855            nr as SpiceInt,
1856            nc as SpiceInt,
1857            mout.as_mut_ptr().cast(),
1858        )
1859    };
1860    mout
1861}
1862
1863/* -------------------------------------------------------------------------------------------- */
1864/* Coordinate conversions between non-rectangular systems                                         */
1865/* -------------------------------------------------------------------------------------------- */
1866
1867cspice_proc! {
1868    /**
1869    Convert from latitudinal to cylindrical coordinates.
1870    */
1871    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1872    pub fn latcyl(radius: f64, lon: f64, lat: f64) -> (f64, f64, f64) {}
1873}
1874
1875cspice_proc! {
1876    /**
1877    Convert from cylindrical to latitudinal coordinates.
1878    */
1879    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1880    pub fn cyllat(r: f64, lonc: f64, z: f64) -> (f64, f64, f64) {}
1881}
1882
1883cspice_proc! {
1884    /**
1885    Convert from latitudinal to spherical coordinates.
1886    */
1887    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1888    pub fn latsph(radius: f64, lon: f64, lat: f64) -> (f64, f64, f64) {}
1889}
1890
1891cspice_proc! {
1892    /**
1893    Convert from spherical to latitudinal coordinates.
1894    */
1895    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1896    pub fn sphlat(r: f64, colat: f64, lons: f64) -> (f64, f64, f64) {}
1897}
1898
1899cspice_proc! {
1900    /**
1901    Convert from cylindrical to spherical coordinates.
1902    */
1903    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1904    pub fn cylsph(r: f64, lonc: f64, z: f64) -> (f64, f64, f64) {}
1905}
1906
1907cspice_proc! {
1908    /**
1909    Convert from spherical to cylindrical coordinates.
1910    */
1911    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1912    pub fn sphcyl(radius: f64, colat: f64, slon: f64) -> (f64, f64, f64) {}
1913}
1914
1915cspice_proc! {
1916    /**
1917    Convert from range, azimuth and elevation to rectangular coordinates.
1918
1919    `azccw` says whether azimuth increases counterclockwise, `elplsz` whether elevation is positive
1920    toward `+z`.
1921    */
1922    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1923    pub fn azlrec(range: f64, az: f64, el: f64, azccw: bool, elplsz: bool) -> [f64; 3] {}
1924}
1925
1926cspice_proc! {
1927    /**
1928    Convert from rectangular coordinates to range, azimuth and elevation.
1929    */
1930    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1931    pub fn recazl(rectan: [f64; 3], azccw: bool, elplsz: bool) -> (f64, f64, f64) {}
1932}
1933
1934/* -------------------------------------------------------------------------------------------- */
1935/* Jacobians of the coordinate conversions                                                        */
1936/* -------------------------------------------------------------------------------------------- */
1937
1938cspice_proc! {
1939    /**
1940    Jacobian of the transformation from rectangular to latitudinal coordinates.
1941    */
1942    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1943    pub fn dlatdr(x: f64, y: f64, z: f64) -> [[f64; 3]; 3] {}
1944}
1945
1946cspice_proc! {
1947    /**
1948    Jacobian of the transformation from latitudinal to rectangular coordinates.
1949    */
1950    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1951    pub fn drdlat(r: f64, lon: f64, lat: f64) -> [[f64; 3]; 3] {}
1952}
1953
1954cspice_proc! {
1955    /**
1956    Jacobian of the transformation from rectangular to spherical coordinates.
1957    */
1958    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1959    pub fn dsphdr(x: f64, y: f64, z: f64) -> [[f64; 3]; 3] {}
1960}
1961
1962cspice_proc! {
1963    /**
1964    Jacobian of the transformation from spherical to rectangular coordinates.
1965    */
1966    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1967    pub fn drdsph(r: f64, colat: f64, lon: f64) -> [[f64; 3]; 3] {}
1968}
1969
1970cspice_proc! {
1971    /**
1972    Jacobian of the transformation from rectangular to cylindrical coordinates.
1973    */
1974    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1975    pub fn dcyldr(x: f64, y: f64, z: f64) -> [[f64; 3]; 3] {}
1976}
1977
1978cspice_proc! {
1979    /**
1980    Jacobian of the transformation from cylindrical to rectangular coordinates.
1981    */
1982    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1983    pub fn drdcyl(r: f64, lon: f64, z: f64) -> [[f64; 3]; 3] {}
1984}
1985
1986cspice_proc! {
1987    /**
1988    Jacobian of the transformation from rectangular to geodetic coordinates.
1989    */
1990    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1991    pub fn dgeodr(x: f64, y: f64, z: f64, re: f64, f: f64) -> [[f64; 3]; 3] {}
1992}
1993
1994cspice_proc! {
1995    /**
1996    Jacobian of the transformation from geodetic to rectangular coordinates.
1997    */
1998    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
1999    pub fn drdgeo(lon: f64, lat: f64, alt: f64, re: f64, f: f64) -> [[f64; 3]; 3] {}
2000}
2001
2002cspice_proc! {
2003    /**
2004    Jacobian of the transformation from rectangular to planetographic coordinates.
2005    */
2006    #[allow(clippy::too_many_arguments)]
2007    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2008    pub fn dpgrdr(body: &str, x: f64, y: f64, z: f64, re: f64, f: f64) -> [[f64; 3]; 3] {}
2009}
2010
2011cspice_proc! {
2012    /**
2013    Jacobian of the transformation from planetographic to rectangular coordinates.
2014    */
2015    #[allow(clippy::too_many_arguments)]
2016    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2017    pub fn drdpgr(body: &str, lon: f64, lat: f64, alt: f64, re: f64, f: f64) -> [[f64; 3]; 3] {}
2018}
2019
2020cspice_proc! {
2021    /**
2022    Jacobian of the transformation from rectangular to azimuth/elevation coordinates.
2023    */
2024    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2025    pub fn dazldr(x: f64, y: f64, z: f64, azccw: bool, elplsz: bool) -> [[f64; 3]; 3] {}
2026}
2027
2028cspice_proc! {
2029    /**
2030    Jacobian of the transformation from azimuth/elevation to rectangular coordinates.
2031    */
2032    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2033    pub fn drdazl(range: f64, az: f64, el: f64, azccw: bool, elplsz: bool) -> [[f64; 3]; 3] {}
2034}
2035
2036cspice_proc! {
2037    /**
2038    Transform a state between two coordinate systems.
2039    */
2040    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2041    pub fn xfmsta(
2042        input_state: [f64; 6],
2043        input_coord_sys: &str,
2044        output_coord_sys: &str,
2045        body: &str
2046    ) -> [f64; 6] {
2047    }
2048}
2049
2050/* -------------------------------------------------------------------------------------------- */
2051
2052cspice_proc! {
2053    /**
2054    Add two 3-dimensional vectors.
2055    */
2056    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2057    pub fn vadd(v1: [f64; 3], v2: [f64; 3]) -> [f64; 3] {}
2058}
2059
2060cspice_proc! {
2061    /**
2062    Subtract one 3-dimensional vector from another.
2063    */
2064    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2065    pub fn vsub(v1: [f64; 3], v2: [f64; 3]) -> [f64; 3] {}
2066}
2067
2068cspice_proc! {
2069    /**
2070    Multiply a 3-dimensional vector by a scalar.
2071    */
2072    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2073    pub fn vscl(s: f64, v1: [f64; 3]) -> [f64; 3] {}
2074}
2075
2076cspice_proc! {
2077    /**
2078    Copy a 3-dimensional vector.
2079    */
2080    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2081    pub fn vequ(vin: [f64; 3]) -> [f64; 3] {}
2082}
2083
2084cspice_proc! {
2085    /**
2086    Negate a 3-dimensional vector.
2087    */
2088    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2089    pub fn vminus(v1: [f64; 3]) -> [f64; 3] {}
2090}
2091
2092cspice_proc! {
2093    /**
2094    Find the unit vector along a 3-dimensional vector.
2095    */
2096    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2097    pub fn vhat(v1: [f64; 3]) -> [f64; 3] {}
2098}
2099
2100cspice_proc! {
2101    /**
2102    Normalize a 3-dimensional vector, returning the unit vector and the original magnitude.
2103    */
2104    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2105    pub fn unorm(v1: [f64; 3]) -> ([f64; 3], f64) {}
2106}
2107
2108cspice_proc! {
2109    /**
2110    Compute the magnitude of a 3-dimensional vector.
2111    */
2112    #[return_output]
2113    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2114    pub fn vnorm(v1: [f64; 3]) -> f64 {}
2115}
2116
2117cspice_proc! {
2118    /**
2119    Compute the distance between two 3-dimensional vectors.
2120    */
2121    #[return_output]
2122    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2123    pub fn vdist(v1: [f64; 3], v2: [f64; 3]) -> f64 {}
2124}
2125
2126cspice_proc! {
2127    /**
2128    Compute the relative difference between two 3-dimensional vectors.
2129    */
2130    #[return_output]
2131    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2132    pub fn vrel(v1: [f64; 3], v2: [f64; 3]) -> f64 {}
2133}
2134
2135cspice_proc! {
2136    /**
2137    Compute the dot product of two double precision, 3-dimensional vectors.
2138    */
2139    #[return_output]
2140    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2141    pub fn vdot(v1: [f64; 3], v2: [f64; 3]) -> f64 {}
2142}
2143
2144cspice_proc! {
2145    /**
2146    Compute the cross product of two 3-dimensional vectors.
2147    */
2148    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2149    pub fn vcrss(v1: [f64; 3], v2: [f64; 3]) -> [f64; 3] {}
2150}
2151
2152cspice_proc! {
2153    /**
2154    Find the separation angle in radians between two double precision, 3-dimensional vectors. This
2155    angle is defined as zero if either vector is zero.
2156    */
2157    #[return_output]
2158    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2159    pub fn vsep(v1: [f64; 3], v2: [f64; 3]) -> f64 {}
2160}
2161
2162cspice_proc! {
2163    /**
2164    Multiply a 3x3 double precision matrix with a 3-dimensional double precision vector.
2165    */
2166    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2167    pub fn mxv(m1: [[f64; 3]; 3], vin: [f64; 3]) -> [f64; 3] {}
2168}
2169
2170cspice_proc! {
2171    /**
2172    Multiply the transpose of a 3x3 matrix with a 3-dimensional vector.
2173    */
2174    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2175    pub fn mtxv(m1: [[f64; 3]; 3], vin: [f64; 3]) -> [f64; 3] {}
2176}
2177
2178cspice_proc! {
2179    /**
2180    Multiply two 3x3 matrices.
2181    */
2182    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2183    pub fn mxm(m1: [[f64; 3]; 3], m2: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2184}
2185
2186cspice_proc! {
2187    /**
2188    Multiply a 3x3 matrix by the transpose of another.
2189    */
2190    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2191    pub fn mxmt(m1: [[f64; 3]; 3], m2: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2192}
2193
2194cspice_proc! {
2195    /**
2196    Multiply the transpose of a 3x3 matrix by another 3x3 matrix.
2197    */
2198    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2199    pub fn mtxm(m1: [[f64; 3]; 3], m2: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2200}
2201
2202cspice_proc! {
2203    /**
2204    Transpose a 3x3 matrix.
2205    */
2206    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2207    pub fn xpose(m1: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2208}
2209
2210cspice_proc! {
2211    /**
2212    Invert a 3x3 matrix.
2213    */
2214    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2215    pub fn invert(m1: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2216}
2217
2218cspice_proc! {
2219    /**
2220    Compute the determinant of a 3x3 matrix.
2221    */
2222    #[return_output]
2223    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2224    pub fn det(m1: [[f64; 3]; 3]) -> f64 {}
2225}
2226
2227cspice_proc! {
2228    /**
2229    Compute the trace of a 3x3 matrix.
2230    */
2231    #[return_output]
2232    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2233    pub fn trace(matrix: [[f64; 3]; 3]) -> f64 {}
2234}
2235
2236cspice_proc! {
2237    /**
2238    Find the transformation to the right-handed frame having a given vector as a specified axis and
2239    a second given vector lying in a specified coordinate plane.
2240    */
2241    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2242    pub fn twovec(axdef: [f64; 3], indexa: i32, plndef: [f64; 3], indexp: i32) -> [[f64; 3]; 3] {}
2243}
2244
2245cspice_proc! {
2246    /**
2247    Calculate the 3x3 rotation matrix generated by a rotation of a specified angle about a specified
2248    axis. This rotation is thought of as rotating the coordinate system.
2249    */
2250    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2251    pub fn rotate(angle: f64, iaxis: i32) -> [[f64; 3]; 3] {}
2252}
2253
2254cspice_proc! {
2255    /**
2256    Apply a rotation of `angle` radians about axis `iaxis` to a matrix.
2257    */
2258    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2259    pub fn rotmat(m1: [[f64; 3]; 3], angle: f64, iaxis: i32) -> [[f64; 3]; 3] {}
2260}
2261
2262/* -------------------------------------------------------------------------------------------- */
2263/* Rotations                                                                                      */
2264/* -------------------------------------------------------------------------------------------- */
2265
2266cspice_proc! {
2267    /**
2268    Find the unit quaternion corresponding to a specified rotation matrix.
2269    */
2270    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2271    pub fn m2q(r: [[f64; 3]; 3]) -> [f64; 4] {}
2272}
2273
2274cspice_proc! {
2275    /**
2276    Find the rotation matrix corresponding to a specified unit quaternion.
2277    */
2278    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2279    pub fn q2m(q: [f64; 4]) -> [[f64; 3]; 3] {}
2280}
2281
2282cspice_proc! {
2283    /**
2284    Multiply two quaternions.
2285    */
2286    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2287    pub fn qxq(q1: [f64; 4], q2: [f64; 4]) -> [f64; 4] {}
2288}
2289
2290cspice_proc! {
2291    /**
2292    Construct a rotation matrix that rotates vectors by a specified angle about a specified axis.
2293    */
2294    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2295    pub fn axisar(axis: [f64; 3], angle: f64) -> [[f64; 3]; 3] {}
2296}
2297
2298cspice_proc! {
2299    /**
2300    Compute the axis of the rotation a matrix represents, and the angle about that axis.
2301    */
2302    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2303    pub fn raxisa(matrix: [[f64; 3]; 3]) -> ([f64; 3], f64) {}
2304}
2305
2306cspice_proc! {
2307    /**
2308    Construct a rotation matrix from a set of Euler angles.
2309    */
2310    #[allow(clippy::too_many_arguments)]
2311    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2312    pub fn eul2m(
2313        angle3: f64,
2314        angle2: f64,
2315        angle1: f64,
2316        axis3: i32,
2317        axis2: i32,
2318        axis1: i32
2319    ) -> [[f64; 3]; 3] {
2320    }
2321}
2322
2323cspice_proc! {
2324    /**
2325    Factor a rotation matrix as a product of three rotations about specified coordinate axes,
2326    returning the three angles in the order `angle3, angle2, angle1`.
2327    */
2328    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2329    pub fn m2eul(r: [[f64; 3]; 3], axis3: i32, axis2: i32, axis1: i32) -> (f64, f64, f64) {}
2330}
2331
2332cspice_proc! {
2333    /**
2334    Construct a state transformation matrix from a set of Euler angles and their derivatives.
2335    */
2336    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2337    pub fn eul2xf(eulang: [f64; 6], axisa: i32, axisb: i32, axisc: i32) -> [[f64; 6]; 6] {}
2338}
2339
2340cspice_proc! {
2341    /**
2342    Factor a state transformation matrix into Euler angles and their derivatives.
2343
2344    The boolean says whether the factorisation is unique.
2345    */
2346    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2347    pub fn xf2eul(xform: [[f64; 6]; 6], axisa: i32, axisb: i32, axisc: i32) -> ([f64; 6], bool) {}
2348}
2349
2350cspice_proc! {
2351    /**
2352    Split a state transformation matrix into a rotation and the angular velocity of that rotation.
2353    */
2354    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2355    pub fn xf2rav(xform: [[f64; 6]; 6]) -> ([[f64; 3]; 3], [f64; 3]) {}
2356}
2357
2358cspice_proc! {
2359    /**
2360    Build a state transformation matrix from a rotation and an angular velocity.
2361    */
2362    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2363    pub fn rav2xf(rot: [[f64; 3]; 3], av: [f64; 3]) -> [[f64; 6]; 6] {}
2364}
2365
2366cspice_proc! {
2367    /**
2368    Compute the inverse of a 3x3 matrix whose rows are orthogonal but not necessarily unit length.
2369    */
2370    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2371    pub fn invort(m: [[f64; 3]; 3]) -> [[f64; 3]; 3] {}
2372}
2373
2374cspice_proc! {
2375    /**
2376    Decide whether a matrix is a rotation matrix, to within the given norm and determinant
2377    tolerances.
2378    */
2379    #[return_output]
2380    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2381    pub fn isrot(m: [[f64; 3]; 3], ntol: f64, dtol: f64) -> bool {}
2382}
2383
2384/* -------------------------------------------------------------------------------------------- */
2385/* SPK                                                                                            */
2386/* -------------------------------------------------------------------------------------------- */
2387
2388cspice_proc! {
2389    /**
2390    Return the position of a target body relative to an observing body, optionally corrected for
2391    light time (planetary aberration) and stellar aberration.
2392    */
2393    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2394    pub fn spkpos(targ: &str, et: f64, frame: &str, abcorr: &str, obs: &str) -> ([f64; 3], f64) {}
2395}
2396
2397cspice_proc! {
2398    /**
2399    Return the state (position and velocity) of a target body relative to an observing body,
2400    optionally corrected for light time (planetary aberration) and stellar aberration.
2401    */
2402    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2403    pub fn spkezr(targ: &str, et: f64, frame: &str, abcorr: &str, obs: &str) -> ([f64; 6], f64) {}
2404}
2405
2406cspice_proc! {
2407    /**
2408    Return the state of a target body relative to an observing body, both given by their ID codes.
2409    */
2410    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2411    pub fn spkez(targ: i32, et: f64, frame: &str, abcorr: &str, obs: i32) -> ([f64; 6], f64) {}
2412}
2413
2414cspice_proc! {
2415    /**
2416    Return the position of a target body relative to an observing body, both given by their ID
2417    codes.
2418    */
2419    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2420    pub fn spkezp(targ: i32, et: f64, frame: &str, abcorr: &str, obs: i32) -> ([f64; 3], f64) {}
2421}
2422
2423cspice_proc! {
2424    /**
2425    Compute the geometric state of a target body relative to an observing body.
2426    */
2427    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2428    pub fn spkgeo(targ: i32, et: f64, frame: &str, obs: i32) -> ([f64; 6], f64) {}
2429}
2430
2431cspice_proc! {
2432    /**
2433    Return the state of a specified target relative to an observer that is described by a constant
2434    position in a specified reference frame.
2435    */
2436    #[allow(clippy::too_many_arguments)]
2437    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2438    pub fn spkcpo(
2439        target: &str,
2440        et: f64,
2441        outref: &str,
2442        refloc: &str,
2443        abcorr: &str,
2444        obssta: [f64; 6],
2445        obsctr: &str,
2446        obsref: &str
2447    ) -> ([f64; 6], f64) {
2448    }
2449}
2450
2451cspice_proc! {
2452    /**
2453    Return the state of a target that is described by a constant position in a specified reference
2454    frame, relative to a specified observer.
2455    */
2456    #[allow(clippy::too_many_arguments)]
2457    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2458    pub fn spkcpt(
2459        trgpos: [f64; 3],
2460        trgctr: &str,
2461        trgref: &str,
2462        et: f64,
2463        outref: &str,
2464        refloc: &str,
2465        abcorr: &str,
2466        obsrvr: &str
2467    ) -> ([f64; 6], f64) {
2468    }
2469}
2470
2471cspice_proc! {
2472    /**
2473    Return the state of a specified target relative to an observer that is described by a constant
2474    velocity in a specified reference frame.
2475    */
2476    #[allow(clippy::too_many_arguments)]
2477    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2478    pub fn spkcvo(
2479        target: &str,
2480        et: f64,
2481        outref: &str,
2482        refloc: &str,
2483        abcorr: &str,
2484        obssta: [f64; 6],
2485        obsepc: f64,
2486        obsctr: &str,
2487        obsref: &str
2488    ) -> ([f64; 6], f64) {
2489    }
2490}
2491
2492cspice_proc! {
2493    /**
2494    Return the state of a target that is described by a constant velocity in a specified reference
2495    frame, relative to a specified observer.
2496    */
2497    #[allow(clippy::too_many_arguments)]
2498    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2499    pub fn spkcvt(
2500        trgsta: [f64; 6],
2501        trgepc: f64,
2502        trgctr: &str,
2503        trgref: &str,
2504        et: f64,
2505        outref: &str,
2506        refloc: &str,
2507        abcorr: &str,
2508        obsrvr: &str
2509    ) -> ([f64; 6], f64) {
2510    }
2511}
2512
2513cspice_proc! {
2514    /**
2515    Find the set of ID codes of all objects in a specified SPK file.
2516
2517    This function has a [neat version][crate::neat::spkobj].
2518    */
2519    pub fn spkobj(spk: &str, ids: &mut Cell<i32>) {}
2520}
2521
2522cspice_proc! {
2523    /**
2524    Find the coverage window for a specified ephemeris object in a specified SPK file.
2525
2526    This function has a [neat version][crate::neat::spkcov].
2527    */
2528    pub fn spkcov(spk: &str, idcode: i32, cover: &mut Cell<f64>) {}
2529}
2530
2531cspice_proc! {
2532    /**
2533    Create a new SPK file, returning the handle of the opened file.
2534    */
2535    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2536    pub fn spkopn(fname: &str, ifname: &str, ncomch: i32) -> i32 {}
2537}
2538
2539cspice_proc! {
2540    /**
2541    Open an existing SPK file for subsequent write, returning its handle.
2542    */
2543    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2544    pub fn spkopa(fname: &str) -> i32 {}
2545}
2546
2547cspice_proc! {
2548    /**
2549    Close a SPK file opened for read or write.
2550    */
2551    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2552    pub fn spkcls(handle: i32) {}
2553}
2554
2555/**
2556Write a type 9 segment to an SPK file.
2557
2558# Panics
2559
2560Panics if `n` is negative, or larger than `states` or `epochs`: CSPICE reads exactly `n` records
2561from each and has no way of knowing how long they are.
2562*/
2563#[allow(clippy::too_many_arguments)]
2564#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2565pub fn spkw09(
2566    handle: i32,
2567    body: i32,
2568    center: i32,
2569    frame: &str,
2570    first: f64,
2571    last: f64,
2572    segid: &str,
2573    degree: i32,
2574    n: i32,
2575    states: &[[f64; 6]],
2576    epochs: &[f64],
2577) {
2578    let count = usize::try_from(n).expect("the number of states cannot be negative");
2579    assert!(
2580        count <= states.len() && count <= epochs.len(),
2581        "spkw09 was asked for {count} records but got {} states and {} epochs",
2582        states.len(),
2583        epochs.len()
2584    );
2585
2586    let frame = to_cstring(frame);
2587    let segid = to_cstring(segid);
2588
2589    unsafe {
2590        crate::c::spkw09_c(
2591            handle,
2592            body,
2593            center,
2594            frame.as_ptr() as *mut SpiceChar,
2595            first,
2596            last,
2597            segid.as_ptr() as *mut SpiceChar,
2598            degree,
2599            n,
2600            states.as_ptr() as *mut [SpiceDouble; 6],
2601            epochs.as_ptr() as *mut SpiceDouble,
2602        );
2603    }
2604}
2605
2606/* -------------------------------------------------------------------------------------------- */
2607/* Surface geometry                                                                               */
2608/* -------------------------------------------------------------------------------------------- */
2609
2610cspice_proc! {
2611    /**
2612    Compute, for a given observer and a ray emanating from the observer, the surface intercept of
2613    the ray on a target body at a specified epoch, optionally corrected for light time and stellar
2614    aberration.
2615
2616    The surface of the target body may be represented by a triaxial ellipsoid or by topographic data
2617    provided by DSK files.
2618
2619    This routine supersedes `srfxpt`.
2620    */
2621    #[allow(clippy::too_many_arguments)]
2622    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2623    pub fn sincpt(
2624        method: &str,
2625        target: &str,
2626        et: f64,
2627        fixref: &str,
2628        abcorr: &str,
2629        obsrvr: &str,
2630        dref: &str,
2631        dvec: [f64; 3]
2632    ) -> ([f64; 3], f64, [f64; 3], bool) {
2633    }
2634}
2635
2636cspice_proc! {
2637    /**
2638    Compute the rectangular coordinates of the sub-observer point on a target body at a specified
2639    epoch, optionally corrected for light time and stellar aberration.
2640    */
2641    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2642    pub fn subpnt(
2643        method: &str,
2644        target: &str,
2645        et: f64,
2646        fixref: &str,
2647        abcorr: &str,
2648        obsrvr: &str
2649    ) -> ([f64; 3], f64, [f64; 3]) {
2650    }
2651}
2652
2653cspice_proc! {
2654    /**
2655    Compute the rectangular coordinates of the sub-solar point on a target body at a specified
2656    epoch, optionally corrected for light time and stellar aberration.
2657    */
2658    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2659    pub fn subslr(
2660        method: &str,
2661        target: &str,
2662        et: f64,
2663        fixref: &str,
2664        abcorr: &str,
2665        obsrvr: &str
2666    ) -> ([f64; 3], f64, [f64; 3]) {
2667    }
2668}
2669
2670cspice_proc! {
2671    /**
2672    Find the illumination angles---phase, solar incidence, and emission---at a specified surface
2673    point of a target body.
2674    */
2675    #[allow(clippy::too_many_arguments)]
2676    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2677    pub fn ilumin(
2678        method: &str,
2679        target: &str,
2680        et: f64,
2681        fixref: &str,
2682        abcorr: &str,
2683        obsrvr: &str,
2684        spoint: [f64; 3]
2685    ) -> (f64, [f64; 3], f64, f64, f64) {
2686    }
2687}
2688
2689cspice_proc! {
2690    /**
2691    Compute the illumination angles---phase, incidence, and emission---at a specified point on a
2692    target body. Return logical flags indicating whether the surface point is visible from the
2693    observer's position and whether the surface point is illuminated.
2694
2695    The target body's surface is represented using topographic data provided by DSK files, or by a
2696    reference ellipsoid.
2697
2698    The illumination source is a specified ephemeris object.
2699    */
2700    #[allow(clippy::too_many_arguments)]
2701    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2702    pub fn illumf(
2703        method: &str,
2704        target: &str,
2705        ilusrc: &str,
2706        et: f64,
2707        fixref: &str,
2708        abcorr: &str,
2709        obsrvr: &str,
2710        spoint: [f64; 3]
2711    ) -> (f64, [f64; 3], f64, f64, f64, bool, bool) {
2712    }
2713}
2714
2715cspice_proc! {
2716    /**
2717    Determine the intersection of a line-of-sight vector with the surface of an ellipsoid.
2718    */
2719    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2720    pub fn surfpt(positn: [f64; 3], u: [f64; 3], a: f64, b: f64, c: f64) -> ([f64; 3], bool) {}
2721}
2722
2723cspice_proc! {
2724    /**
2725    Locate the point on the surface of an ellipsoid that is nearest to a specified position, and
2726    the altitude of that position above the ellipsoid.
2727    */
2728    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2729    pub fn nearpt(positn: [f64; 3], a: f64, b: f64, c: f64) -> ([f64; 3], f64) {}
2730}
2731
2732cspice_proc! {
2733    /**
2734    Determine the occultation condition (not occulted, partially, etc.) of one target relative to
2735    another target as seen by an observer at a given time, with targets modeled as points,
2736    ellipsoids, or digital shapes (DSK).
2737    */
2738    #[allow(clippy::too_many_arguments)]
2739    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2740    pub fn occult(
2741        targ1: &str,
2742        shape1: &str,
2743        frame1: &str,
2744        targ2: &str,
2745        shape2: &str,
2746        frame2: &str,
2747        abcorr: &str,
2748        obsrvr: &str,
2749        et: f64
2750    ) -> i32 {
2751    }
2752}
2753
2754cspice_proc! {
2755    /**
2756    Compute the apparent phase angle for a target, observer, illuminator set of ephemeris objects.
2757    */
2758    #[return_output]
2759    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2760    pub fn phaseq(et: f64, target: &str, illumn: &str, obsrvr: &str, abcorr: &str) -> f64 {}
2761}
2762
2763/**
2764Map an array of surface points on a target body to the corresponding unit length outward surface
2765normal vectors.
2766*/
2767#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2768pub fn srfnrm(
2769    method: &str,
2770    target: &str,
2771    et: f64,
2772    fixref: &str,
2773    srfpts: &[[f64; 3]],
2774) -> Vec<[f64; 3]> {
2775    let method = to_cstring(method);
2776    let target = to_cstring(target);
2777    let fixref = to_cstring(fixref);
2778    let mut normls = vec![[0.0; 3]; srfpts.len()];
2779
2780    unsafe {
2781        crate::c::srfnrm_c(
2782            method.as_ptr() as *mut SpiceChar,
2783            target.as_ptr() as *mut SpiceChar,
2784            et,
2785            fixref.as_ptr() as *mut SpiceChar,
2786            srfpts.len() as SpiceInt,
2787            srfpts.as_ptr() as *mut [f64; 3],
2788            normls.as_mut_ptr(),
2789        );
2790    }
2791
2792    normls
2793}
2794
2795/**
2796Map an array of planetocentric longitude/latitude pairs to the corresponding surface points on a
2797target body.
2798*/
2799#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2800pub fn latsrf(
2801    method: &str,
2802    target: &str,
2803    et: f64,
2804    fixref: &str,
2805    lonlat: &[[f64; 2]],
2806) -> Vec<[f64; 3]> {
2807    let method = to_cstring(method);
2808    let target = to_cstring(target);
2809    let fixref = to_cstring(fixref);
2810    let mut srfpts = vec![[0.0; 3]; lonlat.len()];
2811
2812    unsafe {
2813        crate::c::latsrf_c(
2814            method.as_ptr() as *mut SpiceChar,
2815            target.as_ptr() as *mut SpiceChar,
2816            et,
2817            fixref.as_ptr() as *mut SpiceChar,
2818            lonlat.len() as SpiceInt,
2819            lonlat.as_ptr() as *mut [f64; 2],
2820            srfpts.as_mut_ptr(),
2821        );
2822    }
2823
2824    srfpts
2825}
2826
2827/**
2828Compute a set of points on the umbral or penumbral terminator of a specified target body, where the
2829target shape is modelled as an ellipsoid.
2830*/
2831#[allow(clippy::too_many_arguments)]
2832#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2833pub fn edterm(
2834    trmtyp: &str,
2835    source: &str,
2836    target: &str,
2837    et: f64,
2838    fixfrm: &str,
2839    abcorr: &str,
2840    obsrvr: &str,
2841    npts: usize,
2842) -> (f64, [f64; 3], Vec<[f64; 3]>) {
2843    let trmtyp = to_cstring(trmtyp);
2844    let source = to_cstring(source);
2845    let target = to_cstring(target);
2846    let fixfrm = to_cstring(fixfrm);
2847    let abcorr = to_cstring(abcorr);
2848    let obsrvr = to_cstring(obsrvr);
2849
2850    let mut trgepc = 0.0;
2851    let mut obspos = [0.0; 3];
2852    let mut termpts = vec![[0.0; 3]; npts];
2853
2854    unsafe {
2855        crate::c::edterm_c(
2856            trmtyp.as_ptr() as *mut SpiceChar,
2857            source.as_ptr() as *mut SpiceChar,
2858            target.as_ptr() as *mut SpiceChar,
2859            et,
2860            fixfrm.as_ptr() as *mut SpiceChar,
2861            abcorr.as_ptr() as *mut SpiceChar,
2862            obsrvr.as_ptr() as *mut SpiceChar,
2863            npts as SpiceInt,
2864            &mut trgepc,
2865            obspos.as_mut_ptr(),
2866            termpts.as_mut_ptr(),
2867        );
2868    }
2869
2870    (trgepc, obspos, termpts)
2871}
2872
2873/**
2874Find limb points on a target body, on cuts of a half-plane pencil rotating about the observer-target
2875vector.
2876
2877Returns, per cut, the number of points found, then the points themselves, the epoch associated with
2878each, and the tangent vector from the observer to each.
2879*/
2880#[allow(clippy::too_many_arguments, clippy::type_complexity)]
2881#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2882pub fn limbpt(
2883    method: &str,
2884    target: &str,
2885    et: f64,
2886    fixref: &str,
2887    abcorr: &str,
2888    corloc: &str,
2889    obsrvr: &str,
2890    refvec: [f64; 3],
2891    rolstp: f64,
2892    ncuts: usize,
2893    schstp: f64,
2894    soltol: f64,
2895    maxn: usize,
2896) -> (Vec<i32>, Vec<[f64; 3]>, Vec<f64>, Vec<[f64; 3]>) {
2897    let method = to_cstring(method);
2898    let target = to_cstring(target);
2899    let fixref = to_cstring(fixref);
2900    let abcorr = to_cstring(abcorr);
2901    let corloc = to_cstring(corloc);
2902    let obsrvr = to_cstring(obsrvr);
2903
2904    let mut npts = vec![0; ncuts.max(1)];
2905    let mut points = vec![[0.0; 3]; maxn];
2906    let mut epochs = vec![0.0; maxn];
2907    let mut tangts = vec![[0.0; 3]; maxn];
2908
2909    unsafe {
2910        crate::c::limbpt_c(
2911            method.as_ptr() as *mut SpiceChar,
2912            target.as_ptr() as *mut SpiceChar,
2913            et,
2914            fixref.as_ptr() as *mut SpiceChar,
2915            abcorr.as_ptr() as *mut SpiceChar,
2916            corloc.as_ptr() as *mut SpiceChar,
2917            obsrvr.as_ptr() as *mut SpiceChar,
2918            refvec.as_ptr() as *mut SpiceDouble,
2919            rolstp,
2920            ncuts as SpiceInt,
2921            schstp,
2922            soltol,
2923            maxn as SpiceInt,
2924            npts.as_mut_ptr(),
2925            points.as_mut_ptr(),
2926            epochs.as_mut_ptr(),
2927            tangts.as_mut_ptr(),
2928        );
2929    }
2930
2931    truncate_cuts(npts, points, epochs, tangts)
2932}
2933
2934/**
2935Find terminator points on a target body, on cuts of a half-plane pencil rotating about the
2936observer-target vector.
2937
2938Shaped like [`limbpt`], with the illumination source named separately.
2939*/
2940#[allow(clippy::too_many_arguments, clippy::type_complexity)]
2941#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
2942pub fn termpt(
2943    method: &str,
2944    ilusrc: &str,
2945    target: &str,
2946    et: f64,
2947    fixref: &str,
2948    abcorr: &str,
2949    corloc: &str,
2950    obsrvr: &str,
2951    refvec: [f64; 3],
2952    rolstp: f64,
2953    ncuts: usize,
2954    schstp: f64,
2955    soltol: f64,
2956    maxn: usize,
2957) -> (Vec<i32>, Vec<[f64; 3]>, Vec<f64>, Vec<[f64; 3]>) {
2958    let method = to_cstring(method);
2959    let ilusrc = to_cstring(ilusrc);
2960    let target = to_cstring(target);
2961    let fixref = to_cstring(fixref);
2962    let abcorr = to_cstring(abcorr);
2963    let corloc = to_cstring(corloc);
2964    let obsrvr = to_cstring(obsrvr);
2965
2966    let mut npts = vec![0; ncuts.max(1)];
2967    let mut points = vec![[0.0; 3]; maxn];
2968    let mut epochs = vec![0.0; maxn];
2969    let mut tangts = vec![[0.0; 3]; maxn];
2970
2971    unsafe {
2972        crate::c::termpt_c(
2973            method.as_ptr() as *mut SpiceChar,
2974            ilusrc.as_ptr() as *mut SpiceChar,
2975            target.as_ptr() as *mut SpiceChar,
2976            et,
2977            fixref.as_ptr() as *mut SpiceChar,
2978            abcorr.as_ptr() as *mut SpiceChar,
2979            corloc.as_ptr() as *mut SpiceChar,
2980            obsrvr.as_ptr() as *mut SpiceChar,
2981            refvec.as_ptr() as *mut SpiceDouble,
2982            rolstp,
2983            ncuts as SpiceInt,
2984            schstp,
2985            soltol,
2986            maxn as SpiceInt,
2987            npts.as_mut_ptr(),
2988            points.as_mut_ptr(),
2989            epochs.as_mut_ptr(),
2990            tangts.as_mut_ptr(),
2991        );
2992    }
2993
2994    truncate_cuts(npts, points, epochs, tangts)
2995}
2996
2997/// Cut the per-cut output arrays down to the number of points CSPICE actually wrote.
2998#[allow(clippy::type_complexity)]
2999fn truncate_cuts(
3000    npts: Vec<SpiceInt>,
3001    mut points: Vec<[f64; 3]>,
3002    mut epochs: Vec<f64>,
3003    mut tangts: Vec<[f64; 3]>,
3004) -> (Vec<i32>, Vec<[f64; 3]>, Vec<f64>, Vec<[f64; 3]>) {
3005    let found = npts.iter().map(|count| count.max(&0)).sum::<SpiceInt>() as usize;
3006    points.truncate(found);
3007    epochs.truncate(found);
3008    tangts.truncate(found);
3009    (npts, points, epochs, tangts)
3010}
3011
3012/**
3013Return the field-of-view (FOV) parameters for a specified instrument. The instrument is specified by
3014its NAIF ID code.
3015
3016This function has a [neat version][crate::neat::getfov].
3017*/
3018pub fn getfov(
3019    instid: i32,
3020    room: usize,
3021    shapelen: usize,
3022    framelen: usize,
3023) -> (String, String, [f64; 3], Vec<[f64; 3]>) {
3024    let mut shape = vec![0 as SpiceChar; shapelen.max(1)];
3025    let mut frame = vec![0 as SpiceChar; framelen.max(1)];
3026    let mut bsight = [0.0; 3];
3027    let mut n = 0;
3028    let mut bounds = vec![[0.0; 3]; room];
3029
3030    unsafe {
3031        crate::c::getfov_c(
3032            instid,
3033            room as SpiceInt,
3034            shapelen as SpiceInt,
3035            framelen as SpiceInt,
3036            shape.as_mut_ptr(),
3037            frame.as_mut_ptr(),
3038            bsight.as_mut_ptr(),
3039            &mut n,
3040            bounds.as_mut_ptr(),
3041        )
3042    };
3043
3044    bounds.truncate(n.max(0) as usize);
3045    (from_cbuf(&shape), from_cbuf(&frame), bsight, bounds)
3046}
3047
3048/* -------------------------------------------------------------------------------------------- */
3049/* Planes and ellipses                                                                            */
3050/* -------------------------------------------------------------------------------------------- */
3051
3052cspice_proc! {
3053    /**
3054    Build a plane from a normal vector and a constant.
3055    */
3056    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3057    pub fn nvc2pl(normal: [f64; 3], constant: f64) -> PLANE {}
3058}
3059
3060cspice_proc! {
3061    /**
3062    Build a plane from a normal vector and a point.
3063    */
3064    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3065    pub fn nvp2pl(normal: [f64; 3], point: [f64; 3]) -> PLANE {}
3066}
3067
3068cspice_proc! {
3069    /**
3070    Build a plane from a point and two spanning vectors.
3071    */
3072    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3073    pub fn psv2pl(point: [f64; 3], span1: [f64; 3], span2: [f64; 3]) -> PLANE {}
3074}
3075
3076cspice_proc! {
3077    /**
3078    Take a plane apart into a unit normal vector and a constant.
3079    */
3080    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3081    pub fn pl2nvc(plane: PLANE) -> ([f64; 3], f64) {}
3082}
3083
3084cspice_proc! {
3085    /**
3086    Take a plane apart into a unit normal vector and a point.
3087    */
3088    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3089    pub fn pl2nvp(plane: PLANE) -> ([f64; 3], [f64; 3]) {}
3090}
3091
3092cspice_proc! {
3093    /**
3094    Take a plane apart into a point and two spanning vectors.
3095    */
3096    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3097    pub fn pl2psv(plane: PLANE) -> ([f64; 3], [f64; 3], [f64; 3]) {}
3098}
3099
3100cspice_proc! {
3101    /**
3102    Build an ellipse from a centre and two generating vectors.
3103    */
3104    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3105    pub fn cgv2el(center: [f64; 3], vec1: [f64; 3], vec2: [f64; 3]) -> ELLIPSE {}
3106}
3107
3108cspice_proc! {
3109    /**
3110    Take an ellipse apart into its centre and its semi-major and semi-minor axes.
3111    */
3112    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3113    pub fn el2cgv(ellipse: ELLIPSE) -> ([f64; 3], [f64; 3], [f64; 3]) {}
3114}
3115
3116cspice_proc! {
3117    /**
3118    Find the semi-axes of the ellipse two vectors generate.
3119    */
3120    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3121    pub fn saelgv(vec1: [f64; 3], vec2: [f64; 3]) -> ([f64; 3], [f64; 3]) {}
3122}
3123
3124cspice_proc! {
3125    /**
3126    Find the intersection of an ellipsoid and a plane, when there is one.
3127    */
3128    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3129    pub fn inedpl(a: f64, b: f64, c: f64, plane: PLANE) -> (ELLIPSE, bool) {}
3130}
3131
3132cspice_proc! {
3133    /**
3134    Find the intersection of an ellipse and a plane: how many points there are, and the points.
3135    */
3136    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3137    pub fn inelpl(ellips: ELLIPSE, plane: PLANE) -> (i32, [f64; 3], [f64; 3]) {}
3138}
3139
3140cspice_proc! {
3141    /**
3142    Find the intersection of a ray and a plane: how many points there are, and the point.
3143    */
3144    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3145    pub fn inrypl(vertex: [f64; 3], dir: [f64; 3], plane: PLANE) -> (i32, [f64; 3]) {}
3146}
3147
3148cspice_proc! {
3149    /**
3150    Find the limb of an ellipsoid as seen from a viewing point.
3151    */
3152    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3153    pub fn edlimb(a: f64, b: f64, c: f64, viewpt: [f64; 3]) -> ELLIPSE {}
3154}
3155
3156cspice_proc! {
3157    /**
3158    Project an ellipse orthogonally onto a plane.
3159    */
3160    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3161    pub fn pjelpl(elin: ELLIPSE, plane: PLANE) -> ELLIPSE {}
3162}
3163
3164cspice_proc! {
3165    /**
3166    Project a vector orthogonally onto a plane.
3167    */
3168    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3169    pub fn vprjp(vin: [f64; 3], plane: PLANE) -> [f64; 3] {}
3170}
3171
3172cspice_proc! {
3173    /**
3174    Invert an orthogonal projection: find the vector of `invpl` that projects onto `vin`.
3175    */
3176    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3177    pub fn vprjpi(vin: [f64; 3], projpl: PLANE, invpl: PLANE) -> ([f64; 3], bool) {}
3178}
3179
3180cspice_proc! {
3181    /**
3182    Find the point of an ellipse nearest a specified point, and the distance between them.
3183    */
3184    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3185    pub fn npelpt(point: [f64; 3], ellips: ELLIPSE) -> ([f64; 3], f64) {}
3186}
3187
3188cspice_proc! {
3189    /**
3190    Find the point of an ellipsoid nearest a line, and the distance between them.
3191    */
3192    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3193    pub fn npedln(
3194        a: f64,
3195        b: f64,
3196        c: f64,
3197        linept: [f64; 3],
3198        linedr: [f64; 3]
3199    ) -> ([f64; 3], f64) {
3200    }
3201}
3202
3203cspice_proc! {
3204    /**
3205    Find the point of a line nearest a specified point, and the distance between them.
3206    */
3207    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3208    pub fn nplnpt(linpt: [f64; 3], lindir: [f64; 3], point: [f64; 3]) -> ([f64; 3], f64) {}
3209}
3210
3211cspice_proc! {
3212    /**
3213    The outward normal of an ellipsoid at a point on its surface.
3214    */
3215    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3216    pub fn surfnm(a: f64, b: f64, c: f64, point: [f64; 3]) -> [f64; 3] {}
3217}
3218
3219cspice_proc! {
3220    /**
3221    Find the state of the intersection of a ray with an ellipsoid, given the state of the ray.
3222    */
3223    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3224    pub fn surfpv(
3225        stvrtx: [f64; 6],
3226        stdir: [f64; 6],
3227        a: f64,
3228        b: f64,
3229        c: f64
3230    ) -> ([f64; 6], bool) {
3231    }
3232}
3233
3234/* -------------------------------------------------------------------------------------------- */
3235/* Surfaces                                                                                       */
3236/* -------------------------------------------------------------------------------------------- */
3237
3238cspice_proc! {
3239    /**
3240    Translate a surface ID code, together with a body ID code, to the corresponding surface name.
3241
3242    The boolean tells whether the returned string is a name rather than the string representation of
3243    the code.
3244
3245    This function has a [neat version][crate::neat::srfc2s].
3246    */
3247    pub fn srfc2s(code: i32, bodyid: i32, #[lenout] srflen: i32) -> (String, bool) {}
3248}
3249
3250cspice_proc! {
3251    /**
3252    Translate a surface ID code, together with a body string, to the corresponding surface name.
3253
3254    This function has a [neat version][crate::neat::srfcss].
3255    */
3256    pub fn srfcss(code: i32, bodstr: &str, #[lenout] srflen: i32) -> (String, bool) {}
3257}
3258
3259cspice_proc! {
3260    /**
3261    Translate a surface string, together with a body string, to the corresponding surface ID code.
3262    */
3263    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3264    pub fn srfs2c(srfstr: &str, bodstr: &str) -> (i32, bool) {}
3265}
3266
3267cspice_proc! {
3268    /**
3269    Translate a surface string, together with a body ID code, to the corresponding surface ID code.
3270    */
3271    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3272    pub fn srfscc(surfce: &str, bodyid: i32) -> (i32, bool) {}
3273}
3274
3275/* -------------------------------------------------------------------------------------------- */
3276/* PCK                                                                                            */
3277/* -------------------------------------------------------------------------------------------- */
3278
3279cspice_proc! {
3280    /**
3281    Find the coverage window for a specified reference frame in a specified binary PCK file.
3282
3283    This function has a [neat version][crate::neat::pckcov].
3284    */
3285    pub fn pckcov(pck: &str, idcode: i32, cover: &mut Cell<f64>) {}
3286}
3287
3288cspice_proc! {
3289    /**
3290    Find the set of reference frame class ID codes of all frames in a specified binary PCK file.
3291
3292    This function has a [neat version][crate::neat::pckfrm].
3293    */
3294    pub fn pckfrm(pck: &str, ids: &mut Cell<i32>) {}
3295}
3296
3297/* -------------------------------------------------------------------------------------------- */
3298/* Two-body orbits                                                                                */
3299/* -------------------------------------------------------------------------------------------- */
3300
3301cspice_proc! {
3302    /**
3303    Determine the state of a body from a set of elliptic, hyperbolic, or parabolic orbital elements.
3304    */
3305    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3306    pub fn conics(elts: [f64; 8], et: f64) -> [f64; 6] {}
3307}
3308
3309cspice_proc! {
3310    /**
3311    Determine the set of osculating conic orbital elements that corresponds to the state of a body
3312    at some epoch.
3313    */
3314    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3315    pub fn oscelt(state: [f64; 6], et: f64, mu: f64) -> [f64; 8] {}
3316}
3317
3318cspice_proc! {
3319    /**
3320    Like [`oscelt`], with the true anomaly, semi-major axis and orbital period appended.
3321    */
3322    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3323    pub fn oscltx(state: [f64; 6], et: f64, mu: f64) -> [f64; 20] {}
3324}
3325
3326cspice_proc! {
3327    /**
3328    Propagate a two body solution from one epoch to another.
3329    */
3330    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3331    pub fn prop2b(gm: f64, pvinit: [f64; 6], dt: f64) -> [f64; 6] {}
3332}
3333
3334/* -------------------------------------------------------------------------------------------- */
3335/* Windows                                                                                        */
3336/* -------------------------------------------------------------------------------------------- */
3337
3338cspice_proc! {
3339    /**
3340    Insert the interval `[left, right]` into a double precision window.
3341    */
3342    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3343    pub fn wninsd(left: f64, right: f64, window: &mut Cell<f64>) {}
3344}
3345
3346cspice_proc! {
3347    /**
3348    Fetch the endpoints of the `n`th interval of a double precision window, counting from zero.
3349    */
3350    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3351    pub fn wnfetd(window: &mut Cell<f64>, n: i32) -> (f64, f64) {}
3352}
3353
3354cspice_proc! {
3355    /**
3356    Return the number of intervals in a double precision window.
3357    */
3358    #[return_output]
3359    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3360    pub fn wncard(window: &mut Cell<f64>) -> i32 {}
3361}
3362
3363cspice_proc! {
3364    /**
3365    Place the complement of a window, relative to the interval `[left, right]`, into `result`.
3366    */
3367    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3368    pub fn wncomd(left: f64, right: f64, window: &mut Cell<f64>, result: &mut Cell<f64>) {}
3369}
3370
3371cspice_proc! {
3372    /**
3373    Contract each interval of a window by `left` at its start and `right` at its end.
3374    */
3375    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3376    pub fn wncond(left: f64, right: f64, window: &mut Cell<f64>) {}
3377}
3378
3379cspice_proc! {
3380    /**
3381    Expand each interval of a window by `left` at its start and `right` at its end.
3382    */
3383    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3384    pub fn wnexpd(left: f64, right: f64, window: &mut Cell<f64>) {}
3385}
3386
3387cspice_proc! {
3388    /**
3389    Place the difference of two windows into `c`.
3390    */
3391    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3392    pub fn wndifd(a: &mut Cell<f64>, b: &mut Cell<f64>, c: &mut Cell<f64>) {}
3393}
3394
3395cspice_proc! {
3396    /**
3397    Place the intersection of two windows into `c`.
3398    */
3399    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3400    pub fn wnintd(a: &mut Cell<f64>, b: &mut Cell<f64>, c: &mut Cell<f64>) {}
3401}
3402
3403cspice_proc! {
3404    /**
3405    Place the union of two windows into `c`.
3406    */
3407    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3408    pub fn wnunid(a: &mut Cell<f64>, b: &mut Cell<f64>, c: &mut Cell<f64>) {}
3409}
3410
3411cspice_proc! {
3412    /**
3413    Whether a point belongs to a window.
3414    */
3415    #[return_output]
3416    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3417    pub fn wnelmd(point: f64, window: &mut Cell<f64>) -> bool {}
3418}
3419
3420cspice_proc! {
3421    /**
3422    Whether an interval is included in a window.
3423    */
3424    #[return_output]
3425    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3426    pub fn wnincd(left: f64, right: f64, window: &mut Cell<f64>) -> bool {}
3427}
3428
3429cspice_proc! {
3430    /**
3431    Compare two windows; `op` is one of `"="`, `"<>"`, `"<="`, `"<"`, `">="` or `">"`.
3432    */
3433    #[return_output]
3434    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3435    pub fn wnreld(a: &mut Cell<f64>, op: &str, b: &mut Cell<f64>) -> bool {}
3436}
3437
3438cspice_proc! {
3439    /**
3440    Replace each interval of a window by one of its endpoints; `side` is `'L'` or `'R'`.
3441    */
3442    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3443    pub fn wnextd(side: char, window: &mut Cell<f64>) {}
3444}
3445
3446cspice_proc! {
3447    /**
3448    Fill the gaps shorter than `sml` between adjacent intervals of a window.
3449    */
3450    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3451    pub fn wnfild(sml: f64, window: &mut Cell<f64>) {}
3452}
3453
3454cspice_proc! {
3455    /**
3456    Drop the intervals of a window shorter than `sml`.
3457    */
3458    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3459    pub fn wnfltd(sml: f64, window: &mut Cell<f64>) {}
3460}
3461
3462cspice_proc! {
3463    /**
3464    Summarize a window: total measure, average and standard deviation of the interval lengths, and
3465    the indices of the shortest and longest intervals.
3466
3467    The two indices point at the *left endpoints* in the flat endpoint array, so they run
3468    `0, 2, 4, ...` rather than `0, 1, 2, ...`; the `n`th interval is reported as `2 * n`. Ties go
3469    to the first interval of that length.
3470    */
3471    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3472    #[allow(clippy::type_complexity)]
3473    pub fn wnsumd(window: &mut Cell<f64>) -> (f64, f64, f64, i32, i32) {}
3474}
3475
3476cspice_proc! {
3477    /**
3478    Validate a double precision window built by writing into a cell directly.
3479    */
3480    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3481    pub fn wnvald(size: i32, n: i32, window: &mut Cell<f64>) {}
3482}
3483
3484/* -------------------------------------------------------------------------------------------- */
3485/* Sets and cells                                                                                 */
3486/* -------------------------------------------------------------------------------------------- */
3487
3488cspice_proc! {
3489    /**
3490    Place the union of two sets into `c`.
3491    */
3492    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3493    pub fn union<T: CellItem>(a: &mut Cell<T>, b: &mut Cell<T>, c: &mut Cell<T>) {}
3494}
3495
3496cspice_proc! {
3497    /**
3498    Place the intersection of two sets into `c`.
3499    */
3500    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3501    pub fn inter<T: CellItem>(a: &mut Cell<T>, b: &mut Cell<T>, c: &mut Cell<T>) {}
3502}
3503
3504cspice_proc! {
3505    /**
3506    Place the difference of two sets into `c`.
3507    */
3508    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3509    pub fn diff<T: CellItem>(a: &mut Cell<T>, b: &mut Cell<T>, c: &mut Cell<T>) {}
3510}
3511
3512cspice_proc! {
3513    /**
3514    Copy the contents of one cell into another.
3515    */
3516    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3517    pub fn copy<T: CellItem>(a: &mut Cell<T>, b: &mut Cell<T>) {}
3518}
3519
3520cspice_proc! {
3521    /**
3522    The cardinality of a cell; [`Cell::len`] reports the same number without a CSPICE call.
3523    */
3524    #[return_output]
3525    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3526    pub fn card<T: CellItem>(cell: &mut Cell<T>) -> i32 {}
3527}
3528
3529cspice_proc! {
3530    /**
3531    Set the cardinality of a cell.
3532    */
3533    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3534    pub fn scard<T: CellItem>(card: i32, cell: &mut Cell<T>) {}
3535}
3536
3537cspice_proc! {
3538    /**
3539    The size of a cell; [`Cell::capacity`] reports the same number without a CSPICE call.
3540    */
3541    #[return_output]
3542    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3543    pub fn size<T: CellItem>(cell: &mut Cell<T>) -> i32 {}
3544}
3545
3546cspice_proc! {
3547    /**
3548    Set the size of a cell.
3549    */
3550    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3551    pub fn ssize<T: CellItem>(size: i32, cell: &mut Cell<T>) {}
3552}
3553
3554cspice_proc! {
3555    /**
3556    Turn a cell holding `n` items into a set, by sorting it and removing the duplicates.
3557    */
3558    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3559    pub fn valid<T: CellItem>(size: i32, n: i32, a: &mut Cell<T>) {}
3560}
3561
3562cspice_proc! {
3563    /**
3564    Whether an integer belongs to a set.
3565    */
3566    #[return_output]
3567    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3568    pub fn elemi(item: i32, set: &mut Cell<i32>) -> bool {}
3569}
3570
3571cspice_proc! {
3572    /**
3573    Whether a double precision number belongs to a set.
3574    */
3575    #[return_output]
3576    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3577    pub fn elemd(item: f64, set: &mut Cell<f64>) -> bool {}
3578}
3579
3580cspice_proc! {
3581    /**
3582    Whether a string belongs to a set.
3583    */
3584    #[return_output]
3585    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3586    pub fn elemc(item: &str, set: &mut Cell<String>) -> bool {}
3587}
3588
3589cspice_proc! {
3590    /**
3591    Insert an integer into a set.
3592    */
3593    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3594    pub fn insrti(item: i32, set: &mut Cell<i32>) {}
3595}
3596
3597cspice_proc! {
3598    /**
3599    Insert a double precision number into a set.
3600    */
3601    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3602    pub fn insrtd(item: f64, set: &mut Cell<f64>) {}
3603}
3604
3605cspice_proc! {
3606    /**
3607    Insert a string into a set.
3608    */
3609    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3610    pub fn insrtc(item: &str, set: &mut Cell<String>) {}
3611}
3612
3613cspice_proc! {
3614    /**
3615    Remove an integer from a set.
3616    */
3617    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3618    pub fn removi(item: i32, set: &mut Cell<i32>) {}
3619}
3620
3621cspice_proc! {
3622    /**
3623    Remove a double precision number from a set.
3624    */
3625    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3626    pub fn removd(item: f64, set: &mut Cell<f64>) {}
3627}
3628
3629cspice_proc! {
3630    /**
3631    Remove a string from a set.
3632    */
3633    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3634    pub fn removc(item: &str, set: &mut Cell<String>) {}
3635}
3636
3637cspice_proc! {
3638    /**
3639    Append an integer to a cell; [`Cell::push`] is the idiomatic form.
3640    */
3641    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3642    pub fn appndi(item: i32, cell: &mut Cell<i32>) {}
3643}
3644
3645cspice_proc! {
3646    /**
3647    Append a double precision number to a cell; [`Cell::push`] is the idiomatic form.
3648    */
3649    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3650    pub fn appndd(item: f64, cell: &mut Cell<f64>) {}
3651}
3652
3653cspice_proc! {
3654    /**
3655    Append a string to a cell; [`Cell::push`] is the idiomatic form.
3656    */
3657    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3658    pub fn appndc(item: &str, cell: &mut Cell<String>) {}
3659}
3660
3661/* -------------------------------------------------------------------------------------------- */
3662/* Geometry finder                                                                                */
3663/* -------------------------------------------------------------------------------------------- */
3664
3665cspice_proc! {
3666    /**
3667    Determine the time windows, within a confinement window, when one body is occulted by or in
3668    transit across another, as seen from an observer.
3669
3670    This function has a [neat version][crate::neat::gfoclt].
3671    */
3672    #[allow(clippy::too_many_arguments)]
3673    pub fn gfoclt(
3674        occtyp: &str,
3675        front: &str,
3676        fshape: &str,
3677        fframe: &str,
3678        back: &str,
3679        bshape: &str,
3680        bframe: &str,
3681        abcorr: &str,
3682        obsrvr: &str,
3683        step: f64,
3684        cnfine: &mut Cell<f64>,
3685        result: &mut Cell<f64>
3686    ) {
3687    }
3688}
3689
3690/* -------------------------------------------------------------------------------------------- */
3691/* Two-line elements                                                                              */
3692/* -------------------------------------------------------------------------------------------- */
3693
3694/// Number of elements a two-line element set is parsed into.
3695pub const TLE_NELTS: usize = 10;
3696
3697/// Number of geophysical constants the SGP4 propagator needs.
3698pub const TLE_NGEOPHS: usize = 8;
3699
3700/**
3701Parse the two lines of a NORAD two-line element set into the epoch and the element set CSPICE uses.
3702
3703`frstyr` is the first year of the century the two digit years in the set belong to; 1957, the start
3704of the space age, is the usual choice.
3705
3706# Panics
3707
3708Panics if `lines` does not hold exactly two lines.
3709*/
3710#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3711pub fn getelm<S: AsRef<str>>(frstyr: i32, lines: &[S]) -> (f64, [f64; TLE_NELTS]) {
3712    assert!(
3713        lines.len() == 2,
3714        "a two-line element set has two lines, got {}",
3715        lines.len()
3716    );
3717
3718    // CSPICE reads the pair out of one contiguous, fixed stride, char array.
3719    let lineln = lines
3720        .iter()
3721        .map(|line| line.as_ref().len())
3722        .max()
3723        .unwrap_or(0)
3724        + 1;
3725    let mut buffer = vec![0 as SpiceChar; 2 * lineln];
3726    for (index, line) in lines.iter().enumerate() {
3727        let slot = &mut buffer[index * lineln..(index + 1) * lineln];
3728        for (target, byte) in slot.iter_mut().zip(line.as_ref().as_bytes()) {
3729            *target = *byte as SpiceChar;
3730        }
3731    }
3732
3733    let mut epoch = 0.0;
3734    let mut elems = [0.0; TLE_NELTS];
3735
3736    unsafe {
3737        crate::c::getelm_c(
3738            frstyr,
3739            lineln as SpiceInt,
3740            buffer.as_ptr().cast(),
3741            &mut epoch,
3742            elems.as_mut_ptr(),
3743        );
3744    }
3745
3746    (epoch, elems)
3747}
3748
3749cspice_proc! {
3750    /**
3751    Evaluate a two-line element set with the SGP4 propagator.
3752
3753    `geophs` holds the eight geophysical constants the propagator needs, in the order
3754    `J2, J3, J4, KE, QO, SO, ER, AE`; they normally come from a geophysical constants kernel.
3755    */
3756    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3757    pub fn evsgp4(et: f64, geophs: [f64; 8], elems: [f64; 10]) -> [f64; 6] {}
3758}
3759
3760/* -------------------------------------------------------------------------------------------- */
3761/* Searching, sorting and ordering                                                                */
3762/* -------------------------------------------------------------------------------------------- */
3763
3764/// Generate the wrappers that search a slice for a value.
3765macro_rules! search {
3766    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
3767        #[doc = $doc]
3768        ///
3769        /// Returns the index found, or `-1`.
3770        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3771        pub fn $name(value: $ty, array: &[$ty]) -> i32 {
3772            unsafe { crate::c::$cname(value, array.len() as SpiceInt, array.as_ptr() as *mut _) }
3773        }
3774    )*};
3775}
3776
3777search! {
3778    bsrchd(f64) => bsrchd_c, "Binary search a sorted array of doubles.";
3779    bsrchi(i32) => bsrchi_c, "Binary search a sorted array of integers.";
3780    lstled(f64) => lstled_c, "Last index of the doubles less than or equal to a value.";
3781    lstlei(i32) => lstlei_c, "Last index of the integers less than or equal to a value.";
3782    lstltd(f64) => lstltd_c, "Last index of the doubles strictly less than a value.";
3783    lstlti(i32) => lstlti_c, "Last index of the integers strictly less than a value.";
3784}
3785
3786/// Generate the wrappers that sort a slice in place.
3787macro_rules! sort_in_place {
3788    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
3789        #[doc = $doc]
3790        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3791        pub fn $name(array: &mut [$ty]) {
3792            unsafe { crate::c::$cname(array.len() as SpiceInt, array.as_mut_ptr()) }
3793        }
3794    )*};
3795}
3796
3797sort_in_place! {
3798    shelld(f64) => shelld_c, "Sort an array of doubles in place.";
3799    shelli(i32) => shelli_c, "Sort an array of integers in place.";
3800}
3801
3802/// Generate the wrappers that report the order of a slice without moving it.
3803macro_rules! order_of {
3804    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
3805        #[doc = $doc]
3806        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3807        pub fn $name(array: &[$ty]) -> Vec<i32> {
3808            let mut iorder = vec![0; array.len()];
3809            unsafe {
3810                crate::c::$cname(
3811                    array.as_ptr() as *mut _,
3812                    array.len() as SpiceInt,
3813                    iorder.as_mut_ptr(),
3814                )
3815            };
3816            iorder
3817        }
3818    )*};
3819}
3820
3821order_of! {
3822    orderd(f64) => orderd_c, "The order vector that sorts an array of doubles.";
3823    orderi(i32) => orderi_c, "The order vector that sorts an array of integers.";
3824}
3825
3826/// Generate the wrappers that apply an order vector to a slice in place.
3827macro_rules! reorder {
3828    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
3829        #[doc = $doc]
3830        ///
3831        /// # Panics
3832        ///
3833        /// Panics if the order vector is not as long as the array.
3834        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3835        pub fn $name(iorder: &[i32], array: &mut [$ty]) {
3836            assert!(
3837                iorder.len() == array.len(),
3838                "the order vector has {} entries for an array of {}",
3839                iorder.len(),
3840                array.len()
3841            );
3842            unsafe {
3843                crate::c::$cname(
3844                    iorder.as_ptr() as *mut SpiceInt,
3845                    array.len() as SpiceInt,
3846                    array.as_mut_ptr(),
3847                )
3848            };
3849        }
3850    )*};
3851}
3852
3853reorder! {
3854    reordd(f64) => reordd_c, "Reorder an array of doubles in place.";
3855    reordi(i32) => reordi_c, "Reorder an array of integers in place.";
3856    reordl(crate::c::SpiceBoolean) => reordl_c, "Reorder an array of logical flags in place.";
3857}
3858
3859cspice_proc! {
3860    /**
3861    Bracket a double precision number between two endpoints.
3862    */
3863    #[return_output]
3864    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3865    pub fn brcktd(number: f64, end1: f64, end2: f64) -> f64 {}
3866}
3867
3868cspice_proc! {
3869    /**
3870    Bracket an integer between two endpoints.
3871    */
3872    #[return_output]
3873    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3874    pub fn brckti(number: i32, end1: i32, end2: i32) -> i32 {}
3875}
3876
3877/**
3878The sum of an array of doubles.
3879*/
3880#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3881pub fn sumad(array: &[f64]) -> f64 {
3882    unsafe { crate::c::sumad_c(array.as_ptr() as *mut SpiceDouble, array.len() as SpiceInt) }
3883}
3884
3885/**
3886The sum of an array of integers.
3887*/
3888#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3889pub fn sumai(array: &[i32]) -> i32 {
3890    unsafe { crate::c::sumai_c(array.as_ptr() as *mut SpiceInt, array.len() as SpiceInt) }
3891}
3892
3893/**
3894Whether an array is an order vector: a permutation of `0 .. n`.
3895*/
3896#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3897pub fn isordv(array: &[i32]) -> bool {
3898    unsafe { crate::c::isordv_c(array.as_ptr() as *mut SpiceInt, array.len() as SpiceInt) != 0 }
3899}
3900
3901/// Generate the wrappers that search a strided array of strings.
3902macro_rules! search_strings {
3903    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
3904        #[doc = $doc]
3905        ///
3906        /// Returns the index found, or `-1`.
3907        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3908        pub fn $name<S: AsRef<str>>(value: &str, array: &[S]) -> i32 {
3909            let value = to_cstring(value);
3910            let (buffer, stride) = to_strided(array);
3911            unsafe {
3912                crate::c::$cname(
3913                    value.as_ptr() as *mut SpiceChar,
3914                    array.len() as SpiceInt,
3915                    stride as SpiceInt,
3916                    buffer.as_ptr().cast(),
3917                )
3918            }
3919        }
3920    )*};
3921}
3922
3923search_strings! {
3924    bsrchc => bsrchc_c, "Binary search a sorted array of strings.";
3925    esrchc => esrchc_c, "Search an array of strings, ignoring case and trailing blanks.";
3926    lstlec => lstlec_c, "Last index of the strings less than or equal to a value.";
3927    lstltc => lstltc_c, "Last index of the strings strictly less than a value.";
3928}
3929
3930/**
3931Binary search an array of integers ordered by an order vector.
3932
3933Returns the index found, or `-1`.
3934*/
3935#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3936pub fn bschoi(value: i32, array: &[i32], order: &[i32]) -> i32 {
3937    unsafe {
3938        crate::c::bschoi_c(
3939            value,
3940            array.len() as SpiceInt,
3941            array.as_ptr() as *mut SpiceInt,
3942            order.as_ptr() as *mut SpiceInt,
3943        )
3944    }
3945}
3946
3947/**
3948Binary search an array of strings ordered by an order vector.
3949
3950Returns the index found, or `-1`.
3951*/
3952#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3953pub fn bschoc<S: AsRef<str>>(value: &str, array: &[S], order: &[i32]) -> i32 {
3954    let value = to_cstring(value);
3955    let (buffer, stride) = to_strided(array);
3956    unsafe {
3957        crate::c::bschoc_c(
3958            value.as_ptr() as *mut SpiceChar,
3959            array.len() as SpiceInt,
3960            stride as SpiceInt,
3961            buffer.as_ptr().cast(),
3962            order.as_ptr() as *mut SpiceInt,
3963        )
3964    }
3965}
3966
3967/**
3968The order vector that sorts an array of strings.
3969*/
3970#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3971pub fn orderc<S: AsRef<str>>(array: &[S]) -> Vec<i32> {
3972    let (buffer, stride) = to_strided(array);
3973    let mut iorder = vec![0; array.len()];
3974    unsafe {
3975        crate::c::orderc_c(
3976            stride as SpiceInt,
3977            buffer.as_ptr().cast(),
3978            array.len() as SpiceInt,
3979            iorder.as_mut_ptr(),
3980        )
3981    };
3982    iorder
3983}
3984
3985/**
3986Apply an order vector to an array of strings.
3987
3988# Panics
3989
3990Panics if the order vector is not as long as the array.
3991*/
3992#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
3993pub fn reordc<S: AsRef<str>>(iorder: &[i32], array: &[S]) -> Vec<String> {
3994    assert!(
3995        iorder.len() == array.len(),
3996        "the order vector has {} entries for an array of {}",
3997        iorder.len(),
3998        array.len()
3999    );
4000    let (mut buffer, stride) = to_strided(array);
4001    unsafe {
4002        crate::c::reordc_c(
4003            iorder.as_ptr() as *mut SpiceInt,
4004            array.len() as SpiceInt,
4005            stride as SpiceInt,
4006            buffer.as_mut_ptr().cast(),
4007        )
4008    };
4009    from_strided(&buffer, stride, array.len())
4010}
4011
4012/**
4013Sort an array of strings.
4014*/
4015#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4016pub fn shellc<S: AsRef<str>>(array: &[S]) -> Vec<String> {
4017    let (mut buffer, stride) = to_strided(array);
4018    unsafe {
4019        crate::c::shellc_c(
4020            array.len() as SpiceInt,
4021            stride as SpiceInt,
4022            buffer.as_mut_ptr().cast(),
4023        )
4024    };
4025    from_strided(&buffer, stride, array.len())
4026}
4027
4028/* -------------------------------------------------------------------------------------------- */
4029/* Strings                                                                                        */
4030/* -------------------------------------------------------------------------------------------- */
4031
4032cspice_proc! {
4033    /**
4034    Convert a string to lower case.
4035    */
4036    pub fn lcase(input: &str, #[lenout] lenout: i32) -> String {}
4037}
4038
4039cspice_proc! {
4040    /**
4041    Convert a string to upper case.
4042    */
4043    pub fn ucase(input: &str, #[lenout] lenout: i32) -> String {}
4044}
4045
4046cspice_proc! {
4047    /**
4048    Compress runs of a delimiter down to `n` of them.
4049    */
4050    pub fn cmprss(delim: char, n: i32, input: &str, #[lenout] lenout: i32) -> String {}
4051}
4052
4053cspice_proc! {
4054    /**
4055    Whether two strings are equivalent, ignoring case and leading and trailing blanks.
4056    */
4057    #[return_output]
4058    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4059    pub fn eqstr(a: &str, b: &str) -> bool {}
4060}
4061
4062cspice_proc! {
4063    /**
4064    Match a string against a template, ignoring case; `wstr` matches any run of characters and
4065    `wchr` any single one.
4066    */
4067    #[return_output]
4068    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4069    pub fn matchi(string: &str, templ: &str, wstr: char, wchr: char) -> bool {}
4070}
4071
4072cspice_proc! {
4073    /**
4074    Match a string against a template, respecting case.
4075    */
4076    #[return_output]
4077    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4078    pub fn matchw(string: &str, templ: &str, wstr: char, wchr: char) -> bool {}
4079}
4080
4081cspice_proc! {
4082    /**
4083    Replace a marker in a string with a string.
4084    */
4085    pub fn repmc(input: &str, marker: &str, value: &str, #[lenout] lenout: i32) -> String {}
4086}
4087
4088cspice_proc! {
4089    /**
4090    Replace a marker in a string with a double precision number.
4091    */
4092    pub fn repmd(
4093        input: &str,
4094        marker: &str,
4095        value: f64,
4096        sigdig: i32,
4097        #[lenout] lenout: i32
4098    ) -> String {
4099    }
4100}
4101
4102cspice_proc! {
4103    /**
4104    Replace a marker in a string with a formatted double precision number; `format` is `'E'` or
4105    `'F'`.
4106    */
4107    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4108    #[allow(clippy::too_many_arguments)]
4109    pub fn repmf(
4110        input: &str,
4111        marker: &str,
4112        value: f64,
4113        sigdig: i32,
4114        format: char,
4115        #[lenout] lenout: i32
4116    ) -> String {
4117    }
4118}
4119
4120cspice_proc! {
4121    /**
4122    Replace a marker in a string with an integer.
4123    */
4124    pub fn repmi(input: &str, marker: &str, value: i32, #[lenout] lenout: i32) -> String {}
4125}
4126
4127cspice_proc! {
4128    /**
4129    Replace a marker in a string with the text of a boolean; `rtcase` picks the capitalisation.
4130    */
4131    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4132    pub fn repml(
4133        input: &str,
4134        marker: &str,
4135        value: bool,
4136        rtcase: char,
4137        #[lenout] outlen: i32
4138    ) -> String {
4139    }
4140}
4141
4142cspice_proc! {
4143    /**
4144    Replace a marker in a string with an ordinal number; `strcase` picks the capitalisation.
4145    */
4146    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4147    #[cname(repmot_c)]
4148    pub fn repmot(
4149        input: &str,
4150        marker: &str,
4151        value: i32,
4152        strcase: char,
4153        #[lenout] lenout: i32
4154    ) -> String {
4155    }
4156}
4157
4158/**
4159Split a string at the first run of blanks, into the first word and the rest.
4160*/
4161pub fn nextwd(string: &str, nexlen: usize, reslen: usize) -> (String, String) {
4162    let string = to_cstring(string);
4163    let mut next = vec![0 as SpiceChar; nexlen.max(1)];
4164    let mut rest = vec![0 as SpiceChar; reslen.max(1)];
4165
4166    unsafe {
4167        crate::c::nextwd_c(
4168            string.as_ptr() as *mut SpiceChar,
4169            nexlen as SpiceInt,
4170            reslen as SpiceInt,
4171            next.as_mut_ptr(),
4172            rest.as_mut_ptr(),
4173        )
4174    };
4175
4176    (from_cbuf(&next), from_cbuf(&rest))
4177}
4178
4179/**
4180Split a list on a single delimiter.
4181
4182This function has a [neat version][crate::neat::lparse].
4183*/
4184pub fn lparse(list: &str, delim: &str, nmax: usize, lenout: usize) -> Vec<String> {
4185    let list = to_cstring(list);
4186    let delim = to_cstring(delim);
4187    let lenout = lenout.max(1);
4188    let mut buffer = vec![0 as SpiceChar; nmax.max(1) * lenout];
4189    let mut n = 0;
4190
4191    unsafe {
4192        crate::c::lparse_c(
4193            list.as_ptr() as *mut SpiceChar,
4194            delim.as_ptr() as *mut SpiceChar,
4195            nmax as SpiceInt,
4196            lenout as SpiceInt,
4197            &mut n,
4198            buffer.as_mut_ptr().cast(),
4199        )
4200    };
4201
4202    from_strided(&buffer, lenout, n.max(0) as usize)
4203}
4204
4205/**
4206Split a list on any of a set of delimiters, treating runs of them as one.
4207
4208This function has a [neat version][crate::neat::lparsm].
4209*/
4210pub fn lparsm(list: &str, delims: &str, nmax: usize, lenout: usize) -> Vec<String> {
4211    let list = to_cstring(list);
4212    let delims = to_cstring(delims);
4213    let lenout = lenout.max(1);
4214    let mut buffer = vec![0 as SpiceChar; nmax.max(1) * lenout];
4215    let mut n = 0;
4216
4217    unsafe {
4218        crate::c::lparsm_c(
4219            list.as_ptr() as *mut SpiceChar,
4220            delims.as_ptr() as *mut SpiceChar,
4221            nmax as SpiceInt,
4222            lenout as SpiceInt,
4223            &mut n,
4224            buffer.as_mut_ptr().cast(),
4225        )
4226    };
4227
4228    from_strided(&buffer, lenout, n.max(0) as usize)
4229}
4230
4231/* ---------------------------------------------------------------------------------------------- */
4232/* Units, numbers and text                                                                        */
4233/* ---------------------------------------------------------------------------------------------- */
4234
4235cspice_proc! {
4236    /**
4237    Take a measurement X, the units associated with X, and units to which X should be converted; return Y --- the value of the measurement in the output units.
4238    */
4239    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4240    pub fn convrt(x: f64, input: &str, output: &str) -> f64 {}
4241}
4242
4243cspice_proc! {
4244    /**
4245    Return the value of the largest (positive) number representable in a double precision variable.
4246    */
4247    #[return_output]
4248    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4249    pub fn dpmax() -> f64 {}
4250}
4251
4252cspice_proc! {
4253    /**
4254    Return the value of the smallest (negative) number representable in a double precision variable.
4255    */
4256    #[return_output]
4257    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4258    pub fn dpmin() -> f64 {}
4259}
4260
4261cspice_proc! {
4262    /**
4263    Convert a double precision number to an equivalent character string using a base 16 "scientific notation."
4264    */
4265    pub fn dp2hx(number: f64, #[lenout] lenout: i32) -> (String, i32) {}
4266}
4267
4268cspice_proc! {
4269    /**
4270    Convert a string representing a double precision number in a base 16 "scientific notation" into its equivalent double precision number.
4271    */
4272    pub fn hx2dp(string: &str, #[lenout] lenout: i32) -> (f64, bool, String) {}
4273}
4274
4275cspice_proc! {
4276    /**
4277    Find the first occurrence in a string of a character belonging to a collection of characters, starting at a specified location, searching forward.
4278    */
4279    #[return_output]
4280    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4281    pub fn cpos(string: &str, chars: &str, start: i32) -> i32 {}
4282}
4283
4284cspice_proc! {
4285    /**
4286    Find the first occurrence in a string of a character belonging to a collection of characters, starting at a specified location, searching in reverse.
4287    */
4288    #[return_output]
4289    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4290    pub fn cposr(string: &str, chars: &str, start: i32) -> i32 {}
4291}
4292
4293cspice_proc! {
4294    /**
4295    Find the first occurrence in a string of a substring, starting at a specified location, searching forward.
4296    */
4297    #[return_output]
4298    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4299    pub fn pos(string: &str, substr: &str, start: i32) -> i32 {}
4300}
4301
4302cspice_proc! {
4303    /**
4304    Find the first occurrence in a string of a substring, starting at a specified location, searching backward.
4305    */
4306    #[return_output]
4307    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4308    pub fn posr(string: &str, substr: &str, start: i32) -> i32 {}
4309}
4310
4311cspice_proc! {
4312    /**
4313    Convert from an ephemeris epoch measured in seconds past the epoch of J2000 to a calendar string format using a formal calendar free of leapseconds.
4314    */
4315    pub fn etcal(et: f64, #[lenout] lenout: i32) -> String {}
4316}
4317
4318cspice_proc! {
4319    /**
4320    Restrict the set of strings that are recognized by SPICE time parsing routines to those that have standard values for all time components.
4321    */
4322    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4323    pub fn tparch(kind: &str) {}
4324}
4325
4326cspice_proc! {
4327    /**
4328    Determine if a kernel pool variable is present and if so that it has the correct size and type.
4329    */
4330    #[return_output]
4331    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4332    pub fn badkpv(caller: &str, name: &str, comp: &str, size: i32, divby: i32, kind: char) -> bool {}
4333}
4334
4335/* ---------------------------------------------------------------------------------------------- */
4336/* Bodies, frames and the kernel pool                                                             */
4337/* ---------------------------------------------------------------------------------------------- */
4338
4339cspice_proc! {
4340    /**
4341    Return the frame name, frame ID, and center associated with a given frame class and class ID.
4342    */
4343    pub fn ccifrm(frclss: i32, clssid: i32, #[lenout] lenout: i32) -> (i32, String, i32, bool) {}
4344}
4345
4346cspice_proc! {
4347    /**
4348    Retrieve frame ID code and name to associate with a frame center.
4349    */
4350    pub fn cidfrm(cent: i32, #[lenout] lenout: i32) -> (i32, String, bool) {}
4351}
4352
4353cspice_proc! {
4354    /**
4355    Retrieve frame ID code and name to associate with an object.
4356    */
4357    pub fn cnmfrm(cname: &str, #[lenout] lenout: i32) -> (i32, String, bool) {}
4358}
4359
4360cspice_proc! {
4361    /**
4362    Return a SPICE set containing the frame IDs of all built-in frames of a specified class.
4363    */
4364    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4365    pub fn bltfrm(frmcls: i32, idset: &mut Cell<i32>) {}
4366}
4367
4368cspice_proc! {
4369    /**
4370    Indicate whether or not any watched kernel variables that have a specified agent on their notification list have been updated.
4371    */
4372    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4373    pub fn cvpool(agent: &str) -> bool {}
4374}
4375
4376/* ---------------------------------------------------------------------------------------------- */
4377/* Assorted routines                                                                              */
4378/* ---------------------------------------------------------------------------------------------- */
4379
4380cspice_proc! {
4381    /**
4382    Return the azimuth/elevation coordinates of a specified target relative to an "observer," where the observer has constant position in a specified reference frame. The observer's position is provided by the calling program rather than by loaded SPK files.
4383    */
4384    #[allow(clippy::too_many_arguments)]
4385    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4386    pub fn azlcpo(method: &str, target: &str, et: f64, abcorr: &str, azccw: bool, elplsz: bool, obspos: [f64; 3], obsctr: &str, obsref: &str) -> ([f64; 6], f64) {}
4387}
4388
4389cspice_proc! {
4390    /**
4391    Define a body name/ID code pair for later translation via bodn2c_c or bodc2n_c.
4392    */
4393    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4394    pub fn boddef(name: &str, code: i32) {}
4395}
4396
4397cspice_proc! {
4398    /**
4399    Inform the CSPICE error handling mechanism of entry into a routine.
4400    */
4401    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4402    pub fn chkin(module: &str) {}
4403}
4404
4405cspice_proc! {
4406    /**
4407    Inform the CSPICE error handling mechanism of exit from a routine.
4408    */
4409    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4410    pub fn chkout(module: &str) {}
4411}
4412
4413cspice_proc! {
4414    /**
4415    Compute the state (position and velocity) of an ellipsoid surface point nearest to the position component of a specified state.
4416    */
4417    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4418    pub fn dnearp(state: [f64; 6], a: f64, b: f64, c: f64) -> ([f64; 6], [f64; 2], bool) {}
4419}
4420
4421cspice_proc! {
4422    /**
4423    Compute the unit vector parallel to the cross product of two 3-dimensional vectors and the derivative of this unit vector.
4424    */
4425    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4426    pub fn ducrss(s1: [f64; 6], s2: [f64; 6]) -> [f64; 6] {}
4427}
4428
4429cspice_proc! {
4430    /**
4431    Compute the cross product of two 3-dimensional vectors and the derivative of this cross product.
4432    */
4433    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4434    pub fn dvcrss(s1: [f64; 6], s2: [f64; 6]) -> [f64; 6] {}
4435}
4436
4437cspice_proc! {
4438    /**
4439    Compute the derivative of the dot product of two double precision position vectors.
4440    */
4441    #[return_output]
4442    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4443    pub fn dvdot(s1: [f64; 6], s2: [f64; 6]) -> f64 {}
4444}
4445
4446cspice_proc! {
4447    /**
4448    Find the unit vector corresponding to a state vector and the derivative of the unit vector.
4449    */
4450    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4451    pub fn dvhat(s1: [f64; 6]) -> [f64; 6] {}
4452}
4453
4454cspice_proc! {
4455    /**
4456    Calculate the derivative of the norm of a 3-vector.
4457    */
4458    #[return_output]
4459    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4460    pub fn dvnorm(state: [f64; 6]) -> f64 {}
4461}
4462
4463cspice_proc! {
4464    /**
4465    Delete a variable from the kernel pool.
4466    */
4467    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4468    pub fn dvpool(name: &str) {}
4469}
4470
4471cspice_proc! {
4472    /**
4473    Calculate the time derivative of the separation angle between two input states, S1 and S2.
4474    */
4475    #[return_output]
4476    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4477    pub fn dvsep(s1: [f64; 6], s2: [f64; 6]) -> f64 {}
4478}
4479
4480cspice_proc! {
4481    /**
4482    Return the unique point on an ellipsoid's surface where the outward normal direction is a given vector.
4483    */
4484    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4485    pub fn ednmpt(a: f64, b: f64, c: f64, normal: [f64; 3]) -> [f64; 3] {}
4486}
4487
4488cspice_proc! {
4489    /**
4490    Scale a point so that it lies on the surface of a specified triaxial ellipsoid that is centered at the origin and aligned with the Cartesian coordinate axes.
4491    */
4492    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4493    pub fn edpnt(p: [f64; 3], a: f64, b: f64, c: f64) -> [f64; 3] {}
4494}
4495
4496cspice_proc! {
4497    /**
4498    Compute the state (position and velocity) of an object whose trajectory is described via equinoctial elements relative to some fixed plane (usually the equatorial plane of some planet).
4499    */
4500    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4501    pub fn eqncpv(et: f64, epoch: f64, eqel: [f64; 9], rapol: f64, decpol: f64) -> [f64; 6] {}
4502}
4503
4504cspice_proc! {
4505    /**
4506    Whether a routine should return immediately because the toolkit is in an error state.
4507
4508    Named `return_c` rather than `return`, which is a keyword in Rust. It is the only routine in
4509    the toolkit whose name has to change, and SpiceyPy renames it the same way for the same reason.
4510    */
4511    #[return_output]
4512    #[cname(return_c)]
4513    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4514    pub fn return_c() -> bool {}
4515}
4516
4517cspice_proc! {
4518    /**
4519    Signal an error, with the short message given.
4520    */
4521    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4522    pub fn sigerr(message: &str) {}
4523}
4524
4525cspice_proc! {
4526    /**
4527    Substitute a double precision number for the first occurrence of a marker in the long error
4528    message being built.
4529    */
4530    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4531    pub fn errdp(marker: &str, number: f64) {}
4532}
4533
4534cspice_proc! {
4535    /**
4536    Substitute an integer for the first occurrence of a marker in the long error message being
4537    built.
4538    */
4539    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4540    pub fn errint(marker: &str, number: i32) {}
4541}
4542
4543cspice_proc! {
4544    /**
4545    Substitute a character string for the first occurrence of a marker in the current long error message.
4546    */
4547    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4548    pub fn errch(marker: &str, string: &str) {}
4549}
4550
4551cspice_proc! {
4552    /**
4553    Close a file designated by a Fortran-style integer logical unit.
4554    */
4555    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4556    pub fn ftncls(unit: i32) {}
4557}
4558
4559cspice_proc! {
4560    /**
4561    Deprecated: This routine has been superseded by the CSPICE routine ilumin_c. This routine is supported for purposes of backward compatibility only.
4562    */
4563    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4564    pub fn illum(target: &str, et: f64, abcorr: &str, obsrvr: &str, spoint: [f64; 3]) -> (f64, f64, f64) {}
4565}
4566
4567cspice_proc! {
4568    /**
4569    Return the inverse of a state transformation matrix.
4570    */
4571    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4572    pub fn invstm(mat: [[f64; 6]; 6]) -> [[f64; 6]; 6] {}
4573}
4574
4575cspice_proc! {
4576    /**
4577    Return a boolean value indicating whether a string contains only white space characters.
4578    */
4579    #[return_output]
4580    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4581    pub fn iswhsp(string: &str) -> bool {}
4582}
4583
4584cspice_proc! {
4585    /**
4586    Return the zero based index of the last non-blank character in a character string.
4587    */
4588    #[return_output]
4589    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4590    pub fn lastnb(string: &str) -> i32 {}
4591}
4592
4593cspice_proc! {
4594    /**
4595    Compute the transmission (or reception) time of a signal at a specified target, given the reception (or transmission) time at a specified observer. Also return the elapsed time between transmission and reception.
4596    */
4597    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4598    pub fn ltime(etobs: f64, obs: i32, dir: &str, targ: i32) -> (f64, f64) {}
4599}
4600
4601cspice_proc! {
4602    /**
4603    Scan a string from a specified starting position for the end of a decimal number.
4604    */
4605    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4606    pub fn lx4dec(string: &str, first: i32) -> (i32, i32) {}
4607}
4608
4609cspice_proc! {
4610    /**
4611    Scan a string from a specified starting position for the end of a number.
4612    */
4613    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4614    pub fn lx4num(string: &str, first: i32) -> (i32, i32) {}
4615}
4616
4617cspice_proc! {
4618    /**
4619    Scan a string from a specified starting position for the end of a signed integer.
4620    */
4621    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4622    pub fn lx4sgn(string: &str, first: i32) -> (i32, i32) {}
4623}
4624
4625cspice_proc! {
4626    /**
4627    Scan a string from a specified starting position for the end of an unsigned integer.
4628    */
4629    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4630    pub fn lx4uns(string: &str, first: i32) -> (i32, i32) {}
4631}
4632
4633cspice_proc! {
4634    /**
4635    Scan (lex) a quoted string.
4636    */
4637    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4638    pub fn lxqstr(string: &str, qchar: char, first: i32) -> (i32, i32) {}
4639}
4640
4641cspice_proc! {
4642    /**
4643    Find the first occurrence in a string of a character NOT belonging to a collection of characters, starting at a specified location, searching forward.
4644    */
4645    #[return_output]
4646    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4647    pub fn ncpos(string: &str, chars: &str, start: i32) -> i32 {}
4648}
4649
4650cspice_proc! {
4651    /**
4652    Find the first occurrence in a string of a character NOT belonging to a collection of characters, starting at a specified location, searching in reverse.
4653    */
4654    #[return_output]
4655    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4656    pub fn ncposr(string: &str, chars: &str, start: i32) -> i32 {}
4657}
4658
4659cspice_proc! {
4660    /**
4661    Expand a triangular plate by a specified amount. The expanded plate is co-planar with, and has the same orientation as, the original. The centroids of the two plates coincide.
4662    */
4663    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4664    pub fn pltexp(iverts: [[f64; 3]; 3], delta: f64) -> [[f64; 3]; 3] {}
4665}
4666
4667cspice_proc! {
4668    /**
4669    Parse a string as a double precision number, encapsulating error handling.
4670    */
4671    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4672    pub fn prsdp(string: &str) -> f64 {}
4673}
4674
4675cspice_proc! {
4676    /**
4677    Parse a string as an integer, encapsulating error handling.
4678    */
4679    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4680    pub fn prsint(string: &str) -> i32 {}
4681}
4682
4683cspice_proc! {
4684    /**
4685    Derive angular velocity from a unit quaternion and its derivative with respect to time.
4686    */
4687    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4688    pub fn qdq2av(q: [f64; 4], dq: [f64; 4]) -> [f64; 3] {}
4689}
4690
4691cspice_proc! {
4692    /**
4693    Transform a vector to a new coordinate system rotated by `angle' radians about axis `iaxis'. This transformation rotates `v1' by -angle radians about the specified axis.
4694    */
4695    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4696    pub fn rotvec(v1: [f64; 3], angle: f64, iaxis: i32) -> [f64; 3] {}
4697}
4698
4699cspice_proc! {
4700    /**
4701    Find the roots of a quadratic equation.
4702    */
4703    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4704    pub fn rquad(a: f64, b: f64, c: f64) -> ([f64; 2], [f64; 2]) {}
4705}
4706
4707cspice_proc! {
4708    /**
4709    Convert ephemeris seconds past J2000 (ET) to integral encoded spacecraft clock (`ticks'). For conversion to fractional ticks, (required for C-kernel production), see the routine sce2c_c.
4710    */
4711    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4712    pub fn sce2t(sc: i32, et: f64) -> f64 {}
4713}
4714
4715cspice_proc! {
4716    /**
4717    Convert a spacecraft clock format string to number of "ticks".
4718    */
4719    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4720    pub fn sctiks(sc: i32, clkstr: &str) -> f64 {}
4721}
4722
4723cspice_proc! {
4724    /**
4725    Set the value of the current long error message.
4726    */
4727    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4728    pub fn setmsg(msg: &str) {}
4729}
4730
4731cspice_proc! {
4732    /**
4733    Deprecated: This routine has been superseded by the CSPICE routine sincpt_c. This routine is supported for purposes of backward compatibility only.
4734    */
4735    #[allow(clippy::too_many_arguments)]
4736    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4737    #[allow(clippy::type_complexity)]
4738    pub fn srfxpt(method: &str, target: &str, et: f64, abcorr: &str, obsrvr: &str, dref: &str, dvec: [f64; 3]) -> ([f64; 3], f64, f64, [f64; 3], bool) {}
4739}
4740
4741cspice_proc! {
4742    /**
4743    Correct the apparent position of an object for stellar aberration.
4744    */
4745    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4746    pub fn stelab(pobj: [f64; 3], vobs: [f64; 3]) -> [f64; 3] {}
4747}
4748
4749cspice_proc! {
4750    /**
4751    Correct the position of a target for the stellar aberration effect on radiation transmitted from a specified observer to the target.
4752    */
4753    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4754    pub fn stlabx(pobj: [f64; 3], vobs: [f64; 3]) -> [f64; 3] {}
4755}
4756
4757cspice_proc! {
4758    /**
4759    Deprecated: This routine has been superseded by the CSPICE routine subpnt_c. This routine is supported for purposes of backward compatibility only.
4760    */
4761    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4762    pub fn subpt(method: &str, target: &str, et: f64, abcorr: &str, obsrvr: &str) -> ([f64; 3], f64) {}
4763}
4764
4765cspice_proc! {
4766    /**
4767    Deprecated: This routine has been superseded by the CSPICE routine subslr_c. This routine is supported for purposes of backward compatibility only.
4768    */
4769    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4770    pub fn subsol(method: &str, target: &str, et: f64, abcorr: &str, obsrvr: &str) -> [f64; 3] {}
4771}
4772
4773cspice_proc! {
4774    /**
4775    Compute, for a given observer, ray emanating from the observer, and target, the "tangent point": the point on the ray nearest to the target's surface. Also compute the point on the target's surface nearest to the tangent point.
4776    */
4777    #[allow(clippy::too_many_arguments)]
4778    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4779    #[allow(clippy::type_complexity)]
4780    pub fn tangpt(method: &str, target: &str, et: f64, fixref: &str, abcorr: &str, corloc: &str, obsrvr: &str, dref: &str, dvec: [f64; 3]) -> ([f64; 3], f64, f64, [f64; 3], f64, [f64; 3]) {}
4781}
4782
4783cspice_proc! {
4784    /**
4785    Return a 3x3 matrix that transforms positions in inertial coordinates to positions in body-equator-and-prime-meridian coordinates.
4786    */
4787    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4788    pub fn tipbod(frame: &str, body: i32, et: f64) -> [[f64; 3]; 3] {}
4789}
4790
4791cspice_proc! {
4792    /**
4793    Return a 6x6 matrix that transforms states in inertial coordinates to states in body-equator-and-prime-meridian coordinates.
4794    */
4795    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4796    pub fn tisbod(frame: &str, body: i32, et: f64) -> [[f64; 6]; 6] {}
4797}
4798
4799cspice_proc! {
4800    /**
4801    Find the position rotation matrix from a Text Kernel (TK) frame with the specified frame class ID to its base frame.
4802    */
4803    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4804    pub fn tkfram(frcode: i32) -> ([[f64; 3]; 3], i32, bool) {}
4805}
4806
4807cspice_proc! {
4808    /**
4809    Return the number of modules in the traceback representation.
4810    */
4811    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4812    pub fn trcdep() -> i32 {}
4813}
4814
4815cspice_proc! {
4816    /**
4817    Compute the angular separation in radians between two spherical or point objects.
4818    */
4819    #[allow(clippy::too_many_arguments)]
4820    #[return_output]
4821    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4822    pub fn trgsep(et: f64, targ1: &str, shape1: &str, frame1: &str, targ2: &str, shape2: &str, frame2: &str, obsrvr: &str, abcorr: &str) -> f64 {}
4823}
4824
4825cspice_proc! {
4826    /**
4827    Set the lower bound on the 100 year range
4828    */
4829    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4830    pub fn tsetyr(year: i32) {}
4831}
4832
4833cspice_proc! {
4834    /**
4835    Find the state transformation from a base frame to the right-handed frame defined by two state vectors: one state vector defining a specified axis and a second state vector defining a specified coordinate plane.
4836    */
4837    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4838    pub fn twovxf(axdef: [f64; 6], indexa: i32, plndef: [f64; 6], indexp: i32) -> [[f64; 6]; 6] {}
4839}
4840
4841cspice_proc! {
4842    /**
4843    Compute the normalized cross product of two 3-vectors.
4844    */
4845    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4846    pub fn ucrss(v1: [f64; 3], v2: [f64; 3]) -> [f64; 3] {}
4847}
4848
4849/* ---------------------------------------------------------------------------------------------- */
4850/* DAF, DAS and the kernel file layers                                                            */
4851/* ---------------------------------------------------------------------------------------------- */
4852
4853cspice_proc! {
4854    /**
4855    Find the position rotation matrix from a C-kernel (CK) frame with the specified frame class ID (CK ID) to the base frame of the highest priority CK segment containing orientation data for this CK frame at the time requested.
4856    */
4857    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4858    pub fn ckfrot(inst: i32, et: f64) -> ([[f64; 3]; 3], i32, bool) {}
4859}
4860
4861cspice_proc! {
4862    /**
4863    Find the state transformation matrix from a C-kernel (CK) frame with the specified frame class ID (CK ID) to the base frame of the highest priority CK segment containing orientation and angular velocity data for this CK frame at the time requested.
4864    */
4865    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4866    pub fn ckfxfm(inst: i32, et: f64) -> ([[f64; 6]; 6], i32, bool) {}
4867}
4868
4869cspice_proc! {
4870    /**
4871    Load a CK pointing file for use by the CK readers. Return that file's handle, to be used by other CK routines to refer to the file.
4872    */
4873    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4874    pub fn cklpf(fname: &str) -> i32 {}
4875}
4876
4877cspice_proc! {
4878    /**
4879    Return (depending upon the user's request) the ID code of either the spacecraft or spacecraft clock associated with a C-Kernel ID code.
4880    */
4881    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4882    pub fn ckmeta(ckid: i32, meta: &str) -> i32 {}
4883}
4884
4885cspice_proc! {
4886    /**
4887    Unload a CK pointing file so that it will no longer be searched by the readers.
4888    */
4889    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4890    pub fn ckupf(handle: i32) {}
4891}
4892
4893cspice_proc! {
4894    /**
4895    Begin a backward search for arrays in a DAF.
4896    */
4897    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4898    pub fn dafbbs(handle: i32) {}
4899}
4900
4901cspice_proc! {
4902    /**
4903    Begin a forward search for arrays in a DAF.
4904    */
4905    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4906    pub fn dafbfs(handle: i32) {}
4907}
4908
4909cspice_proc! {
4910    /**
4911    Close the DAF associated with a given handle.
4912    */
4913    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4914    pub fn dafcls(handle: i32) {}
4915}
4916
4917cspice_proc! {
4918    /**
4919    Select a DAF that already has a search in progress as the one to continue searching.
4920    */
4921    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4922    pub fn dafcs(handle: i32) {}
4923}
4924
4925cspice_proc! {
4926    /**
4927    Delete the entire comment area of a specified DAF file.
4928    */
4929    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4930    pub fn dafdc(handle: i32) {}
4931}
4932
4933cspice_proc! {
4934    /**
4935    Find the next (forward) array in the current DAF.
4936    */
4937    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4938    pub fn daffna() -> bool {}
4939}
4940
4941cspice_proc! {
4942    /**
4943    Find the previous (backward) array in the current DAF.
4944    */
4945    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4946    pub fn daffpa() -> bool {}
4947}
4948
4949cspice_proc! {
4950    /**
4951    Return (get) the handle of the DAF currently being searched.
4952    */
4953    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4954    pub fn dafgh() -> i32 {}
4955}
4956
4957/**
4958Read a contiguous run of double precision words from a DAF record.
4959
4960Returns the `end - begin + 1` words, and whether the record was found.
4961*/
4962#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4963pub fn dafgsr(handle: i32, recno: i32, begin: i32, end: i32) -> (Vec<f64>, bool) {
4964    let words = (end - begin + 1).max(0) as usize;
4965    let mut data = vec![0.0; words.max(1)];
4966    let mut found = 0;
4967    unsafe { crate::c::dafgsr_c(handle, recno, begin, end, data.as_mut_ptr(), &mut found) };
4968    data.truncate(words);
4969    (data, found != 0)
4970}
4971
4972cspice_proc! {
4973    /**
4974    Return the summary format associated with a handle.
4975    */
4976    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4977    pub fn dafhsf(handle: i32) -> (i32, i32) {}
4978}
4979
4980cspice_proc! {
4981    /**
4982    Open a DAF for subsequent read requests.
4983    */
4984    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4985    pub fn dafopr(fname: &str) -> i32 {}
4986}
4987
4988cspice_proc! {
4989    /**
4990    Open a DAF for subsequent write requests.
4991    */
4992    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
4993    pub fn dafopw(fname: &str) -> i32 {}
4994}
4995
4996cspice_proc! {
4997    /**
4998    Delete the entire comment area of a previously opened binary DAS file.
4999    */
5000    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5001    pub fn dasdc(handle: i32) {}
5002}
5003
5004cspice_proc! {
5005    /**
5006    Return a file summary for a specified DAS file.
5007    */
5008    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5009    #[allow(clippy::type_complexity)]
5010    pub fn dashfs(handle: i32) -> (i32, i32, i32, i32, i32, [i32; 3], [i32; 3], [i32; 3]) {}
5011}
5012
5013cspice_proc! {
5014    /**
5015    Return last DAS logical addresses of character, double precision and integer type that are currently in use in a specified DAS file.
5016    */
5017    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5018    pub fn daslla(handle: i32) -> (i32, i32, i32) {}
5019}
5020
5021cspice_proc! {
5022    /**
5023    Close the DAS file associated with a given handle, without flushing buffered data or segregating the file.
5024    */
5025    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5026    pub fn dasllc(handle: i32) {}
5027}
5028
5029cspice_proc! {
5030    /**
5031    Open a new DAS file and set the file type.
5032    */
5033    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5034    pub fn dasonw(fname: &str, ftype: &str, ifname: &str, ncomr: i32) -> i32 {}
5035}
5036
5037cspice_proc! {
5038    /**
5039    Open a scratch DAS file for writing.
5040    */
5041    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5042    pub fn dasops() -> i32 {}
5043}
5044
5045cspice_proc! {
5046    /**
5047    Open a DAS file for writing.
5048    */
5049    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5050    pub fn dasopw(fname: &str) -> i32 {}
5051}
5052
5053cspice_proc! {
5054    /**
5055    Write out all buffered records of a specified DAS file.
5056    */
5057    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5058    pub fn daswbr(handle: i32) {}
5059}
5060
5061cspice_proc! {
5062    /**
5063    Begin a new segment in a DLA file.
5064    */
5065    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5066    pub fn dlabns(handle: i32) {}
5067}
5068
5069cspice_proc! {
5070    /**
5071    End a new segment in a DLA file.
5072    */
5073    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5074    pub fn dlaens(handle: i32) {}
5075}
5076
5077cspice_proc! {
5078    /**
5079    Open a new DLA file and set the file type.
5080    */
5081    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5082    pub fn dlaopn(fname: &str, ftype: &str, ifname: &str, ncomch: i32) -> i32 {}
5083}
5084
5085cspice_proc! {
5086    /**
5087    Close an open PCK file.
5088    */
5089    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5090    pub fn pckcls(handle: i32) {}
5091}
5092
5093cspice_proc! {
5094    /**
5095    Load a binary PCK file for use by the readers. Return the handle of the loaded file which is used by other PCK routines to refer to the file.
5096    */
5097    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5098    pub fn pcklof(fname: &str) -> i32 {}
5099}
5100
5101cspice_proc! {
5102    /**
5103    Create a new PCK file, returning the handle of the opened file.
5104    */
5105    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5106    pub fn pckopn(name: &str, ifname: &str, ncomch: i32) -> i32 {}
5107}
5108
5109cspice_proc! {
5110    /**
5111    Unload a binary PCK file so that it will no longer be searched by the readers.
5112    */
5113    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5114    pub fn pckuof(handle: i32) {}
5115}
5116
5117/* -------------------------------------------------------------------------------------------- */
5118/* DAF and DAS, the array files underneath the kernels                                            */
5119/* -------------------------------------------------------------------------------------------- */
5120
5121/// Largest DAF summary, in double precision words.
5122pub const DAF_MAXSUM: usize = 125;
5123
5124/// Read a run of double precision words from a DAF, for the two routines that do it.
5125macro_rules! daf_read {
5126    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
5127        #[doc = $doc]
5128        ///
5129        /// Returns the `end - begin + 1` words, addressed from one.
5130        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5131        pub fn $name(handle: i32, begin: i32, end: i32) -> Vec<f64> {
5132            let words = (end - begin + 1).max(0) as usize;
5133            let mut data = vec![0.0; words.max(1)];
5134            unsafe { crate::c::$cname(handle, begin, end, data.as_mut_ptr()) };
5135            data.truncate(words);
5136            data
5137        }
5138    )*};
5139}
5140
5141daf_read! {
5142    dafgda => dafgda_c, "Read double precision data from the current array of a DAF.";
5143    dafrda => dafrda_c, "Read double precision data from a DAF; superseded by `dafgda`.";
5144}
5145
5146cspice_proc! {
5147    /**
5148    Return the name of the current array in the current DAF.
5149    */
5150    pub fn dafgn(#[lenout] lenout: i32) -> String {}
5151}
5152
5153/**
5154Return the summary of the current array in the current DAF.
5155
5156At most [`DAF_MAXSUM`] words are returned, which is the largest a DAF summary can be.
5157*/
5158#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5159pub fn dafgs() -> Vec<f64> {
5160    let mut summary = vec![0.0; DAF_MAXSUM];
5161    unsafe { crate::c::dafgs_c(summary.as_mut_ptr()) };
5162    summary
5163}
5164
5165/**
5166Pack the double precision and integer components of a DAF summary into one array.
5167*/
5168#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5169pub fn dafps(dc: &[f64], ic: &[i32]) -> Vec<f64> {
5170    let words = dc.len() + (ic.len() + 1) / 2 + 1;
5171    let mut summary = vec![0.0; words.max(1)];
5172    unsafe {
5173        crate::c::dafps_c(
5174            dc.len() as SpiceInt,
5175            ic.len() as SpiceInt,
5176            dc.as_ptr() as *mut SpiceDouble,
5177            ic.as_ptr() as *mut SpiceInt,
5178            summary.as_mut_ptr(),
5179        )
5180    };
5181    summary
5182}
5183
5184/**
5185Unpack a DAF summary into its `nd` double precision and `ni` integer components.
5186*/
5187#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5188pub fn dafus(summary: &[f64], nd: usize, ni: usize) -> (Vec<f64>, Vec<i32>) {
5189    let mut dc = vec![0.0; nd.max(1)];
5190    let mut ic = vec![0; ni.max(1)];
5191    unsafe {
5192        crate::c::dafus_c(
5193            summary.as_ptr() as *mut SpiceDouble,
5194            nd as SpiceInt,
5195            ni as SpiceInt,
5196            dc.as_mut_ptr(),
5197            ic.as_mut_ptr(),
5198        )
5199    };
5200    dc.truncate(nd);
5201    ic.truncate(ni);
5202    (dc, ic)
5203}
5204
5205/**
5206Replace the summary of the current array in the current DAF.
5207*/
5208#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5209pub fn dafrs(summary: &[f64]) {
5210    unsafe { crate::c::dafrs_c(summary.as_ptr() as *mut SpiceDouble) }
5211}
5212
5213/**
5214Read the file record of a DAF: the summary sizes, the internal file name, and the pointers to the
5215first and last summary records and the first free address.
5216*/
5217#[allow(clippy::type_complexity)]
5218#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5219pub fn dafrfr(handle: i32, lenout: usize) -> (i32, i32, String, i32, i32, i32) {
5220    let mut ifname = vec![0 as SpiceChar; lenout.max(1)];
5221    let (mut nd, mut ni, mut fward, mut bward, mut free) = (0, 0, 0, 0, 0);
5222    unsafe {
5223        crate::c::dafrfr_c(
5224            handle,
5225            lenout as SpiceInt,
5226            &mut nd,
5227            &mut ni,
5228            ifname.as_mut_ptr(),
5229            &mut fward,
5230            &mut bward,
5231            &mut free,
5232        )
5233    };
5234    (nd, ni, from_cbuf(&ifname), fward, bward, free)
5235}
5236
5237/**
5238Add comment lines to the comment area of a DAF.
5239*/
5240#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5241pub fn dafac<S: AsRef<str>>(handle: i32, buffer: &[S]) {
5242    let (packed, lenvals) = to_strided(buffer);
5243    unsafe {
5244        crate::c::dafac_c(
5245            handle,
5246            buffer.len() as SpiceInt,
5247            lenvals as SpiceInt,
5248            packed.as_ptr().cast(),
5249        )
5250    }
5251}
5252
5253/**
5254Read comment lines from the comment area of a DAF.
5255
5256Returns at most `bufsiz` lines, and whether the comment area has been read to the end.
5257
5258This function has a [neat version][crate::neat::dafec].
5259*/
5260pub fn dafec(handle: i32, bufsiz: usize, lenout: usize) -> (Vec<String>, bool) {
5261    let lenout = lenout.max(1);
5262    let mut buffer = vec![0 as SpiceChar; bufsiz.max(1) * lenout];
5263    let (mut n, mut done) = (0, 0);
5264    unsafe {
5265        crate::c::dafec_c(
5266            handle,
5267            bufsiz as SpiceInt,
5268            lenout as SpiceInt,
5269            &mut n,
5270            buffer.as_mut_ptr().cast(),
5271            &mut done,
5272        )
5273    };
5274    (from_strided(&buffer, lenout, n.max(0) as usize), done != 0)
5275}
5276
5277/// Read a run of words from a DAS, for the double precision and integer cases.
5278macro_rules! das_read {
5279    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
5280        #[doc = $doc]
5281        ///
5282        /// Returns the `last - first + 1` words, addressed from one.
5283        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5284        pub fn $name(handle: i32, first: i32, last: i32) -> Vec<$ty> {
5285            let words = (last - first + 1).max(0) as usize;
5286            let mut data = vec![<$ty>::default(); words.max(1)];
5287            unsafe { crate::c::$cname(handle, first, last, data.as_mut_ptr()) };
5288            data.truncate(words);
5289            data
5290        }
5291    )*};
5292}
5293
5294das_read! {
5295    dasrdd(f64) => dasrdd_c, "Read double precision data from a DAS.";
5296    dasrdi(i32) => dasrdi_c, "Read integer data from a DAS.";
5297}
5298
5299/// Update a run of words in a DAS, for the double precision and integer cases.
5300macro_rules! das_update {
5301    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
5302        #[doc = $doc]
5303        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5304        pub fn $name(handle: i32, first: i32, last: i32, data: &[$ty]) {
5305            unsafe { crate::c::$cname(handle, first, last, data.as_ptr() as *mut _) }
5306        }
5307    )*};
5308}
5309
5310das_update! {
5311    dasudd(f64) => dasudd_c, "Update double precision data in a DAS.";
5312    dasudi(i32) => dasudi_c, "Update integer data in a DAS.";
5313}
5314
5315/// Append data to a DAS, for the double precision and integer cases.
5316macro_rules! das_add {
5317    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
5318        #[doc = $doc]
5319        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5320        pub fn $name(handle: i32, data: &[$ty]) {
5321            unsafe {
5322                crate::c::$cname(handle, data.len() as SpiceInt, data.as_ptr() as *mut _)
5323            }
5324        }
5325    )*};
5326}
5327
5328das_add! {
5329    dasadd(f64) => dasadd_c, "Append double precision data to a DAS.";
5330    dasadi(i32) => dasadi_c, "Append integer data to a DAS.";
5331}
5332
5333/**
5334Append characters to a DAS, taking the substring `bpos ..= epos` of each line.
5335*/
5336#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5337pub fn dasadc<S: AsRef<str>>(handle: i32, bpos: i32, epos: i32, data: &[S]) {
5338    let (packed, datlen) = to_strided(data);
5339    // The count CSPICE wants is of characters, not of lines.
5340    let sublen = (epos - bpos + 1).max(0) as usize;
5341    unsafe {
5342        crate::c::dasadc_c(
5343            handle,
5344            (data.len() * sublen) as SpiceInt,
5345            bpos,
5346            epos,
5347            datlen as SpiceInt,
5348            packed.as_ptr().cast(),
5349        )
5350    }
5351}
5352
5353/**
5354Read characters from a DAS, into the substring `bpos ..= epos` of each line.
5355
5356Returns one line per substring the range covers, each `epos + 1` characters long, of which only
5357`bpos ..= epos` come from the file.
5358*/
5359#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5360pub fn dasrdc(handle: i32, first: i32, last: i32, bpos: i32, epos: i32) -> Vec<String> {
5361    let sublen = (epos - bpos + 1).max(1) as usize;
5362    let datlen = (epos + 1).max(1) as usize;
5363    let lines = ((last - first + 1).max(0) as usize + sublen - 1) / sublen;
5364    // The routine reads the file as a stream of characters and leaves the rest of each line alone,
5365    // so the lines start out blank rather than empty.
5366    let mut data = vec![b' ' as SpiceChar; lines.max(1) * datlen];
5367    unsafe {
5368        crate::c::dasrdc_c(
5369            handle,
5370            first,
5371            last,
5372            bpos,
5373            epos,
5374            datlen as SpiceInt,
5375            data.as_mut_ptr().cast(),
5376        )
5377    };
5378    (0..lines)
5379        .map(|line| {
5380            data[line * datlen..(line + 1) * datlen]
5381                .iter()
5382                .map(|&byte| byte as u8 as char)
5383                .collect()
5384        })
5385        .collect()
5386}
5387
5388/**
5389Update characters in a DAS, taking the substring `bpos ..= epos` of each line.
5390*/
5391#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5392pub fn dasudc<S: AsRef<str>>(handle: i32, first: i32, last: i32, bpos: i32, epos: i32, data: &[S]) {
5393    // Only `bpos ..= epos` of each line is read, so every line has to reach at least that far.
5394    let datlen = (epos + 1).max(1) as usize;
5395    let mut packed = vec![b' ' as SpiceChar; data.len().max(1) * datlen];
5396    for (line, value) in data.iter().enumerate() {
5397        let slot = &mut packed[line * datlen..(line + 1) * datlen];
5398        for (target, byte) in slot.iter_mut().zip(value.as_ref().as_bytes()) {
5399            *target = *byte as SpiceChar;
5400        }
5401    }
5402    unsafe {
5403        crate::c::dasudc_c(
5404            handle,
5405            first,
5406            last,
5407            bpos,
5408            epos,
5409            datlen as SpiceInt,
5410            packed.as_ptr().cast(),
5411        )
5412    }
5413}
5414
5415/**
5416Add comment lines to the comment area of a DAS.
5417*/
5418#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5419pub fn dasac<S: AsRef<str>>(handle: i32, buffer: &[S]) {
5420    let (packed, buflen) = to_strided(buffer);
5421    unsafe {
5422        crate::c::dasac_c(
5423            handle,
5424            buffer.len() as SpiceInt,
5425            buflen as SpiceInt,
5426            packed.as_ptr().cast(),
5427        )
5428    }
5429}
5430
5431/**
5432Read comment lines from the comment area of a DAS.
5433
5434This function has a [neat version][crate::neat::dasec].
5435*/
5436pub fn dasec(handle: i32, bufsiz: usize, buflen: usize) -> (Vec<String>, bool) {
5437    let buflen = buflen.max(1);
5438    let mut buffer = vec![0 as SpiceChar; bufsiz.max(1) * buflen];
5439    let (mut n, mut done) = (0, 0);
5440    unsafe {
5441        crate::c::dasec_c(
5442            handle,
5443            bufsiz as SpiceInt,
5444            buflen as SpiceInt,
5445            &mut n,
5446            buffer.as_mut_ptr().cast(),
5447            &mut done,
5448        )
5449    };
5450    (from_strided(&buffer, buflen, n.max(0) as usize), done != 0)
5451}
5452
5453cspice_proc! {
5454    /**
5455    Return the name of the file a DAS handle refers to.
5456    */
5457    pub fn dashfn(handle: i32, #[lenout] namlen: i32) -> String {}
5458}
5459
5460/**
5461Read the file record of a DAS: the ID word, the internal file name, and the reserved and comment
5462area sizes.
5463*/
5464#[allow(clippy::type_complexity)]
5465#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5466pub fn dasrfr(handle: i32, idwlen: usize, ifnlen: usize) -> (String, String, i32, i32, i32, i32) {
5467    let mut idword = vec![0 as SpiceChar; idwlen.max(1)];
5468    let mut ifname = vec![0 as SpiceChar; ifnlen.max(1)];
5469    let (mut nresvr, mut nresvc, mut ncomr, mut ncomc) = (0, 0, 0, 0);
5470    unsafe {
5471        crate::c::dasrfr_c(
5472            handle,
5473            idwlen as SpiceInt,
5474            ifnlen as SpiceInt,
5475            idword.as_mut_ptr(),
5476            ifname.as_mut_ptr(),
5477            &mut nresvr,
5478            &mut nresvc,
5479            &mut ncomr,
5480            &mut ncomc,
5481        )
5482    };
5483    (
5484        from_cbuf(&idword),
5485        from_cbuf(&ifname),
5486        nresvr,
5487        nresvc,
5488        ncomr,
5489        ncomc,
5490    )
5491}
5492
5493cspice_proc! {
5494    /**
5495    Find the segment preceding a specified segment in a DLA file.
5496    */
5497    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5498    pub fn dlafps(handle: i32, descr: DLADSC) -> (DLADSC, bool) {}
5499}
5500
5501/* ---------------------------------------------------------------------------------------------- */
5502/* Kernel readers and writers                                                                     */
5503/* ---------------------------------------------------------------------------------------------- */
5504
5505cspice_proc! {
5506    /**
5507    Begin a type 14 SPK segment in the SPK file associated with `handle'.
5508    */
5509    #[allow(clippy::too_many_arguments)]
5510    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5511    pub fn spk14b(handle: i32, segid: &str, body: i32, center: i32, frame: &str, first: f64, last: f64, chbdeg: i32) {}
5512}
5513
5514cspice_proc! {
5515    /**
5516    End the type 14 SPK segment currently being written to the SPK file associated with `handle'.
5517    */
5518    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5519    pub fn spk14e(handle: i32) {}
5520}
5521
5522cspice_proc! {
5523    /**
5524    Return the state (position and velocity) of a target body relative to an observer, optionally corrected for light time and stellar aberration, expressed relative to an inertial reference frame.
5525    */
5526    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5527    pub fn spkacs(targ: i32, et: f64, frame: &str, abcorr: &str, obs: i32) -> ([f64; 6], f64, f64) {}
5528}
5529
5530cspice_proc! {
5531    /**
5532    Return the position of a target body relative to an observer, optionally corrected for light time and stellar aberration.
5533    */
5534    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5535    pub fn spkapo(targ: i32, et: f64, frame: &str, sobs: [f64; 6], abcorr: &str) -> ([f64; 3], f64) {}
5536}
5537
5538cspice_proc! {
5539    /**
5540    Deprecated: This routine has been superseded by the CSPICE routine spkaps_c. This routine is supported for purposes of backward compatibility only.
5541    */
5542    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5543    pub fn spkapp(targ: i32, et: f64, frame: &str, sobs: [f64; 6], abcorr: &str) -> ([f64; 6], f64) {}
5544}
5545
5546cspice_proc! {
5547    /**
5548    Return the state (position and velocity) of a target body relative to an observer specified by its state and acceleration relative to the solar system barycenter. The returned state may be optionally corrected for light time and stellar aberration. All input and output vectors are expressed relative to an inertial reference frame.
5549    */
5550    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5551    pub fn spkaps(targ: i32, et: f64, frame: &str, abcorr: &str, stobs: [f64; 6], accobs: [f64; 3]) -> ([f64; 6], f64, f64) {}
5552}
5553
5554cspice_proc! {
5555    /**
5556    Compute the geometric position of a target body relative to an observing body.
5557    */
5558    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5559    pub fn spkgps(targ: i32, et: f64, frame: &str, obs: i32) -> ([f64; 3], f64) {}
5560}
5561
5562cspice_proc! {
5563    /**
5564    Return the state (position and velocity) of a target body relative to an observer, optionally corrected for light time, expressed relative to an inertial reference frame.
5565    */
5566    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5567    pub fn spkltc(targ: i32, et: f64, frame: &str, abcorr: &str, stobs: [f64; 6]) -> ([f64; 6], f64, f64) {}
5568}
5569
5570cspice_proc! {
5571    /**
5572    Perform routine error checks and if all check pass, pack the descriptor for an SPK segment
5573    */
5574    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5575    pub fn spkpds(body: i32, center: i32, frame: &str, kind: i32, first: f64, last: f64) -> [f64; 5] {}
5576}
5577
5578cspice_proc! {
5579    /**
5580    Return, for a specified SPK segment and time, the state (position and velocity) of the segment's target body relative to its center of motion.
5581    */
5582    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5583    pub fn spkpvn(handle: i32, descr: [f64; 5], et: f64) -> (i32, [f64; 6], i32) {}
5584}
5585
5586cspice_proc! {
5587    /**
5588    Return the state (position and velocity) of a target body relative to the solar system barycenter.
5589    */
5590    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5591    pub fn spkssb(targ: i32, et: f64, frame: &str) -> [f64; 6] {}
5592}
5593
5594cspice_proc! {
5595    /**
5596    Unload an ephemeris file so that it will no longer be searched by the readers.
5597    */
5598    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5599    pub fn spkuef(handle: i32) {}
5600}
5601
5602cspice_proc! {
5603    /**
5604    Write an SPK segment of type 15 given a type 15 data record.
5605    */
5606    #[allow(clippy::too_many_arguments)]
5607    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5608    pub fn spkw15(handle: i32, body: i32, center: i32, frame: &str, first: f64, last: f64, segid: &str, epoch: f64, tp: [f64; 3], pa: [f64; 3], p: f64, ecc: f64, j2flg: f64, pv: [f64; 3], gm: f64, j2: f64, radius: f64) {}
5609}
5610
5611cspice_proc! {
5612    /**
5613    Write an SPK segment of type 17 given a type 17 data record.
5614    */
5615    #[allow(clippy::too_many_arguments)]
5616    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5617    pub fn spkw17(handle: i32, body: i32, center: i32, frame: &str, first: f64, last: f64, segid: &str, epoch: f64, eqel: [f64; 9], rapol: f64, decpol: f64) {}
5618}
5619
5620/* -------------------------------------------------------------------------------------------- */
5621/* Kernel writers and low level readers                                                           */
5622/* -------------------------------------------------------------------------------------------- */
5623
5624/// Largest SPK or PCK segment descriptor, in double precision words.
5625pub const SPK_DSCSIZ: usize = 5;
5626
5627/// Write a segment whose data is one flat run of Chebyshev coefficients.
5628macro_rules! spk_chebyshev {
5629    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
5630        #[doc = $doc]
5631        #[allow(clippy::too_many_arguments)]
5632        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5633        pub fn $name(
5634            handle: i32,
5635            body: i32,
5636            center: i32,
5637            frame: &str,
5638            first: f64,
5639            last: f64,
5640            segid: &str,
5641            intlen: f64,
5642            n: i32,
5643            polydg: i32,
5644            cdata: &[f64],
5645            btime: f64,
5646        ) {
5647            let frame = to_cstring(frame);
5648            let segid = to_cstring(segid);
5649            unsafe {
5650                crate::c::$cname(
5651                    handle, body, center,
5652                    frame.as_ptr() as *mut SpiceChar,
5653                    first, last,
5654                    segid.as_ptr() as *mut SpiceChar,
5655                    intlen, n, polydg,
5656                    cdata.as_ptr() as *mut SpiceDouble,
5657                    btime,
5658                );
5659            }
5660        }
5661    )*};
5662}
5663
5664spk_chebyshev! {
5665    spkw02 => spkw02_c, "Write a type 2 segment: Chebyshev polynomials for position.";
5666    spkw03 => spkw03_c, "Write a type 3 segment: Chebyshev polynomials for position and velocity.";
5667}
5668
5669/// Write a segment whose data is a run of states at given epochs.
5670macro_rules! spk_states_at_epochs {
5671    ($($name:ident($mid:ident: $midty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
5672        #[doc = $doc]
5673        ///
5674        /// # Panics
5675        ///
5676        /// Panics if `n` is larger than `states` or `epochs`.
5677        #[allow(clippy::too_many_arguments)]
5678        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5679        pub fn $name(
5680            handle: i32,
5681            body: i32,
5682            center: i32,
5683            frame: &str,
5684            first: f64,
5685            last: f64,
5686            segid: &str,
5687            $mid: $midty,
5688            n: i32,
5689            states: &[[f64; 6]],
5690            epochs: &[f64],
5691        ) {
5692            let count = usize::try_from(n).expect("the record count cannot be negative");
5693            assert!(
5694                count <= states.len() && count <= epochs.len(),
5695                "asked for {count} records but got {} states and {} epochs",
5696                states.len(),
5697                epochs.len()
5698            );
5699            let frame = to_cstring(frame);
5700            let segid = to_cstring(segid);
5701            unsafe {
5702                crate::c::$cname(
5703                    handle, body, center,
5704                    frame.as_ptr() as *mut SpiceChar,
5705                    first, last,
5706                    segid.as_ptr() as *mut SpiceChar,
5707                    $mid, n,
5708                    states.as_ptr() as *mut [SpiceDouble; 6],
5709                    epochs.as_ptr() as *mut SpiceDouble,
5710                );
5711            }
5712        }
5713    )*};
5714}
5715
5716spk_states_at_epochs! {
5717    spkw05(gm: f64) => spkw05_c,
5718        "Write a type 5 segment: discrete states propagated with two body dynamics.";
5719    spkw13(degree: i32) => spkw13_c,
5720        "Write a type 13 segment: Hermite interpolation of unequally spaced states.";
5721}
5722
5723/// Write a segment whose states are evenly spaced in time.
5724macro_rules! spk_states_evenly_spaced {
5725    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
5726        #[doc = $doc]
5727        ///
5728        /// # Panics
5729        ///
5730        /// Panics if `n` is larger than `states`.
5731        #[allow(clippy::too_many_arguments)]
5732        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5733        pub fn $name(
5734            handle: i32,
5735            body: i32,
5736            center: i32,
5737            frame: &str,
5738            first: f64,
5739            last: f64,
5740            segid: &str,
5741            degree: i32,
5742            n: i32,
5743            states: &[[f64; 6]],
5744            epoch0: f64,
5745            step: f64,
5746        ) {
5747            let count = usize::try_from(n).expect("the record count cannot be negative");
5748            assert!(count <= states.len(), "asked for {count} states but got {}", states.len());
5749            let frame = to_cstring(frame);
5750            let segid = to_cstring(segid);
5751            unsafe {
5752                crate::c::$cname(
5753                    handle, body, center,
5754                    frame.as_ptr() as *mut SpiceChar,
5755                    first, last,
5756                    segid.as_ptr() as *mut SpiceChar,
5757                    degree, n,
5758                    states.as_ptr() as *mut [SpiceDouble; 6],
5759                    epoch0, step,
5760                );
5761            }
5762        }
5763    )*};
5764}
5765
5766spk_states_evenly_spaced! {
5767    spkw08 => spkw08_c, "Write a type 8 segment: Lagrange interpolation of evenly spaced states.";
5768    spkw12 => spkw12_c, "Write a type 12 segment: Hermite interpolation of evenly spaced states.";
5769}
5770
5771/**
5772Write a type 10 segment: two-line element sets.
5773*/
5774#[allow(clippy::too_many_arguments)]
5775#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5776pub fn spkw10(
5777    handle: i32,
5778    body: i32,
5779    center: i32,
5780    frame: &str,
5781    first: f64,
5782    last: f64,
5783    segid: &str,
5784    consts: &[f64],
5785    n: i32,
5786    elems: &[f64],
5787    epochs: &[f64],
5788) {
5789    let frame = to_cstring(frame);
5790    let segid = to_cstring(segid);
5791    unsafe {
5792        crate::c::spkw10_c(
5793            handle,
5794            body,
5795            center,
5796            frame.as_ptr() as *mut SpiceChar,
5797            first,
5798            last,
5799            segid.as_ptr() as *mut SpiceChar,
5800            consts.as_ptr() as *mut SpiceDouble,
5801            n,
5802            elems.as_ptr() as *mut SpiceDouble,
5803            epochs.as_ptr() as *mut SpiceDouble,
5804        );
5805    }
5806}
5807
5808/**
5809Write a type 18 segment: Hermite or Lagrange interpolation of packets of state data.
5810
5811`packts` holds one packet per epoch, laid out row by row.
5812*/
5813#[allow(clippy::too_many_arguments)]
5814#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5815pub fn spkw18(
5816    handle: i32,
5817    subtyp: i32,
5818    body: i32,
5819    center: i32,
5820    frame: &str,
5821    first: f64,
5822    last: f64,
5823    segid: &str,
5824    degree: i32,
5825    n: i32,
5826    packts: &[f64],
5827    epochs: &[f64],
5828) {
5829    let frame = to_cstring(frame);
5830    let segid = to_cstring(segid);
5831    unsafe {
5832        crate::c::spkw18_c(
5833            handle,
5834            subtyp as crate::c::SpiceSPK18Subtype,
5835            body,
5836            center,
5837            frame.as_ptr() as *mut SpiceChar,
5838            first,
5839            last,
5840            segid.as_ptr() as *mut SpiceChar,
5841            degree,
5842            n,
5843            packts.as_ptr().cast(),
5844            epochs.as_ptr() as *mut SpiceDouble,
5845        );
5846    }
5847}
5848
5849/**
5850Write a type 20 segment: Chebyshev polynomials for velocity, with the position at the interval
5851start.
5852*/
5853#[allow(clippy::too_many_arguments)]
5854#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5855pub fn spkw20(
5856    handle: i32,
5857    body: i32,
5858    center: i32,
5859    frame: &str,
5860    first: f64,
5861    last: f64,
5862    segid: &str,
5863    intlen: f64,
5864    n: i32,
5865    polydg: i32,
5866    cdata: &[f64],
5867    dscale: f64,
5868    tscale: f64,
5869    initjd: f64,
5870    initfr: f64,
5871) {
5872    let frame = to_cstring(frame);
5873    let segid = to_cstring(segid);
5874    unsafe {
5875        crate::c::spkw20_c(
5876            handle,
5877            body,
5878            center,
5879            frame.as_ptr() as *mut SpiceChar,
5880            first,
5881            last,
5882            segid.as_ptr() as *mut SpiceChar,
5883            intlen,
5884            n,
5885            polydg,
5886            cdata.as_ptr() as *mut SpiceDouble,
5887            dscale,
5888            tscale,
5889            initjd,
5890            initfr,
5891        );
5892    }
5893}
5894
5895/**
5896Add Chebyshev coefficient sets to a type 14 segment opened with [`spk14b`].
5897*/
5898#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5899pub fn spk14a(handle: i32, ncsets: i32, coeffs: &[f64], epochs: &[f64]) {
5900    unsafe {
5901        crate::c::spk14a_c(
5902            handle,
5903            ncsets,
5904            coeffs.as_ptr() as *mut SpiceDouble,
5905            epochs.as_ptr() as *mut SpiceDouble,
5906        )
5907    }
5908}
5909
5910/**
5911Search for the segment of an SPK that covers a body at an epoch.
5912
5913This function has a [neat version][crate::neat::spksfs].
5914*/
5915pub fn spksfs(body: i32, et: f64, idlen: usize) -> (i32, [f64; SPK_DSCSIZ], String, bool) {
5916    let mut descr = [0.0; SPK_DSCSIZ];
5917    let mut ident = vec![0 as SpiceChar; idlen.max(1)];
5918    let (mut handle, mut found) = (0, 0);
5919    unsafe {
5920        crate::c::spksfs_c(
5921            body,
5922            et,
5923            idlen as SpiceInt,
5924            &mut handle,
5925            descr.as_mut_ptr(),
5926            ident.as_mut_ptr(),
5927            &mut found,
5928        )
5929    };
5930    (handle, descr, from_cbuf(&ident), found != 0)
5931}
5932
5933cspice_proc! {
5934    /**
5935    Load an SPK for use by the low level readers, outside the KEEPER subsystem.
5936    */
5937    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5938    pub fn spklef(filename: &str) -> i32 {}
5939}
5940
5941/**
5942Unpack an SPK segment descriptor.
5943*/
5944#[allow(clippy::type_complexity)]
5945#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5946pub fn spkuds(descr: &[f64]) -> (i32, i32, i32, i32, f64, f64, i32, i32) {
5947    let (mut body, mut center, mut frame, mut kind) = (0, 0, 0, 0);
5948    let (mut first, mut last) = (0.0, 0.0);
5949    let (mut begin, mut end) = (0, 0);
5950    unsafe {
5951        crate::c::spkuds_c(
5952            descr.as_ptr() as *mut SpiceDouble,
5953            &mut body,
5954            &mut center,
5955            &mut frame,
5956            &mut kind,
5957            &mut first,
5958            &mut last,
5959            &mut begin,
5960            &mut end,
5961        )
5962    };
5963    (body, center, frame, kind, first, last, begin, end)
5964}
5965
5966/**
5967Copy a subset of the data in an SPK segment into another file.
5968*/
5969#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5970pub fn spksub(handle: i32, descr: &mut [f64], ident: &str, begin: f64, end: f64, newh: i32) {
5971    let ident = to_cstring(ident);
5972    unsafe {
5973        crate::c::spksub_c(
5974            handle,
5975            descr.as_mut_ptr(),
5976            ident.as_ptr() as *mut SpiceChar,
5977            begin,
5978            end,
5979            newh,
5980        )
5981    }
5982}
5983
5984/**
5985Write a type 1 segment to a CK file: discrete pointing with angular velocity.
5986*/
5987#[allow(clippy::too_many_arguments)]
5988#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
5989pub fn ckw01(
5990    handle: i32,
5991    begtime: f64,
5992    endtime: f64,
5993    inst: i32,
5994    frame: &str,
5995    avflag: bool,
5996    segid: &str,
5997    nrec: i32,
5998    sclkdp: &[f64],
5999    quats: &[[f64; 4]],
6000    avvs: &[[f64; 3]],
6001) {
6002    let frame = to_cstring(frame);
6003    let segid = to_cstring(segid);
6004    unsafe {
6005        crate::c::ckw01_c(
6006            handle,
6007            begtime,
6008            endtime,
6009            inst,
6010            frame.as_ptr() as *mut SpiceChar,
6011            avflag as crate::c::SpiceBoolean,
6012            segid.as_ptr() as *mut SpiceChar,
6013            nrec,
6014            sclkdp.as_ptr() as *mut SpiceDouble,
6015            quats.as_ptr() as *mut [SpiceDouble; 4],
6016            avvs.as_ptr() as *mut [SpiceDouble; 3],
6017        );
6018    }
6019}
6020
6021/**
6022Write a type 2 segment to a CK file: constant angular velocity over each interval.
6023*/
6024#[allow(clippy::too_many_arguments)]
6025#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6026pub fn ckw02(
6027    handle: i32,
6028    begtim: f64,
6029    endtim: f64,
6030    inst: i32,
6031    frame: &str,
6032    segid: &str,
6033    nrec: i32,
6034    start: &[f64],
6035    stop: &[f64],
6036    quats: &[[f64; 4]],
6037    avvs: &[[f64; 3]],
6038    rates: &[f64],
6039) {
6040    let frame = to_cstring(frame);
6041    let segid = to_cstring(segid);
6042    unsafe {
6043        crate::c::ckw02_c(
6044            handle,
6045            begtim,
6046            endtim,
6047            inst,
6048            frame.as_ptr() as *mut SpiceChar,
6049            segid.as_ptr() as *mut SpiceChar,
6050            nrec,
6051            start.as_ptr() as *mut SpiceDouble,
6052            stop.as_ptr() as *mut SpiceDouble,
6053            quats.as_ptr() as *mut [SpiceDouble; 4],
6054            avvs.as_ptr() as *mut [SpiceDouble; 3],
6055            rates.as_ptr() as *mut SpiceDouble,
6056        );
6057    }
6058}
6059
6060/**
6061Write a type 5 segment to a CK file: interpolated quaternion packets.
6062*/
6063#[allow(clippy::too_many_arguments)]
6064#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6065pub fn ckw05(
6066    handle: i32,
6067    subtyp: i32,
6068    degree: i32,
6069    begtim: f64,
6070    endtim: f64,
6071    inst: i32,
6072    frame: &str,
6073    avflag: bool,
6074    segid: &str,
6075    n: i32,
6076    sclkdp: &[f64],
6077    packets: &[f64],
6078    rate: f64,
6079    nints: i32,
6080    starts: &[f64],
6081) {
6082    let frame = to_cstring(frame);
6083    let segid = to_cstring(segid);
6084    unsafe {
6085        crate::c::ckw05_c(
6086            handle,
6087            subtyp as crate::c::SpiceCK05Subtype,
6088            degree,
6089            begtim,
6090            endtim,
6091            inst,
6092            frame.as_ptr() as *mut SpiceChar,
6093            avflag as crate::c::SpiceBoolean,
6094            segid.as_ptr() as *mut SpiceChar,
6095            n,
6096            sclkdp.as_ptr() as *mut SpiceDouble,
6097            packets.as_ptr().cast(),
6098            rate,
6099            nints,
6100            starts.as_ptr() as *mut SpiceDouble,
6101        );
6102    }
6103}
6104
6105/// Read a pointing record from a CK segment, for the two segment types that have them.
6106macro_rules! ck_record {
6107    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
6108        #[doc = $doc]
6109        ///
6110        /// `room` is how many double precision words to make space for.
6111        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6112        pub fn $name(handle: i32, descr: &[f64], recno: i32, room: usize) -> Vec<f64> {
6113            let mut record = vec![0.0; room.max(1)];
6114            unsafe {
6115                crate::c::$cname(
6116                    handle,
6117                    descr.as_ptr() as *mut SpiceDouble,
6118                    recno,
6119                    record.as_mut_ptr(),
6120                )
6121            };
6122            record
6123        }
6124    )*};
6125}
6126
6127ck_record! {
6128    ckgr02 => ckgr02_c, "Read a pointing record from a type 2 CK segment.";
6129    ckgr03 => ckgr03_c, "Read a pointing record from a type 3 CK segment.";
6130}
6131
6132/// Count the pointing records of a CK segment, for the two segment types that have them.
6133macro_rules! ck_record_count {
6134    ($($name:ident => $cname:ident, $doc:expr);* $(;)?) => {$(
6135        #[doc = $doc]
6136        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6137        pub fn $name(handle: i32, descr: &[f64]) -> i32 {
6138            let mut nrec = 0;
6139            unsafe {
6140                crate::c::$cname(handle, descr.as_ptr() as *mut SpiceDouble, &mut nrec)
6141            };
6142            nrec
6143        }
6144    )*};
6145}
6146
6147ck_record_count! {
6148    cknr02 => cknr02_c, "Number of pointing records in a type 2 CK segment.";
6149    cknr03 => cknr03_c, "Number of pointing records in a type 3 CK segment.";
6150}
6151
6152/**
6153Write a type 2 segment to a binary PCK file: Chebyshev polynomials for the Euler angles.
6154*/
6155#[allow(clippy::too_many_arguments)]
6156#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6157pub fn pckw02(
6158    handle: i32,
6159    clssid: i32,
6160    frame: &str,
6161    first: f64,
6162    last: f64,
6163    segid: &str,
6164    intlen: f64,
6165    n: i32,
6166    polydg: i32,
6167    cdata: &[f64],
6168    btime: f64,
6169) {
6170    let frame = to_cstring(frame);
6171    let segid = to_cstring(segid);
6172    unsafe {
6173        crate::c::pckw02_c(
6174            handle,
6175            clssid,
6176            frame.as_ptr() as *mut SpiceChar,
6177            first,
6178            last,
6179            segid.as_ptr() as *mut SpiceChar,
6180            intlen,
6181            n,
6182            polydg,
6183            cdata.as_ptr() as *mut SpiceDouble,
6184            btime,
6185        );
6186    }
6187}
6188
6189/**
6190Return the bookkeeping parameters of a type 2 DSK segment.
6191*/
6192#[allow(clippy::type_complexity)]
6193#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6194pub fn dskb02(
6195    handle: i32,
6196    dladsc: DLADSC,
6197) -> (
6198    i32,
6199    i32,
6200    i32,
6201    [[f64; 2]; 3],
6202    f64,
6203    [f64; 3],
6204    [i32; 3],
6205    i32,
6206    i32,
6207    i32,
6208    i32,
6209) {
6210    let mut dladsc = dladsc;
6211    let (mut nv, mut np, mut nvxtot) = (0, 0, 0);
6212    let mut vtxbds = [[0.0; 2]; 3];
6213    let mut voxsiz = 0.0;
6214    let mut voxori = [0.0; 3];
6215    let mut vgrext = [0; 3];
6216    let (mut cgscal, mut vtxnpl, mut voxnpt, mut voxnpl) = (0, 0, 0, 0);
6217    unsafe {
6218        crate::c::dskb02_c(
6219            handle,
6220            &mut dladsc,
6221            &mut nv,
6222            &mut np,
6223            &mut nvxtot,
6224            vtxbds.as_mut_ptr(),
6225            &mut voxsiz,
6226            voxori.as_mut_ptr(),
6227            vgrext.as_mut_ptr(),
6228            &mut cgscal,
6229            &mut vtxnpl,
6230            &mut voxnpt,
6231            &mut voxnpl,
6232        )
6233    };
6234    (
6235        nv, np, nvxtot, vtxbds, voxsiz, voxori, vgrext, cgscal, vtxnpl, voxnpt, voxnpl,
6236    )
6237}
6238
6239/// Fetch a run of items from a type 2 DSK segment, for the double precision and integer cases.
6240macro_rules! dsk_fetch {
6241    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
6242        #[doc = $doc]
6243        ///
6244        /// `item` is one of the [`dsk02`] keywords and at most `room` values are returned.
6245        ///
6246        /// `start` counts from **zero**, unlike most of the toolkit: the vertex indices of the
6247        /// first plate are at `start` 0, even though plate IDs themselves start at 1.
6248        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6249        pub fn $name(
6250            handle: i32,
6251            dladsc: DLADSC,
6252            item: i32,
6253            start: i32,
6254            room: usize,
6255        ) -> Vec<$ty> {
6256            let mut dladsc = dladsc;
6257            let mut values = vec![<$ty>::default(); room.max(1)];
6258            let mut n = 0;
6259            unsafe {
6260                crate::c::$cname(
6261                    handle,
6262                    &mut dladsc,
6263                    item,
6264                    start,
6265                    room as SpiceInt,
6266                    &mut n,
6267                    values.as_mut_ptr(),
6268                )
6269            };
6270            values.truncate(n.max(0) as usize);
6271            values
6272        }
6273    )*};
6274}
6275
6276dsk_fetch! {
6277    dskd02(f64) => dskd02_c, "Fetch double precision data from a type 2 DSK segment.";
6278    dski02(i32) => dski02_c, "Fetch integer data from a type 2 DSK segment.";
6279}
6280
6281/**
6282Determine the vertical extent of a plate set in a given coordinate system.
6283*/
6284#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6285pub fn dskrb2(vrtces: &[[f64; 3]], plates: &[[i32; 3]], corsys: i32, corpar: &[f64]) -> (f64, f64) {
6286    assert!(
6287        corpar.len() >= DSK_NSYPAR,
6288        "dskrb2 needs {DSK_NSYPAR} coordinate parameters but got {}",
6289        corpar.len()
6290    );
6291    let (mut mncor3, mut mxcor3) = (0.0, 0.0);
6292    unsafe {
6293        crate::c::dskrb2_c(
6294            vrtces.len() as SpiceInt,
6295            vrtces.as_ptr() as *mut [f64; 3],
6296            plates.len() as SpiceInt,
6297            plates.as_ptr() as *mut [SpiceInt; 3],
6298            corsys,
6299            corpar.as_ptr() as *mut SpiceDouble,
6300            &mut mncor3,
6301            &mut mxcor3,
6302        )
6303    };
6304    (mncor3, mxcor3)
6305}
6306
6307cspice_proc! {
6308    /**
6309    Convert encoded spacecraft clock ticks to a clock string.
6310    */
6311    pub fn scfmt(sc: i32, ticks: f64, #[lenout] clkstrlen: i32) -> String {}
6312}
6313
6314/**
6315Return the partition start and stop times of a spacecraft clock.
6316*/
6317#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6318pub fn scpart(sc: i32, maxparts: usize) -> (Vec<f64>, Vec<f64>) {
6319    let mut pstart = vec![0.0; maxparts.max(1)];
6320    let mut pstop = vec![0.0; maxparts.max(1)];
6321    let mut nparts = 0;
6322    unsafe { crate::c::scpart_c(sc, &mut nparts, pstart.as_mut_ptr(), pstop.as_mut_ptr()) };
6323    let count = nparts.max(0) as usize;
6324    pstart.truncate(count);
6325    pstop.truncate(count);
6326    (pstart, pstop)
6327}
6328
6329/* -------------------------------------------------------------------------------------------- */
6330/* Interpolation and polynomials                                                                  */
6331/* -------------------------------------------------------------------------------------------- */
6332
6333/**
6334Evaluate a Chebyshev expansion at `x`, returning the value and its derivative.
6335
6336`x2s` holds the midpoint and radius of the interval the expansion is defined on.
6337*/
6338#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6339pub fn chbint(cp: &[f64], degp: i32, x2s: [f64; 2], x: f64) -> (f64, f64) {
6340    let (mut p, mut dpdx) = (0.0, 0.0);
6341    unsafe {
6342        crate::c::chbint_c(
6343            cp.as_ptr() as *mut SpiceDouble,
6344            degp,
6345            x2s.as_ptr() as *mut SpiceDouble,
6346            x,
6347            &mut p,
6348            &mut dpdx,
6349        )
6350    };
6351    (p, dpdx)
6352}
6353
6354/**
6355Evaluate a Chebyshev expansion at `x`.
6356*/
6357#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6358pub fn chbval(cp: &[f64], degp: i32, x2s: [f64; 2], x: f64) -> f64 {
6359    let mut p = 0.0;
6360    unsafe {
6361        crate::c::chbval_c(
6362            cp.as_ptr() as *mut SpiceDouble,
6363            degp,
6364            x2s.as_ptr() as *mut SpiceDouble,
6365            x,
6366            &mut p,
6367        )
6368    };
6369    p
6370}
6371
6372/**
6373Evaluate a Chebyshev expansion at `x`, returning the value and its indefinite integral.
6374*/
6375#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6376pub fn chbigr(degp: i32, cp: &[f64], x2s: [f64; 2], x: f64) -> (f64, f64) {
6377    let (mut p, mut itgrlp) = (0.0, 0.0);
6378    unsafe {
6379        crate::c::chbigr_c(
6380            degp,
6381            cp.as_ptr() as *mut SpiceDouble,
6382            x2s.as_ptr() as *mut SpiceDouble,
6383            x,
6384            &mut p,
6385            &mut itgrlp,
6386        )
6387    };
6388    (p, itgrlp)
6389}
6390
6391/**
6392Evaluate a Chebyshev expansion and its first `nderiv` derivatives at `x`.
6393*/
6394#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6395pub fn chbder(cp: &[f64], degp: i32, x2s: [f64; 2], x: f64, nderiv: i32) -> Vec<f64> {
6396    let count = nderiv.max(0) as usize + 1;
6397    let mut partdp = vec![0.0; 3 * count.max(1)];
6398    let mut dpdxs = vec![0.0; count.max(1)];
6399    let mut x2s = x2s;
6400    unsafe {
6401        crate::c::chbder_c(
6402            cp.as_ptr() as *mut SpiceDouble,
6403            degp,
6404            x2s.as_mut_ptr(),
6405            x,
6406            nderiv,
6407            partdp.as_mut_ptr(),
6408            dpdxs.as_mut_ptr(),
6409        )
6410    };
6411    dpdxs
6412}
6413
6414/**
6415Evaluate a polynomial and its first `nderiv` derivatives at `t`.
6416*/
6417#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6418pub fn polyds(coeffs: &[f64], deg: i32, nderiv: i32, t: f64) -> Vec<f64> {
6419    let mut p = vec![0.0; nderiv.max(0) as usize + 1];
6420    unsafe {
6421        crate::c::polyds_c(
6422            coeffs.as_ptr() as *mut SpiceDouble,
6423            deg,
6424            nderiv,
6425            t,
6426            p.as_mut_ptr(),
6427        )
6428    };
6429    p
6430}
6431
6432/**
6433Hermite interpolate a function and its derivative at evenly spaced points.
6434
6435`yvals` holds the value and derivative at each point, in pairs.
6436*/
6437#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6438pub fn hrmesp(first: f64, step: f64, yvals: &[f64], x: f64) -> (f64, f64) {
6439    let n = (yvals.len() / 2) as SpiceInt;
6440    let (mut f, mut df) = (0.0, 0.0);
6441    unsafe {
6442        crate::c::hrmesp_c(
6443            n,
6444            first,
6445            step,
6446            yvals.as_ptr() as *mut SpiceDouble,
6447            x,
6448            &mut f,
6449            &mut df,
6450        )
6451    };
6452    (f, df)
6453}
6454
6455/**
6456Hermite interpolate a function and its derivative at unevenly spaced points.
6457*/
6458#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6459pub fn hrmint(xvals: &[f64], yvals: &[f64], x: f64) -> (f64, f64) {
6460    let n = xvals.len() as SpiceInt;
6461    let mut work = vec![0.0; (4 * xvals.len() + 4).max(1)];
6462    let (mut f, mut df) = (0.0, 0.0);
6463    unsafe {
6464        crate::c::hrmint_c(
6465            n,
6466            xvals.as_ptr() as *mut SpiceDouble,
6467            yvals.as_ptr() as *mut SpiceDouble,
6468            x,
6469            work.as_mut_ptr(),
6470            &mut f,
6471            &mut df,
6472        )
6473    };
6474    (f, df)
6475}
6476
6477/**
6478Lagrange interpolate a function at evenly spaced points.
6479*/
6480#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6481pub fn lgresp(first: f64, step: f64, yvals: &[f64], x: f64) -> f64 {
6482    unsafe {
6483        crate::c::lgresp_c(
6484            yvals.len() as SpiceInt,
6485            first,
6486            step,
6487            yvals.as_ptr() as *mut SpiceDouble,
6488            x,
6489        )
6490    }
6491}
6492
6493/**
6494Lagrange interpolate a function at unevenly spaced points.
6495*/
6496#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6497pub fn lgrint(xvals: &[f64], yvals: &[f64], x: f64) -> f64 {
6498    unsafe {
6499        crate::c::lgrint_c(
6500            xvals.len() as SpiceInt,
6501            xvals.as_ptr() as *mut SpiceDouble,
6502            yvals.as_ptr() as *mut SpiceDouble,
6503            x,
6504        )
6505    }
6506}
6507
6508/**
6509Lagrange interpolate a function and its derivative at unevenly spaced points.
6510*/
6511#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6512pub fn lgrind(xvals: &[f64], yvals: &[f64], x: f64) -> (f64, f64) {
6513    let mut work = vec![0.0; (2 * xvals.len() + 2).max(1)];
6514    let (mut p, mut dp) = (0.0, 0.0);
6515    unsafe {
6516        crate::c::lgrind_c(
6517            xvals.len() as SpiceInt,
6518            xvals.as_ptr() as *mut SpiceDouble,
6519            yvals.as_ptr() as *mut SpiceDouble,
6520            work.as_mut_ptr(),
6521            x,
6522            &mut p,
6523            &mut dp,
6524        )
6525    };
6526    (p, dp)
6527}
6528
6529/**
6530Estimate a derivative by the central difference of a function sampled either side of a point.
6531*/
6532#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6533pub fn qderiv(f0: &[f64], f2: &[f64], delta: f64) -> Vec<f64> {
6534    let ndim = f0.len().min(f2.len());
6535    let mut dfdt = vec![0.0; ndim.max(1)];
6536    unsafe {
6537        crate::c::qderiv_c(
6538            ndim as SpiceInt,
6539            f0.as_ptr() as *mut SpiceDouble,
6540            f2.as_ptr() as *mut SpiceDouble,
6541            delta,
6542            dfdt.as_mut_ptr(),
6543        )
6544    };
6545    dfdt.truncate(ndim);
6546    dfdt
6547}
6548
6549/* -------------------------------------------------------------------------------------------- */
6550/* Plates                                                                                         */
6551/* -------------------------------------------------------------------------------------------- */
6552
6553/**
6554The total area of a set of triangular plates.
6555*/
6556#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6557pub fn pltar(vrtces: &[[f64; 3]], plates: &[[i32; 3]]) -> f64 {
6558    unsafe {
6559        crate::c::pltar_c(
6560            vrtces.len() as SpiceInt,
6561            vrtces.as_ptr() as *mut [f64; 3],
6562            plates.len() as SpiceInt,
6563            plates.as_ptr() as *mut [SpiceInt; 3],
6564        )
6565    }
6566}
6567
6568/**
6569The volume enclosed by a set of triangular plates.
6570*/
6571#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6572pub fn pltvol(vrtces: &[[f64; 3]], plates: &[[i32; 3]]) -> f64 {
6573    unsafe {
6574        crate::c::pltvol_c(
6575            vrtces.len() as SpiceInt,
6576            vrtces.as_ptr() as *mut [f64; 3],
6577            plates.len() as SpiceInt,
6578            plates.as_ptr() as *mut [SpiceInt; 3],
6579        )
6580    }
6581}
6582
6583cspice_proc! {
6584    /**
6585    The outward normal of a triangular plate, scaled by twice its area.
6586    */
6587    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6588    pub fn pltnrm(v1: [f64; 3], v2: [f64; 3], v3: [f64; 3]) -> [f64; 3] {}
6589}
6590
6591cspice_proc! {
6592    /**
6593    The point of a triangular plate nearest a given point, and the distance between them.
6594    */
6595    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6596    pub fn pltnp(
6597        point: [f64; 3],
6598        v1: [f64; 3],
6599        v2: [f64; 3],
6600        v3: [f64; 3]
6601    ) -> ([f64; 3], f64) {
6602    }
6603}
6604
6605cspice_proc! {
6606    /**
6607    Diagonalize a symmetric 2x2 matrix, returning the diagonal and the rotation that produces it.
6608    */
6609    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6610    pub fn diags2(symmat: [[f64; 2]; 2]) -> ([[f64; 2]; 2], [[f64; 2]; 2]) {}
6611}
6612
6613/* -------------------------------------------------------------------------------------------- */
6614/* More searches, sets and the kernel pool                                                        */
6615/* -------------------------------------------------------------------------------------------- */
6616
6617/// Linear search of an unordered array, for the three element types.
6618macro_rules! linear_search {
6619    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
6620        #[doc = $doc]
6621        ///
6622        /// Returns the index found, or `-1`.
6623        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6624        pub fn $name(value: $ty, array: &[$ty]) -> i32 {
6625            unsafe { crate::c::$cname(value, array.len() as SpiceInt, array.as_ptr() as *mut _) }
6626        }
6627    )*};
6628}
6629
6630linear_search! {
6631    isrchd(f64) => isrchd_c, "Search an unordered array of doubles.";
6632    isrchi(i32) => isrchi_c, "Search an unordered array of integers.";
6633}
6634
6635/**
6636Search an unordered array of strings.
6637
6638Returns the index found, or `-1`.
6639*/
6640#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6641pub fn isrchc<S: AsRef<str>>(value: &str, array: &[S]) -> i32 {
6642    let value = to_cstring(value);
6643    let (buffer, stride) = to_strided(array);
6644    unsafe {
6645        crate::c::isrchc_c(
6646            value.as_ptr() as *mut SpiceChar,
6647            array.len() as SpiceInt,
6648            stride as SpiceInt,
6649            buffer.as_ptr().cast(),
6650        )
6651    }
6652}
6653
6654/// The ordinal position of an item within a set, for the three element types.
6655macro_rules! ordinal {
6656    ($($name:ident($ty:ty, $cell:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
6657        #[doc = $doc]
6658        ///
6659        /// Positions run from zero; the result is `-1` when the item is not in the set.
6660        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6661        pub fn $name(item: $ty, set: &mut Cell<$cell>) -> i32 {
6662            let raw = set.as_mut_ptr();
6663            unsafe { crate::c::$cname(item, raw) }
6664        }
6665    )*};
6666}
6667
6668ordinal! {
6669    ordd(f64, f64) => ordd_c, "The ordinal position of a double precision number in a set.";
6670    ordi(i32, i32) => ordi_c, "The ordinal position of an integer in a set.";
6671}
6672
6673/**
6674The ordinal position of a string in a set, counting from zero, or `-1` when it is absent.
6675*/
6676#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6677pub fn ordc(item: &str, set: &mut Cell<String>) -> i32 {
6678    let item = to_cstring(item);
6679    let raw = set.as_mut_ptr();
6680    unsafe { crate::c::ordc_c(item.as_ptr() as *mut SpiceChar, raw) }
6681}
6682
6683cspice_proc! {
6684    /**
6685    Place the symmetric difference of two sets into `c`.
6686    */
6687    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6688    pub fn sdiff<T: CellItem>(a: &mut Cell<T>, b: &mut Cell<T>, c: &mut Cell<T>) {}
6689}
6690
6691cspice_proc! {
6692    /**
6693    Compare two sets; `op` is one of `"="`, `"<>"`, `"<="`, `"<"`, `">="` or `">"`.
6694    */
6695    #[return_output]
6696    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6697    pub fn set<T: CellItem>(a: &mut Cell<T>, op: &str, b: &mut Cell<T>) -> bool {}
6698}
6699
6700cspice_proc! {
6701    /**
6702    Parse a list on any of a set of delimiters, into a set of unique items.
6703    */
6704    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6705    pub fn lparss(list: &str, delims: &str, set: &mut Cell<String>) {}
6706}
6707
6708cspice_proc! {
6709    /**
6710    Find the frame ID codes of all reference frames of a given class in the kernel pool.
6711    */
6712    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6713    pub fn kplfrm(frmcls: i32, idset: &mut Cell<i32>) {}
6714}
6715
6716/**
6717Load the variables of a text kernel held in memory, rather than in a file.
6718*/
6719#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6720pub fn lmpool<S: AsRef<str>>(cvals: &[S]) {
6721    let (buffer, lenvals) = to_strided(cvals);
6722    unsafe {
6723        crate::c::lmpool_c(
6724            buffer.as_ptr().cast(),
6725            lenvals as SpiceInt,
6726            cvals.len() as SpiceInt,
6727        )
6728    }
6729}
6730
6731cspice_proc! {
6732    /**
6733    The value of a kernel pool parameter, such as `"MAXVAR"`, `"MAXLEN"` or `"MAXVAL"`.
6734
6735    This is about the pool's own limits, not about any variable in it; [`dtpool`] reports how many
6736    values a variable holds.
6737    */
6738    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6739    pub fn szpool(name: &str) -> (i32, bool) {}
6740}
6741
6742/**
6743Fetch the `nth` string of a kernel pool variable, re-joining any continuation lines.
6744
6745Returns the string, its length, and whether it was found.
6746
6747This function has a [neat version][crate::neat::stpool].
6748*/
6749pub fn stpool(item: &str, nth: i32, contin: &str, lenout: usize) -> (String, i32, bool) {
6750    let item = to_cstring(item);
6751    let contin = to_cstring(contin);
6752    let mut string = vec![0 as SpiceChar; lenout.max(1)];
6753    let (mut size, mut found) = (0, 0);
6754    unsafe {
6755        crate::c::stpool_c(
6756            item.as_ptr() as *mut SpiceChar,
6757            nth,
6758            contin.as_ptr() as *mut SpiceChar,
6759            lenout as SpiceInt,
6760            string.as_mut_ptr(),
6761            &mut size,
6762            &mut found,
6763        )
6764    };
6765    (from_cbuf(&string), size, found != 0)
6766}
6767
6768/* -------------------------------------------------------------------------------------------- */
6769/* Files, frames and time, the remainder                                                          */
6770/* -------------------------------------------------------------------------------------------- */
6771
6772cspice_proc! {
6773    /**
6774    Whether a file exists.
6775    */
6776    #[return_output]
6777    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6778    pub fn exists(name: &str) -> bool {}
6779}
6780
6781/**
6782Determine the architecture and type of a SPICE kernel file.
6783
6784This function has a [neat version][crate::neat::getfat].
6785*/
6786pub fn getfat(file: &str, arclen: usize, typlen: usize) -> (String, String) {
6787    let file = to_cstring(file);
6788    let mut arch = vec![0 as SpiceChar; arclen.max(1)];
6789    let mut kind = vec![0 as SpiceChar; typlen.max(1)];
6790    unsafe {
6791        crate::c::getfat_c(
6792            file.as_ptr() as *mut SpiceChar,
6793            arclen as SpiceInt,
6794            typlen as SpiceInt,
6795            arch.as_mut_ptr(),
6796            kind.as_mut_ptr(),
6797        )
6798    };
6799    (from_cbuf(&arch), from_cbuf(&kind))
6800}
6801
6802/**
6803Read the next line of a text file, opening it if it is not already open.
6804
6805Returns the line and whether the end of the file has been reached.
6806
6807The file stays open until it has been read to the end, and CSPICE refuses to load a file it already
6808has open, so an abandoned partial read makes that file unloadable. The C API has no counterpart to
6809Fortran's `CLTEXT` to close one early.
6810*/
6811#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6812pub fn rdtext(file: &str, lenout: usize) -> (String, bool) {
6813    let file = to_cstring(file);
6814    let mut line = vec![0 as SpiceChar; lenout.max(1)];
6815    let mut eof = 0;
6816    unsafe {
6817        crate::c::rdtext_c(
6818            file.as_ptr() as *mut SpiceChar,
6819            lenout as SpiceInt,
6820            line.as_mut_ptr(),
6821            &mut eof,
6822        )
6823    };
6824    (from_cbuf(&line), eof != 0)
6825}
6826
6827cspice_proc! {
6828    /**
6829    The centre, class and class ID of a reference frame.
6830    */
6831    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6832    pub fn frinfo(frcode: i32) -> (i32, i32, i32, bool) {}
6833}
6834
6835/**
6836Build a right handed orthonormal frame from a vector, which is normalised in place.
6837
6838Returns the normalised input and the two vectors completing the frame.
6839*/
6840#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6841pub fn frame(x: [f64; 3]) -> ([f64; 3], [f64; 3], [f64; 3]) {
6842    let mut x = x;
6843    let (mut y, mut z) = ([0.0; 3], [0.0; 3]);
6844    unsafe { crate::c::frame_c(x.as_mut_ptr(), y.as_mut_ptr(), z.as_mut_ptr()) };
6845    (x, y, z)
6846}
6847
6848/*
6849These two take their epoch through a `SpiceDouble *` rather than by value, so they cannot go
6850through the macro.
6851*/
6852
6853/**
6854Whether a ray is in the field of view of an instrument at a given epoch.
6855*/
6856#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6857pub fn fovray(
6858    inst: &str,
6859    raydir: [f64; 3],
6860    rframe: &str,
6861    abcorr: &str,
6862    obsrvr: &str,
6863    et: f64,
6864) -> bool {
6865    let inst = to_cstring(inst);
6866    let rframe = to_cstring(rframe);
6867    let abcorr = to_cstring(abcorr);
6868    let obsrvr = to_cstring(obsrvr);
6869    let mut raydir = raydir;
6870    let mut et = et;
6871    let mut visible = 0;
6872    unsafe {
6873        crate::c::fovray_c(
6874            inst.as_ptr() as *mut SpiceChar,
6875            raydir.as_mut_ptr(),
6876            rframe.as_ptr() as *mut SpiceChar,
6877            abcorr.as_ptr() as *mut SpiceChar,
6878            obsrvr.as_ptr() as *mut SpiceChar,
6879            &mut et,
6880            &mut visible,
6881        )
6882    };
6883    visible != 0
6884}
6885
6886/**
6887Whether a target is in the field of view of an instrument at a given epoch.
6888*/
6889#[allow(clippy::too_many_arguments)]
6890#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6891pub fn fovtrg(
6892    inst: &str,
6893    target: &str,
6894    tshape: &str,
6895    tframe: &str,
6896    abcorr: &str,
6897    obsrvr: &str,
6898    et: f64,
6899) -> bool {
6900    let inst = to_cstring(inst);
6901    let target = to_cstring(target);
6902    let tshape = to_cstring(tshape);
6903    let tframe = to_cstring(tframe);
6904    let abcorr = to_cstring(abcorr);
6905    let obsrvr = to_cstring(obsrvr);
6906    let mut et = et;
6907    let mut visible = 0;
6908    unsafe {
6909        crate::c::fovtrg_c(
6910            inst.as_ptr() as *mut SpiceChar,
6911            target.as_ptr() as *mut SpiceChar,
6912            tshape.as_ptr() as *mut SpiceChar,
6913            tframe.as_ptr() as *mut SpiceChar,
6914            abcorr.as_ptr() as *mut SpiceChar,
6915            obsrvr.as_ptr() as *mut SpiceChar,
6916            &mut et,
6917            &mut visible,
6918        )
6919    };
6920    visible != 0
6921}
6922
6923cspice_proc! {
6924    /**
6925    Find the illumination angles at a surface point, with the illumination source named separately.
6926    */
6927    #[allow(clippy::too_many_arguments)]
6928    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
6929    pub fn illumg(
6930        method: &str,
6931        target: &str,
6932        ilusrc: &str,
6933        et: f64,
6934        fixref: &str,
6935        abcorr: &str,
6936        obsrvr: &str,
6937        spoint: [f64; 3]
6938    ) -> (f64, [f64; 3], f64, f64, f64) {
6939    }
6940}
6941
6942/**
6943Return the field of view of an instrument, given its name, with the boundary vectors in the
6944instrument frame.
6945
6946This function has a [neat version][crate::neat::getfvn].
6947*/
6948pub fn getfvn(
6949    inst: &str,
6950    room: usize,
6951    shalen: usize,
6952    fralen: usize,
6953) -> (String, String, [f64; 3], Vec<[f64; 3]>) {
6954    let inst = to_cstring(inst);
6955    let mut shape = vec![0 as SpiceChar; shalen.max(1)];
6956    let mut frame = vec![0 as SpiceChar; fralen.max(1)];
6957    let mut bsight = [0.0; 3];
6958    let mut n = 0;
6959    let mut bounds = vec![[0.0; 3]; room.max(1)];
6960    unsafe {
6961        crate::c::getfvn_c(
6962            inst.as_ptr() as *mut SpiceChar,
6963            room as SpiceInt,
6964            shalen as SpiceInt,
6965            fralen as SpiceInt,
6966            shape.as_mut_ptr(),
6967            frame.as_mut_ptr(),
6968            bsight.as_mut_ptr(),
6969            &mut n,
6970            bounds.as_mut_ptr(),
6971        )
6972    };
6973    bounds.truncate(n.max(0) as usize);
6974    (from_cbuf(&shape), from_cbuf(&frame), bsight, bounds)
6975}
6976
6977/**
6978The local solar time at a longitude on a body.
6979
6980Returns the hour, minute and second, then the time string and the AM/PM form.
6981*/
6982#[allow(clippy::type_complexity)]
6983pub fn et2lst(
6984    et: f64,
6985    body: i32,
6986    lon: f64,
6987    kind: &str,
6988    timlen: usize,
6989    ampmlen: usize,
6990) -> (i32, i32, i32, String, String) {
6991    let kind = to_cstring(kind);
6992    let mut time = vec![0 as SpiceChar; timlen.max(1)];
6993    let mut ampm = vec![0 as SpiceChar; ampmlen.max(1)];
6994    let (mut hr, mut mn, mut sc) = (0, 0, 0);
6995    unsafe {
6996        crate::c::et2lst_c(
6997            et,
6998            body,
6999            lon,
7000            kind.as_ptr() as *mut SpiceChar,
7001            timlen as SpiceInt,
7002            ampmlen as SpiceInt,
7003            &mut hr,
7004            &mut mn,
7005            &mut sc,
7006            time.as_mut_ptr(),
7007            ampm.as_mut_ptr(),
7008        )
7009    };
7010    (hr, mn, sc, from_cbuf(&time), from_cbuf(&ampm))
7011}
7012
7013/**
7014Build a time format picture from a sample time string.
7015
7016Returns the picture, whether the sample was understood, and the error if it was not.
7017*/
7018pub fn tpictr(sample: &str, lenpictur: usize, lenerror: usize) -> (String, bool, String) {
7019    let sample = to_cstring(sample);
7020    let mut pictur = vec![0 as SpiceChar; lenpictur.max(1)];
7021    let mut errmsg = vec![0 as SpiceChar; lenerror.max(1)];
7022    let mut ok = 0;
7023    unsafe {
7024        crate::c::tpictr_c(
7025            sample.as_ptr() as *mut SpiceChar,
7026            lenpictur as SpiceInt,
7027            lenerror as SpiceInt,
7028            pictur.as_mut_ptr(),
7029            &mut ok,
7030            errmsg.as_mut_ptr(),
7031        )
7032    };
7033    (from_cbuf(&pictur), ok != 0, from_cbuf(&errmsg))
7034}
7035
7036/**
7037Set or retrieve a default used by the time routines.
7038
7039`action` is `"SET"` or `"GET"`; the current value is returned either way.
7040*/
7041pub fn timdef(action: &str, item: &str, value: &str, lenout: usize) -> String {
7042    let action = to_cstring(action);
7043    let item = to_cstring(item);
7044    let mut buffer = vec![0 as SpiceChar; lenout.max(value.len() + 1)];
7045    for (target, byte) in buffer.iter_mut().zip(value.as_bytes()) {
7046        *target = *byte as SpiceChar;
7047    }
7048    unsafe {
7049        crate::c::timdef_c(
7050            action.as_ptr() as *mut SpiceChar,
7051            item.as_ptr() as *mut SpiceChar,
7052            buffer.len() as SpiceInt,
7053            buffer.as_mut_ptr(),
7054        )
7055    };
7056    from_cbuf(&buffer)
7057}
7058
7059cspice_proc! {
7060    /**
7061    The name of the routine at a given depth in the traceback.
7062    */
7063    pub fn trcnam(index: i32, #[lenout] namelen: i32) -> String {}
7064}
7065
7066cspice_proc! {
7067    /**
7068    Disable the traceback, which cannot be turned back on.
7069    */
7070    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7071    pub fn trcoff() {}
7072}
7073
7074cspice_proc! {
7075    /**
7076    Replace a marker in a string with the cardinal text of an integer.
7077    */
7078    pub fn repmct(
7079        input: &str,
7080        marker: &str,
7081        value: i32,
7082        strcase: char,
7083        #[lenout] lenout: i32
7084    ) -> String {
7085    }
7086}
7087
7088/**
7089Extract the substring of a word that follows a keyword, from a list of terminating keywords.
7090
7091Returns the remaining string, whether the keyword was found, and the substring.
7092*/
7093#[allow(clippy::type_complexity)]
7094#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7095pub fn kxtrct<S: AsRef<str>>(
7096    keywd: &str,
7097    terms: &[S],
7098    string: &str,
7099    stringlen: usize,
7100    substrlen: usize,
7101) -> (String, bool, String) {
7102    let keywd = to_cstring(keywd);
7103    let (packed, termlen) = to_strided(terms);
7104    let mut buffer = vec![0 as SpiceChar; stringlen.max(string.len() + 1)];
7105    for (target, byte) in buffer.iter_mut().zip(string.as_bytes()) {
7106        *target = *byte as SpiceChar;
7107    }
7108    let mut substr = vec![0 as SpiceChar; substrlen.max(1)];
7109    let mut found = 0;
7110    unsafe {
7111        crate::c::kxtrct_c(
7112            keywd.as_ptr() as *mut SpiceChar,
7113            termlen as SpiceInt,
7114            packed.as_ptr().cast(),
7115            terms.len() as SpiceInt,
7116            buffer.len() as SpiceInt,
7117            substrlen as SpiceInt,
7118            buffer.as_mut_ptr(),
7119            &mut found,
7120            substr.as_mut_ptr(),
7121        )
7122    };
7123    (from_cbuf(&buffer), found != 0, from_cbuf(&substr))
7124}
7125
7126/* -------------------------------------------------------------------------------------------- */
7127/* Geometry finder                                                                                */
7128/* -------------------------------------------------------------------------------------------- */
7129
7130/*
7131Every search takes a confinement window to search within and a window to report the answer in. The
7132confinement window is an input that CSPICE also reads back, so it is taken by `&mut`; the result is
7133cleared and filled. Each has a neat version that allocates the result for you.
7134*/
7135
7136/// Generate the searches that compare a scalar quantity against a reference value.
7137macro_rules! gf_search {
7138    ($($name:ident($($arg:ident: $ty:ty),*) => $cname:ident, $doc:expr);* $(;)?) => {$(
7139        #[doc = $doc]
7140        ///
7141        /// `relate` is one of `"="`, `"<"`, `">"`, `"LOCMIN"`, `"ABSMIN"`, `"LOCMAX"` or
7142        /// `"ABSMAX"`; `nintvls` is the room to make in `result`, in intervals.
7143        #[allow(clippy::too_many_arguments)]
7144        pub fn $name(
7145            $($arg: $ty,)*
7146            relate: &str,
7147            refval: f64,
7148            adjust: f64,
7149            step: f64,
7150            nintvls: i32,
7151            cnfine: &mut Cell<f64>,
7152            result: &mut Cell<f64>,
7153        ) {
7154            $(let $arg = crate::core::ffi::In::new($arg);)*
7155            let relate = to_cstring(relate);
7156            #[allow(unused_mut)]
7157            let ($(mut $arg,)*) = ($($arg,)*);
7158            let cnfine = cnfine.as_mut_ptr();
7159            let result = result.as_mut_ptr();
7160            unsafe {
7161                crate::c::$cname(
7162                    $($arg.raw() as _,)*
7163                    relate.as_ptr() as *mut SpiceChar,
7164                    refval,
7165                    adjust,
7166                    step,
7167                    nintvls,
7168                    cnfine,
7169                    result,
7170                );
7171            }
7172        }
7173    )*};
7174}
7175
7176gf_search! {
7177    gfdist(target: &str, abcorr: &str, obsrvr: &str) => gfdist_c,
7178        "Search for times when the distance to a target meets a condition.";
7179    gfrr(target: &str, abcorr: &str, obsrvr: &str) => gfrr_c,
7180        "Search for times when the range rate of a target meets a condition.";
7181    gfpa(target: &str, illmn: &str, abcorr: &str, obsrvr: &str) => gfpa_c,
7182        "Search for times when the phase angle of a target meets a condition.";
7183    gfposc(
7184        target: &str, frame: &str, abcorr: &str, obsrvr: &str, crdsys: &str, coord: &str
7185    ) => gfposc_c,
7186        "Search for times when a coordinate of a target's position meets a condition.";
7187    gfsubc(
7188        target: &str, fixref: &str, method: &str, abcorr: &str, obsrvr: &str, crdsys: &str,
7189        coord: &str
7190    ) => gfsubc_c,
7191        "Search for times when a coordinate of the sub-observer point meets a condition.";
7192    gfsntc(
7193        target: &str, fixref: &str, method: &str, abcorr: &str, obsrvr: &str, dref: &str,
7194        dvec: [f64; 3], crdsys: &str, coord: &str
7195    ) => gfsntc_c,
7196        "Search for times when a coordinate of a ray-surface intercept meets a condition.";
7197    gfsep(
7198        targ1: &str, shape1: &str, frame1: &str, targ2: &str, shape2: &str, frame2: &str,
7199        abcorr: &str, obsrvr: &str
7200    ) => gfsep_c,
7201        "Search for times when the angular separation of two targets meets a condition.";
7202    gfilum(
7203        method: &str, angtyp: &str, target: &str, illmn: &str, fixref: &str, abcorr: &str,
7204        obsrvr: &str, spoint: [f64; 3]
7205    ) => gfilum_c,
7206        "Search for times when an illumination angle at a surface point meets a condition.";
7207}
7208
7209cspice_proc! {
7210    /**
7211    Search for times when a ray is in the field of view of an instrument.
7212    */
7213    #[allow(clippy::too_many_arguments)]
7214    pub fn gfrfov(
7215        inst: &str,
7216        raydir: [f64; 3],
7217        rframe: &str,
7218        abcorr: &str,
7219        obsrvr: &str,
7220        step: f64,
7221        cnfine: &mut Cell<f64>,
7222        result: &mut Cell<f64>
7223    ) {
7224    }
7225}
7226
7227cspice_proc! {
7228    /**
7229    Search for times when a target is in the field of view of an instrument.
7230    */
7231    #[allow(clippy::too_many_arguments)]
7232    pub fn gftfov(
7233        inst: &str,
7234        target: &str,
7235        tshape: &str,
7236        tframe: &str,
7237        abcorr: &str,
7238        obsrvr: &str,
7239        step: f64,
7240        cnfine: &mut Cell<f64>,
7241        result: &mut Cell<f64>
7242    ) {
7243    }
7244}
7245
7246cspice_proc! {
7247    /**
7248    Set the step size the geometry finder takes between samples.
7249    */
7250    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7251    pub fn gfsstp(step: f64) {}
7252}
7253
7254cspice_proc! {
7255    /**
7256    The step to take from an epoch, as set by [`gfsstp`].
7257    */
7258    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7259    pub fn gfstep(time: f64) -> f64 {}
7260}
7261
7262cspice_proc! {
7263    /**
7264    Set the convergence tolerance the geometry finder uses, in seconds.
7265    */
7266    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7267    pub fn gfstol(value: f64) {}
7268}
7269
7270cspice_proc! {
7271    /**
7272    Refine a bracketing interval by bisection.
7273    */
7274    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7275    pub fn gfrefn(t1: f64, t2: f64, s1: bool, s2: bool) -> f64 {}
7276}
7277
7278cspice_proc! {
7279    /**
7280    Whether an interrupt has been requested; see [`gfinth`].
7281    */
7282    #[return_output]
7283    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7284    pub fn gfbail() -> bool {}
7285}
7286
7287cspice_proc! {
7288    /**
7289    Clear the interrupt handler installed by [`gfinth`].
7290    */
7291    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7292    pub fn gfclrh() {}
7293}
7294
7295cspice_proc! {
7296    /**
7297    Install an interrupt handler for the signal `sigcode`, so a search can be stopped.
7298    */
7299    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7300    pub fn gfinth(sigcode: i32) {}
7301}
7302
7303cspice_proc! {
7304    /**
7305    Begin the default progress report over a confinement window.
7306    */
7307    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7308    pub fn gfrepi(window: &mut Cell<f64>, begmss: &str, endmss: &str) {}
7309}
7310
7311cspice_proc! {
7312    /**
7313    Update the default progress report.
7314    */
7315    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7316    pub fn gfrepu(ivbeg: f64, ivend: f64, time: f64) {}
7317}
7318
7319cspice_proc! {
7320    /**
7321    Finish the default progress report.
7322    */
7323    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7324    pub fn gfrepf() {}
7325}
7326
7327cspice_proc! {
7328    /**
7329    A placeholder scalar function, for the searches that want one but do not use it.
7330    */
7331    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7332    pub fn udf(x: f64) -> f64 {}
7333}
7334
7335/**
7336Whether a scalar function is decreasing at `x`, by a central difference over `dx`.
7337*/
7338#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7339pub fn uddc(udfunc: UdFunc, x: f64, dx: f64) -> bool {
7340    let mut isdecr = 0;
7341    unsafe { crate::c::uddc_c(Some(udfunc), x, dx, &mut isdecr) };
7342    isdecr != 0
7343}
7344
7345/**
7346The derivative of a scalar function at `x`, by a central difference over `dx`.
7347*/
7348#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7349pub fn uddf(udfunc: UdFunc, x: f64, dx: f64) -> f64 {
7350    let mut deriv = 0.0;
7351    unsafe { crate::c::uddf_c(Some(udfunc), x, dx, &mut deriv) };
7352    deriv
7353}
7354
7355/**
7356Search for times when a scalar function the caller supplies meets a condition.
7357
7358`udfuns` computes the quantity and `udfunb` says whether it is decreasing; [`uddc`] can be used to
7359build the second from the first.
7360*/
7361#[allow(clippy::too_many_arguments)]
7362pub fn gfuds(
7363    udfuns: UdFuns,
7364    udfunb: UdFunb,
7365    relate: &str,
7366    refval: f64,
7367    adjust: f64,
7368    step: f64,
7369    nintvls: i32,
7370    cnfine: &mut Cell<f64>,
7371    result: &mut Cell<f64>,
7372) {
7373    let relate = to_cstring(relate);
7374    let cnfine = cnfine.as_mut_ptr();
7375    let result = result.as_mut_ptr();
7376    unsafe {
7377        crate::c::gfuds_c(
7378            Some(udfuns),
7379            Some(udfunb),
7380            relate.as_ptr() as *mut SpiceChar,
7381            refval,
7382            adjust,
7383            step,
7384            nintvls,
7385            cnfine,
7386            result,
7387        );
7388    }
7389}
7390
7391/**
7392Search for times when a boolean function the caller supplies is true.
7393*/
7394pub fn gfudb(
7395    udfuns: UdFuns,
7396    udfunb: UdFunb,
7397    step: f64,
7398    cnfine: &mut Cell<f64>,
7399    result: &mut Cell<f64>,
7400) {
7401    let cnfine = cnfine.as_mut_ptr();
7402    let result = result.as_mut_ptr();
7403    unsafe { crate::c::gfudb_c(Some(udfuns), Some(udfunb), step, cnfine, result) };
7404}
7405
7406/**
7407Search for times when an occultation occurs, with the search progress and stepping under the
7408caller's control.
7409
7410[`crate::neat::gfoclt`] is the form to reach for unless the stepping needs to be customised.
7411*/
7412#[allow(clippy::too_many_arguments)]
7413#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7414pub fn gfocce(
7415    occtyp: &str,
7416    front: &str,
7417    fshape: &str,
7418    fframe: &str,
7419    back: &str,
7420    bshape: &str,
7421    bframe: &str,
7422    abcorr: &str,
7423    obsrvr: &str,
7424    tol: f64,
7425    udstep: UdStep,
7426    udrefn: UdRefn,
7427    rpt: bool,
7428    udrepi: UdRepi,
7429    udrepu: UdRepu,
7430    udrepf: UdRepf,
7431    bail: bool,
7432    udbail: UdBail,
7433    cnfine: &mut Cell<f64>,
7434    result: &mut Cell<f64>,
7435) {
7436    let occtyp = to_cstring(occtyp);
7437    let front = to_cstring(front);
7438    let fshape = to_cstring(fshape);
7439    let fframe = to_cstring(fframe);
7440    let back = to_cstring(back);
7441    let bshape = to_cstring(bshape);
7442    let bframe = to_cstring(bframe);
7443    let abcorr = to_cstring(abcorr);
7444    let obsrvr = to_cstring(obsrvr);
7445    let cnfine = cnfine.as_mut_ptr();
7446    let result = result.as_mut_ptr();
7447    unsafe {
7448        crate::c::gfocce_c(
7449            occtyp.as_ptr() as *mut SpiceChar,
7450            front.as_ptr() as *mut SpiceChar,
7451            fshape.as_ptr() as *mut SpiceChar,
7452            fframe.as_ptr() as *mut SpiceChar,
7453            back.as_ptr() as *mut SpiceChar,
7454            bshape.as_ptr() as *mut SpiceChar,
7455            bframe.as_ptr() as *mut SpiceChar,
7456            abcorr.as_ptr() as *mut SpiceChar,
7457            obsrvr.as_ptr() as *mut SpiceChar,
7458            tol,
7459            Some(udstep),
7460            Some(udrefn),
7461            rpt as crate::c::SpiceBoolean,
7462            Some(udrepi),
7463            Some(udrepu),
7464            Some(udrepf),
7465            bail as crate::c::SpiceBoolean,
7466            Some(udbail),
7467            cnfine,
7468            result,
7469        );
7470    }
7471}
7472
7473/**
7474Search for times when a target or ray is in the field of view of an instrument, with the search
7475progress and stepping under the caller's control.
7476
7477[`gftfov`] and [`gfrfov`] are the forms to reach for unless the stepping needs to be customised.
7478*/
7479#[allow(clippy::too_many_arguments)]
7480#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7481pub fn gffove(
7482    inst: &str,
7483    tshape: &str,
7484    raydir: [f64; 3],
7485    target: &str,
7486    tframe: &str,
7487    abcorr: &str,
7488    obsrvr: &str,
7489    tol: f64,
7490    udstep: UdStep,
7491    udrefn: UdRefn,
7492    rpt: bool,
7493    udrepi: UdRepi,
7494    udrepu: UdRepu,
7495    udrepf: UdRepf,
7496    bail: bool,
7497    udbail: UdBail,
7498    cnfine: &mut Cell<f64>,
7499    result: &mut Cell<f64>,
7500) {
7501    let inst = to_cstring(inst);
7502    let tshape = to_cstring(tshape);
7503    let target = to_cstring(target);
7504    let tframe = to_cstring(tframe);
7505    let abcorr = to_cstring(abcorr);
7506    let obsrvr = to_cstring(obsrvr);
7507    let mut raydir = raydir;
7508    let cnfine = cnfine.as_mut_ptr();
7509    let result = result.as_mut_ptr();
7510    unsafe {
7511        crate::c::gffove_c(
7512            inst.as_ptr() as *mut SpiceChar,
7513            tshape.as_ptr() as *mut SpiceChar,
7514            raydir.as_mut_ptr(),
7515            target.as_ptr() as *mut SpiceChar,
7516            tframe.as_ptr() as *mut SpiceChar,
7517            abcorr.as_ptr() as *mut SpiceChar,
7518            obsrvr.as_ptr() as *mut SpiceChar,
7519            tol,
7520            Some(udstep),
7521            Some(udrefn),
7522            rpt as crate::c::SpiceBoolean,
7523            Some(udrepi),
7524            Some(udrepu),
7525            Some(udrepf),
7526            bail as crate::c::SpiceBoolean,
7527            Some(udbail),
7528            cnfine,
7529            result,
7530        );
7531    }
7532}
7533
7534/**
7535Search for times when a geometric quantity named by a string meets a condition.
7536
7537The quantity and its parameters are given by name, which is what makes this the most general of the
7538searches and the most awkward to call; the specific searches above are easier where they apply.
7539*/
7540#[allow(clippy::too_many_arguments)]
7541#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7542pub fn gfevnt<S: AsRef<str>, T: AsRef<str>>(
7543    udstep: UdStep,
7544    udrefn: UdRefn,
7545    gquant: &str,
7546    qpnams: &[S],
7547    qcpars: &[T],
7548    qdpars: &[f64],
7549    qipars: &[i32],
7550    qlpars: &[bool],
7551    op: &str,
7552    refval: f64,
7553    tol: f64,
7554    adjust: f64,
7555    rpt: bool,
7556    udrepi: UdRepi,
7557    udrepu: UdRepu,
7558    udrepf: UdRepf,
7559    nintvls: i32,
7560    bail: bool,
7561    udbail: UdBail,
7562    cnfine: &mut Cell<f64>,
7563    result: &mut Cell<f64>,
7564) {
7565    let gquant = to_cstring(gquant);
7566    let op = to_cstring(op);
7567    let (names, namelen) = to_strided(qpnams);
7568    let (values, valuelen) = to_strided(qcpars);
7569    let lenvals = namelen.max(valuelen);
7570    // Both string arrays are read with the same stride, so they have to be packed with it.
7571    let (names, _) = if namelen == lenvals {
7572        (names, namelen)
7573    } else {
7574        repack(qpnams, lenvals)
7575    };
7576    let (values, _) = if valuelen == lenvals {
7577        (values, valuelen)
7578    } else {
7579        repack(qcpars, lenvals)
7580    };
7581    // CSPICE reads one element of each of the three numeric arrays per parameter name, whether or
7582    // not the quantity uses it, so they are padded rather than passed at the length given.
7583    let count = qpnams.len().max(1);
7584    let mut reals = qdpars.to_vec();
7585    let mut ints = qipars.to_vec();
7586    let mut flags = qlpars
7587        .iter()
7588        .map(|&flag| flag as crate::c::SpiceBoolean)
7589        .collect::<Vec<_>>();
7590    reals.resize(count, 0.0);
7591    ints.resize(count, 0);
7592    flags.resize(count, 0);
7593    let cnfine = cnfine.as_mut_ptr();
7594    let result = result.as_mut_ptr();
7595
7596    unsafe {
7597        crate::c::gfevnt_c(
7598            Some(udstep),
7599            Some(udrefn),
7600            gquant.as_ptr() as *mut SpiceChar,
7601            qpnams.len() as SpiceInt,
7602            lenvals as SpiceInt,
7603            names.as_ptr().cast(),
7604            values.as_ptr().cast(),
7605            reals.as_ptr() as *mut SpiceDouble,
7606            ints.as_ptr() as *mut SpiceInt,
7607            flags.as_ptr() as *mut crate::c::SpiceBoolean,
7608            op.as_ptr() as *mut SpiceChar,
7609            refval,
7610            tol,
7611            adjust,
7612            rpt as crate::c::SpiceBoolean,
7613            Some(udrepi),
7614            Some(udrepu),
7615            Some(udrepf),
7616            nintvls,
7617            bail as crate::c::SpiceBoolean,
7618            Some(udbail),
7619            cnfine,
7620            result,
7621        );
7622    }
7623}
7624
7625/// Pack strings at a stride the caller chooses, rather than at the natural one.
7626fn repack<S: AsRef<str>>(values: &[S], stride: usize) -> (Vec<SpiceChar>, usize) {
7627    let mut buffer = vec![0 as SpiceChar; values.len().max(1) * stride];
7628    for (index, value) in values.iter().enumerate() {
7629        let slot = &mut buffer[index * stride..(index + 1) * stride];
7630        for (target, byte) in slot.iter_mut().zip(value.as_ref().as_bytes()) {
7631            *target = *byte as SpiceChar;
7632        }
7633    }
7634    (buffer, stride)
7635}
7636
7637cspice_proc! {
7638    /**
7639    The largest integer CSPICE represents.
7640    */
7641    #[return_output]
7642    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7643    pub fn intmax() -> i32 {}
7644}
7645
7646cspice_proc! {
7647    /**
7648    The smallest integer CSPICE represents.
7649    */
7650    #[return_output]
7651    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7652    pub fn intmin() -> i32 {}
7653}
7654
7655/* -------------------------------------------------------------------------------------------- */
7656/* Constants                                                                                      */
7657/* -------------------------------------------------------------------------------------------- */
7658
7659/// Generate the wrappers of the CSPICE routines that just return a constant.
7660macro_rules! constants {
7661    ($($name:ident => $doc:expr),* $(,)?) => {$(
7662        cspice_proc! {
7663            #[doc = $doc]
7664            #[return_output]
7665            #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7666            pub fn $name() -> f64 {}
7667        }
7668    )*};
7669}
7670
7671constants! {
7672    b1900 => "Julian Date of the epoch B1900.",
7673    b1950 => "Julian Date of the epoch B1950.",
7674    clight => "Speed of light in a vacuum, in km/s.",
7675    dpr => "Number of degrees per radian.",
7676    halfpi => "Half the value of pi.",
7677    j1900 => "Julian Date of 1899 DEC 31 12:00:00 (1900 JAN 0.5).",
7678    j1950 => "Julian Date of 1950 JAN 01 00:00:00 (1950 JAN 1.0).",
7679    j2000 => "Julian Date of 2000 JAN 01 12:00:00 (2000 JAN 1.5).",
7680    j2100 => "Julian Date of 2100 JAN 01 12:00:00 (2100 JAN 1.5).",
7681    jyear => "Number of seconds in a Julian year.",
7682    pi => "Value of pi.",
7683    rpd => "Number of radians per degree.",
7684    spd => "Number of seconds in a day.",
7685    twopi => "Twice the value of pi.",
7686    tyear => "Number of seconds in a tropical year.",
7687}
7688
7689cspice_proc! {
7690    /**
7691    Return the version of the CSPICE toolkit; pass `"TOOLKIT"` as the item.
7692    */
7693    #[return_output]
7694    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7695    pub fn tkvrsn(item: &str) -> String {}
7696}
7697
7698/* -------------------------------------------------------------------------------------------- */
7699/* Events kernels                                                                                 */
7700/* -------------------------------------------------------------------------------------------- */
7701
7702/// Attributes of one column of a table of an events kernel.
7703#[allow(clippy::upper_case_acronyms)]
7704pub type EKATTDSC = crate::c::SpiceEKAttDsc;
7705
7706/// Summary of one segment of an events kernel: its table, its shape and its columns.
7707#[allow(clippy::upper_case_acronyms)]
7708pub type EKSEGSUM = crate::c::SpiceEKSegSum;
7709
7710/// Greatest number of columns a segment of an events kernel may have.
7711pub const EK_MXCLSG: usize = 100;
7712
7713/// Greatest number of items the `SELECT` clause of a query may name.
7714pub const EK_MAXQSEL: usize = 50;
7715
7716/// Length of the name of a column, with room for the terminator.
7717pub const EK_CSTRLN: usize = 33;
7718
7719/// Length of the name of a table, with room for the terminator.
7720pub const EK_TSTRLN: usize = 65;
7721
7722/// The size a column declares when the number of values in its entries varies from row to row.
7723pub const EK_VARSIZ: i32 = -1;
7724
7725/// The data type of a column of character strings.
7726pub const EK_CHR: crate::c::SpiceEKDataType = crate::c::_SpiceDataType_SPICE_CHR;
7727
7728/// The data type of a column of double precision numbers.
7729pub const EK_DP: crate::c::SpiceEKDataType = crate::c::_SpiceDataType_SPICE_DP;
7730
7731/// The data type of a column of integers.
7732pub const EK_INT: crate::c::SpiceEKDataType = crate::c::_SpiceDataType_SPICE_INT;
7733
7734/// The data type of a column of epochs, which are read as double precision numbers.
7735pub const EK_TIME: crate::c::SpiceEKDataType = crate::c::_SpiceDataType_SPICE_TIME;
7736
7737/// A selected item that is a column.
7738pub const EK_EXP_COL: crate::c::SpiceEKExprClass = crate::c::_SpiceEKExprClass_SPICE_EK_EXP_COL;
7739
7740/// A selected item that is a function applied to a column.
7741pub const EK_EXP_FUNC: crate::c::SpiceEKExprClass = crate::c::_SpiceEKExprClass_SPICE_EK_EXP_FUNC;
7742
7743/// A selected item that is neither a column nor a function of one.
7744pub const EK_EXP_EXPR: crate::c::SpiceEKExprClass = crate::c::_SpiceEKExprClass_SPICE_EK_EXP_EXPR;
7745
7746cspice_proc! {
7747    /**
7748    Open a new events kernel and prepare it for writing, returning the handle of the open file.
7749    */
7750    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7751    pub fn ekopn(fname: &str, ifname: &str, ncomch: i32) -> i32 {}
7752}
7753
7754cspice_proc! {
7755    /**
7756    Open an existing events kernel for reading, returning the handle of the open file.
7757    */
7758    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7759    pub fn ekopr(fname: &str) -> i32 {}
7760}
7761
7762cspice_proc! {
7763    /**
7764    Open an existing events kernel for writing, returning the handle of the open file.
7765    */
7766    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7767    pub fn ekopw(fname: &str) -> i32 {}
7768}
7769
7770cspice_proc! {
7771    /**
7772    Open a scratch events kernel and prepare it for writing, returning the handle of the open file.
7773
7774    The file is deleted when it is closed.
7775    */
7776    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7777    pub fn ekops() -> i32 {}
7778}
7779
7780cspice_proc! {
7781    /**
7782    Close an open events kernel.
7783    */
7784    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7785    pub fn ekcls(handle: i32) {}
7786}
7787
7788cspice_proc! {
7789    /**
7790    Load an events kernel, making it readable by the query routines, and return its handle.
7791
7792    [`furnsh`] loads one too; this is the form that hands back the handle.
7793    */
7794    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7795    pub fn eklef(fname: &str) -> i32 {}
7796}
7797
7798cspice_proc! {
7799    /**
7800    Unload an events kernel, making its contents unreadable and its room available again.
7801    */
7802    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7803    pub fn ekuef(handle: i32) {}
7804}
7805
7806cspice_proc! {
7807    /**
7808    Return the number of tables the loaded events kernels hold between them.
7809    */
7810    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7811    pub fn ekntab() -> i32 {}
7812}
7813
7814cspice_proc! {
7815    /**
7816    Return the name of the `n`th loaded table, counting from zero.
7817    */
7818    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7819    pub fn ektnam(n: i32, #[lenout] lenout: i32) -> String {}
7820}
7821
7822cspice_proc! {
7823    /**
7824    Return the number of distinct columns of a loaded table.
7825    */
7826    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7827    pub fn ekccnt(table: &str) -> i32 {}
7828}
7829
7830cspice_proc! {
7831    /**
7832    Return the name and the attributes of the `cindex`th column of a loaded table, counting from
7833    zero.
7834    */
7835    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7836    pub fn ekcii(table: &str, cindex: i32, #[lenout] lenout: i32) -> (String, EKATTDSC) {}
7837}
7838
7839cspice_proc! {
7840    /**
7841    Return the number of segments of an open events kernel.
7842    */
7843    #[return_output]
7844    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7845    pub fn eknseg(handle: i32) -> i32 {}
7846}
7847
7848cspice_proc! {
7849    /**
7850    Return the summary of a segment of an open events kernel, counting segments from zero.
7851    */
7852    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7853    pub fn ekssum(handle: i32, segno: i32) -> EKSEGSUM {}
7854}
7855
7856cspice_proc! {
7857    /**
7858    Run a query, returning the number of rows it matched, whether it could not be parsed, and the
7859    message saying why it could not.
7860    */
7861    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7862    pub fn ekfind(query: &str, #[lenout] lenout: i32) -> (i32, bool, String) {}
7863}
7864
7865cspice_proc! {
7866    /**
7867    Return the number of values in the entry of the `selidx`th selected item in a row of the result
7868    of the last [`ekfind`], counting both from zero.
7869    */
7870    #[return_output]
7871    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7872    pub fn eknelt(selidx: i32, row: i32) -> i32 {}
7873}
7874
7875cspice_proc! {
7876    /**
7877    Return one value of a character entry from the result of the last [`ekfind`], and whether it is
7878    null and whether it was found.
7879    */
7880    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7881    pub fn ekgc(
7882        selidx: i32,
7883        row: i32,
7884        elment: i32,
7885        #[lenout] lenout: i32
7886    ) -> (String, bool, bool) {
7887    }
7888}
7889
7890cspice_proc! {
7891    /**
7892    Return one value of a double precision entry from the result of the last [`ekfind`], and
7893    whether it is null and whether it was found.
7894    */
7895    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7896    pub fn ekgd(selidx: i32, row: i32, elment: i32) -> (f64, bool, bool) {}
7897}
7898
7899cspice_proc! {
7900    /**
7901    Return one value of an integer entry from the result of the last [`ekfind`], and whether it is
7902    null and whether it was found.
7903    */
7904    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7905    pub fn ekgi(selidx: i32, row: i32, elment: i32) -> (i32, bool, bool) {}
7906}
7907
7908cspice_proc! {
7909    /**
7910    Append an empty record to a segment of an open events kernel, returning its number.
7911    */
7912    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7913    pub fn ekappr(handle: i32, segno: i32) -> i32 {}
7914}
7915
7916cspice_proc! {
7917    /**
7918    Insert an empty record into a segment of an open events kernel, at the given index.
7919    */
7920    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7921    pub fn ekinsr(handle: i32, segno: i32, recno: i32) {}
7922}
7923
7924cspice_proc! {
7925    /**
7926    Delete a record from a segment of an open events kernel.
7927    */
7928    #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7929    pub fn ekdelr(handle: i32, segno: i32, recno: i32) {}
7930}
7931
7932/**
7933Start a segment of an open events kernel, returning its number.
7934
7935`cnames` names the columns and `decls` declares them, so the two have the same length.
7936*/
7937#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7938pub fn ekbseg<S: AsRef<str>, T: AsRef<str>>(
7939    handle: i32,
7940    tabnam: &str,
7941    cnames: &[S],
7942    decls: &[T],
7943) -> i32 {
7944    let tabnam = to_cstring(tabnam);
7945    let (names, cnmlen) = to_strided(cnames);
7946    let (declarations, declen) = to_strided(decls);
7947    let mut segno = 0;
7948    unsafe {
7949        crate::c::ekbseg_c(
7950            handle,
7951            tabnam.as_ptr() as *mut SpiceChar,
7952            cnames.len() as SpiceInt,
7953            cnmlen as SpiceInt,
7954            names.as_ptr().cast(),
7955            declen as SpiceInt,
7956            declarations.as_ptr().cast(),
7957            &mut segno,
7958        );
7959    }
7960    segno
7961}
7962
7963/**
7964Start a segment of an open events kernel that is to be written a column at a time.
7965
7966Returns the number of the segment and the record pointers, which every later call writing the
7967segment is handed in turn: the column additions [`ekaclc`], [`ekacld`] and [`ekacli`], and finally
7968[`ekffld`].
7969*/
7970#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
7971pub fn ekifld<S: AsRef<str>, T: AsRef<str>>(
7972    handle: i32,
7973    tabnam: &str,
7974    nrows: i32,
7975    cnames: &[S],
7976    decls: &[T],
7977) -> (i32, Vec<i32>) {
7978    let tabnam = to_cstring(tabnam);
7979    let (names, cnmlen) = to_strided(cnames);
7980    let (declarations, declen) = to_strided(decls);
7981    let mut segno = 0;
7982    let mut rcptrs = vec![0; (nrows.max(0) as usize).max(1)];
7983    unsafe {
7984        crate::c::ekifld_c(
7985            handle,
7986            tabnam.as_ptr() as *mut SpiceChar,
7987            cnames.len() as SpiceInt,
7988            nrows,
7989            cnmlen as SpiceInt,
7990            names.as_ptr().cast(),
7991            declen as SpiceInt,
7992            declarations.as_ptr().cast(),
7993            &mut segno,
7994            rcptrs.as_mut_ptr(),
7995        );
7996    }
7997    rcptrs.truncate(nrows.max(0) as usize);
7998    (segno, rcptrs)
7999}
8000
8001/**
8002Finish writing a segment started by [`ekifld`], given the record pointers it returned.
8003*/
8004#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8005pub fn ekffld(handle: i32, segno: i32, rcptrs: &mut [i32]) {
8006    unsafe { crate::c::ekffld_c(handle, segno, rcptrs.as_mut_ptr()) };
8007}
8008
8009/// The three column additions differ only in the type of the values they are handed.
8010macro_rules! ek_add_column {
8011    ($name:ident, $cname:ident, $ty:ty, $values:ident, $doc:expr) => {
8012        #[doc = $doc]
8013        ///
8014        /// `entszs` gives the number of values in each row's entry and `nlflgs` says which entries
8015        /// are null, so both have one element per row. `rcptrs` is what [`ekifld`] returned.
8016        #[allow(clippy::too_many_arguments)]
8017        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8018        pub fn $name(
8019            handle: i32,
8020            segno: i32,
8021            column: &str,
8022            $values: &[$ty],
8023            entszs: &[i32],
8024            nlflgs: &[bool],
8025            rcptrs: &[i32],
8026        ) {
8027            let column = to_cstring(column);
8028            let flags = nlflgs
8029                .iter()
8030                .map(|&flag| flag as crate::c::SpiceBoolean)
8031                .collect::<Vec<_>>();
8032            // The index is only read when the column is indexed, and then it needs one slot a row.
8033            let mut wkindx = vec![0 as SpiceInt; rcptrs.len().max(1)];
8034            unsafe {
8035                crate::c::$cname(
8036                    handle,
8037                    segno,
8038                    column.as_ptr() as *mut SpiceChar,
8039                    $values.as_ptr() as *mut _,
8040                    entszs.as_ptr() as *mut SpiceInt,
8041                    flags.as_ptr() as *mut crate::c::SpiceBoolean,
8042                    rcptrs.as_ptr() as *mut SpiceInt,
8043                    wkindx.as_mut_ptr(),
8044                );
8045            }
8046        }
8047    };
8048}
8049
8050ek_add_column!(
8051    ekacld,
8052    ekacld_c,
8053    f64,
8054    dvals,
8055    "Write a whole double precision column of a segment started by [`ekifld`]."
8056);
8057ek_add_column!(
8058    ekacli,
8059    ekacli_c,
8060    i32,
8061    ivals,
8062    "Write a whole integer column of a segment started by [`ekifld`]."
8063);
8064
8065/**
8066Write a whole character column of a segment started by [`ekifld`].
8067
8068`entszs` gives the number of values in each row's entry and `nlflgs` says which entries are null,
8069so both have one element per row. `rcptrs` is what [`ekifld`] returned.
8070*/
8071#[allow(clippy::too_many_arguments)]
8072#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8073pub fn ekaclc<S: AsRef<str>>(
8074    handle: i32,
8075    segno: i32,
8076    column: &str,
8077    cvals: &[S],
8078    entszs: &[i32],
8079    nlflgs: &[bool],
8080    rcptrs: &[i32],
8081) {
8082    let column = to_cstring(column);
8083    let (values, vallen) = to_strided(cvals);
8084    let flags = nlflgs
8085        .iter()
8086        .map(|&flag| flag as crate::c::SpiceBoolean)
8087        .collect::<Vec<_>>();
8088    let mut wkindx = vec![0 as SpiceInt; rcptrs.len().max(1)];
8089    unsafe {
8090        crate::c::ekaclc_c(
8091            handle,
8092            segno,
8093            column.as_ptr() as *mut SpiceChar,
8094            vallen as SpiceInt,
8095            values.as_ptr().cast(),
8096            entszs.as_ptr() as *mut SpiceInt,
8097            flags.as_ptr() as *mut crate::c::SpiceBoolean,
8098            rcptrs.as_ptr() as *mut SpiceInt,
8099            wkindx.as_mut_ptr(),
8100        );
8101    }
8102}
8103
8104/// Adding an entry to a record and updating one take the same arguments.
8105macro_rules! ek_record_write {
8106    ($name:ident, $cname:ident, $ty:ty, $values:ident, $doc:expr) => {
8107        #[doc = $doc]
8108        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8109        pub fn $name(
8110            handle: i32,
8111            segno: i32,
8112            recno: i32,
8113            column: &str,
8114            $values: &[$ty],
8115            isnull: bool,
8116        ) {
8117            let column = to_cstring(column);
8118            unsafe {
8119                crate::c::$cname(
8120                    handle,
8121                    segno,
8122                    recno,
8123                    column.as_ptr() as *mut SpiceChar,
8124                    $values.len() as SpiceInt,
8125                    $values.as_ptr() as *mut _,
8126                    isnull as crate::c::SpiceBoolean,
8127                );
8128            }
8129        }
8130    };
8131}
8132
8133ek_record_write!(
8134    ekaced,
8135    ekaced_c,
8136    f64,
8137    dvals,
8138    "Write a double precision entry into a record of a segment of an open events kernel."
8139);
8140ek_record_write!(
8141    ekacei,
8142    ekacei_c,
8143    i32,
8144    ivals,
8145    "Write an integer entry into a record of a segment of an open events kernel."
8146);
8147ek_record_write!(
8148    ekuced,
8149    ekuced_c,
8150    f64,
8151    dvals,
8152    "Replace a double precision entry of a record of a segment of an open events kernel."
8153);
8154ek_record_write!(
8155    ekucei,
8156    ekucei_c,
8157    i32,
8158    ivals,
8159    "Replace an integer entry of a record of a segment of an open events kernel."
8160);
8161
8162/// The two character record writers differ only in the routine they call.
8163macro_rules! ek_record_write_c {
8164    ($name:ident, $cname:ident, $doc:expr) => {
8165        #[doc = $doc]
8166        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8167        pub fn $name<S: AsRef<str>>(
8168            handle: i32,
8169            segno: i32,
8170            recno: i32,
8171            column: &str,
8172            cvals: &[S],
8173            isnull: bool,
8174        ) {
8175            let column = to_cstring(column);
8176            let (values, vallen) = to_strided(cvals);
8177            unsafe {
8178                crate::c::$cname(
8179                    handle,
8180                    segno,
8181                    recno,
8182                    column.as_ptr() as *mut SpiceChar,
8183                    cvals.len() as SpiceInt,
8184                    vallen as SpiceInt,
8185                    values.as_ptr().cast(),
8186                    isnull as crate::c::SpiceBoolean,
8187                );
8188            }
8189        }
8190    };
8191}
8192
8193ek_record_write_c!(
8194    ekacec,
8195    ekacec_c,
8196    "Write a character entry into a record of a segment of an open events kernel."
8197);
8198ek_record_write_c!(
8199    ekucec,
8200    ekucec_c,
8201    "Replace a character entry of a record of a segment of an open events kernel."
8202);
8203
8204/// The two numeric record readers differ only in the type of the values they report.
8205macro_rules! ek_record_read {
8206    ($name:ident, $cname:ident, $ty:ty, $zero:expr, $doc:expr) => {
8207        #[doc = $doc]
8208        ///
8209        /// `maxvals` is the room to make for the entry, in values; CSPICE writes as many as the
8210        /// entry holds, which is at most the size the column declares.
8211        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8212        pub fn $name(
8213            handle: i32,
8214            segno: i32,
8215            recno: i32,
8216            column: &str,
8217            maxvals: usize,
8218        ) -> (Vec<$ty>, bool) {
8219            let column = to_cstring(column);
8220            let mut values = vec![$zero; maxvals.max(1)];
8221            let (mut nvals, mut isnull) = (0, 0);
8222            unsafe {
8223                crate::c::$cname(
8224                    handle,
8225                    segno,
8226                    recno,
8227                    column.as_ptr() as *mut SpiceChar,
8228                    &mut nvals,
8229                    values.as_mut_ptr(),
8230                    &mut isnull,
8231                );
8232            }
8233            values.truncate((nvals.max(0) as usize).min(maxvals));
8234            (values, isnull != 0)
8235        }
8236    };
8237}
8238
8239ek_record_read!(
8240    ekrced,
8241    ekrced_c,
8242    f64,
8243    0.0,
8244    "Read a double precision entry of a record of a segment of an open events kernel."
8245);
8246ek_record_read!(
8247    ekrcei,
8248    ekrcei_c,
8249    i32,
8250    0,
8251    "Read an integer entry of a record of a segment of an open events kernel."
8252);
8253
8254/**
8255Read a character entry of a record of a segment of an open events kernel.
8256
8257`maxvals` is the room to make for the entry, in values, and `lenout` the room for each of them.
8258*/
8259#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8260pub fn ekrcec(
8261    handle: i32,
8262    segno: i32,
8263    recno: i32,
8264    column: &str,
8265    maxvals: usize,
8266    lenout: usize,
8267) -> (Vec<String>, bool) {
8268    let column = to_cstring(column);
8269    let stride = lenout.max(1);
8270    let mut buffer = vec![0 as SpiceChar; maxvals.max(1) * stride];
8271    let (mut nvals, mut isnull) = (0, 0);
8272    unsafe {
8273        crate::c::ekrcec_c(
8274            handle,
8275            segno,
8276            recno,
8277            column.as_ptr() as *mut SpiceChar,
8278            stride as SpiceInt,
8279            &mut nvals,
8280            buffer.as_mut_ptr().cast(),
8281            &mut isnull,
8282        );
8283    }
8284    let count = (nvals.max(0) as usize).min(maxvals);
8285    (from_strided(&buffer, stride, count), isnull != 0)
8286}
8287
8288/**
8289Parse the `SELECT` clause of a query, reporting in full on each item it selects.
8290
8291Returns, for each selected item, where its expression begins and ends in `query`, its data type,
8292its class, the table it is taken from and the column it names; then whether the query could not be
8293parsed, and the message saying why.
8294*/
8295#[allow(clippy::type_complexity)]
8296#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8297pub fn ekpsel(
8298    query: &str,
8299    msglen: usize,
8300    tablen: usize,
8301    collen: usize,
8302) -> (
8303    Vec<i32>,
8304    Vec<i32>,
8305    Vec<crate::c::SpiceEKDataType>,
8306    Vec<crate::c::SpiceEKExprClass>,
8307    Vec<String>,
8308    Vec<String>,
8309    bool,
8310    String,
8311) {
8312    let query = to_cstring(query);
8313    let (tablen, collen) = (tablen.max(1), collen.max(1));
8314    let mut xbegs = vec![0 as SpiceInt; EK_MAXQSEL];
8315    let mut xends = vec![0 as SpiceInt; EK_MAXQSEL];
8316    let mut xtypes = vec![EK_CHR; EK_MAXQSEL];
8317    let mut xclass = vec![EK_EXP_COL; EK_MAXQSEL];
8318    let mut tabs = vec![0 as SpiceChar; EK_MAXQSEL * tablen];
8319    let mut cols = vec![0 as SpiceChar; EK_MAXQSEL * collen];
8320    let mut errmsg = vec![0 as SpiceChar; msglen.max(1)];
8321    let (mut n, mut error) = (0, 0);
8322    unsafe {
8323        crate::c::ekpsel_c(
8324            query.as_ptr() as *mut SpiceChar,
8325            errmsg.len() as SpiceInt,
8326            tablen as SpiceInt,
8327            collen as SpiceInt,
8328            &mut n,
8329            xbegs.as_mut_ptr(),
8330            xends.as_mut_ptr(),
8331            xtypes.as_mut_ptr(),
8332            xclass.as_mut_ptr(),
8333            tabs.as_mut_ptr().cast(),
8334            cols.as_mut_ptr().cast(),
8335            &mut error,
8336            errmsg.as_mut_ptr(),
8337        );
8338    }
8339    let count = (n.max(0) as usize).min(EK_MAXQSEL);
8340    xbegs.truncate(count);
8341    xends.truncate(count);
8342    xtypes.truncate(count);
8343    xclass.truncate(count);
8344    (
8345        xbegs,
8346        xends,
8347        xtypes,
8348        xclass,
8349        from_strided(&tabs, tablen, count),
8350        from_strided(&cols, collen, count),
8351        error != 0,
8352        from_cbuf(&errmsg),
8353    )
8354}
8355
8356/* -------------------------------------------------------------------------------------------- */
8357/* The rest of the toolkit                                                                        */
8358/* -------------------------------------------------------------------------------------------- */
8359
8360/// Building an array of a repeated value, for the cases CSPICE provides a routine for.
8361macro_rules! fill_array {
8362    ($($name:ident($ty:ty, $value:expr) => $cname:ident, $doc:expr);* $(;)?) => {$(
8363        #[doc = $doc]
8364        ///
8365        /// `vec![]` does the same thing without leaving Rust; this is here for completeness.
8366        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8367        pub fn $name(value: $ty, ndim: usize) -> Vec<$ty> {
8368            let mut array = vec![$value; ndim.max(1)];
8369            unsafe { crate::c::$cname(value, ndim as SpiceInt, array.as_mut_ptr()) };
8370            array.truncate(ndim);
8371            array
8372        }
8373    )*};
8374}
8375
8376fill_array! {
8377    filld(f64, 0.0) => filld_c, "Fill a double precision array with a value.";
8378    filli(i32, 0) => filli_c, "Fill an integer array with a value.";
8379}
8380
8381/// Building an array of zeros, for the cases CSPICE provides a routine for.
8382macro_rules! clear_array {
8383    ($($name:ident($ty:ty, $value:expr) => $cname:ident, $doc:expr);* $(;)?) => {$(
8384        #[doc = $doc]
8385        ///
8386        /// `vec![]` does the same thing without leaving Rust; this is here for completeness.
8387        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8388        pub fn $name(ndim: usize) -> Vec<$ty> {
8389            let mut array = vec![$value; ndim.max(1)];
8390            unsafe { crate::c::$cname(ndim as SpiceInt, array.as_mut_ptr()) };
8391            array.truncate(ndim);
8392            array
8393        }
8394    )*};
8395}
8396
8397clear_array! {
8398    cleard(f64, 1.0) => cleard_c, "Set every element of a double precision array to zero.";
8399    cleari(i32, 1) => cleari_c, "Set every element of an integer array to zero.";
8400}
8401
8402/**
8403Set every string of an array to blank, returning `ndim` of them, each `arrlen` characters long.
8404
8405`vec![]` does the same thing without leaving Rust; this is here for completeness.
8406*/
8407#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8408pub fn clearc(ndim: usize, arrlen: usize) -> Vec<String> {
8409    let arrlen = arrlen.max(1);
8410    let mut array = vec![b'x' as SpiceChar; ndim.max(1) * arrlen];
8411    unsafe {
8412        crate::c::clearc_c(
8413            ndim as SpiceInt,
8414            arrlen as SpiceInt,
8415            array.as_mut_ptr().cast(),
8416        )
8417    };
8418    from_strided(&array, arrlen, ndim)
8419}
8420
8421/// The extremes, which CSPICE takes as variadic arguments.
8422macro_rules! extremum {
8423    ($($name:ident($ty:ty) => $cname:ident, $doc:expr);* $(;)?) => {$(
8424        #[doc = $doc]
8425        ///
8426        /// The C routine is variadic, which Rust cannot hand a list whose length is only known
8427        /// while it runs; folding the two argument form over the slice gives the same answer for
8428        /// any length. An empty slice gives zero, as the C routine does for a count of none.
8429        #[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8430        pub fn $name(values: &[$ty]) -> $ty {
8431            values
8432                .iter()
8433                .copied()
8434                .reduce(|left, right| unsafe { crate::c::$cname(2, left, right) })
8435                .unwrap_or_else(|| unsafe { crate::c::$cname(0) })
8436        }
8437    )*};
8438}
8439
8440extremum! {
8441    maxd(f64) => maxd_c, "The largest of a set of double precision numbers.";
8442    maxi(i32) => maxi_c, "The largest of a set of integers.";
8443    mind(f64) => mind_c, "The smallest of a set of double precision numbers.";
8444    mini(i32) => mini_c, "The smallest of a set of integers.";
8445}
8446
8447cspice_proc! {
8448    /**
8449    Return the `nth` word of a string, counting from zero, and where in the string it starts.
8450
8451    The location counts from zero too, and is -1 when the string has no such word.
8452    */
8453    pub fn nthwd(string: &str, nth: i32, #[lenout] worlen: i32) -> (String, i32) {}
8454}
8455
8456/**
8457Display a prompt and return the line the user types in reply.
8458
8459Reads from the standard input, so it blocks until there is a line to read.
8460*/
8461#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8462pub fn prompt(dspmsg: &str, buflen: usize) -> String {
8463    let dspmsg = to_cstring(dspmsg);
8464    let mut buffer = vec![0 as SpiceChar; buflen.max(1)];
8465    unsafe {
8466        crate::c::prompt_c(
8467            dspmsg.as_ptr() as *mut SpiceChar,
8468            buffer.len() as SpiceInt,
8469            buffer.as_mut_ptr(),
8470        )
8471    };
8472    from_cbuf(&buffer)
8473}
8474
8475/**
8476Store the command line arguments, so that [`getcml`] can hand them back.
8477
8478CSPICE keeps the pointers rather than the strings, so the copy this makes is leaked on purpose: it
8479has to outlive every later call. The toolkit refuses a second call, for the same reason.
8480*/
8481#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8482pub fn putcml<S: AsRef<str>>(argv: &[S]) {
8483    let pointers = argv
8484        .iter()
8485        .map(|value| to_cstring(value).into_raw())
8486        .collect::<Vec<_>>();
8487    let pointers = Box::leak(pointers.into_boxed_slice());
8488    unsafe { crate::c::putcml_c(argv.len() as SpiceInt, pointers.as_mut_ptr()) }
8489}
8490
8491/**
8492Return the command line arguments [`putcml`] was given.
8493*/
8494#[cfg_attr(any(feature = "lock", doc), impl_for(SpiceLock))]
8495pub fn getcml() -> Vec<String> {
8496    let (mut argc, mut argv) = (0, std::ptr::null_mut());
8497    unsafe { crate::c::getcml_c(&mut argc, &mut argv) };
8498    if argv.is_null() {
8499        return Vec::new();
8500    }
8501    (0..argc.max(0) as usize)
8502        .map(|index| unsafe {
8503            std::ffi::CStr::from_ptr(*argv.add(index))
8504                .to_string_lossy()
8505                .into_owned()
8506        })
8507        .collect()
8508}