Skip to main content

geometry_adapt/
adapt_borrowed_array.rs

1//! [`Point`] impl for `Adapt<&[T; N]>` — a borrowed array.
2//!
3//! Mirrors `boost/geometry/geometries/adapted/c_array.hpp` (raw C
4//! arrays) and `boost/geometry/geometries/adapted/std_array.hpp`
5//! (`std::array<T, N>`); the C++ side adapts both via the same
6//! read-only `traits::access` specialisation because writing through
7//! a const pointer is forbidden anyway. The Rust port encodes that
8//! read-only nature by implementing [`Point`] (read) but *not*
9//! `PointMut` (write) — the split added in KC1.T1.
10//!
11//! # Silent-Cartesian warning
12//!
13//! Same as for [`Adapt<[T; N]>`](crate::Adapt): this impl pins
14//! `type Cs = Cartesian`. A raw `Adapt::<&[f64; 2]>(&[lon, lat])`
15//! therefore satisfies every Cartesian-only strategy bound and will
16//! silently compute Pythagorean nonsense over lat/lon. Wrap
17//! geographic / spherical borrowed arrays with [`WithCs`](crate::WithCs).
18
19use geometry_coords::CoordinateScalar;
20use geometry_cs::Cartesian;
21use geometry_tag::PointTag;
22use geometry_trait::{Geometry, Point};
23
24use crate::Adapt;
25
26impl<T: CoordinateScalar, const N: usize> Geometry for Adapt<&[T; N]> {
27    type Kind = PointTag;
28    type Point = Self;
29}
30
31impl<T: CoordinateScalar, const N: usize> Point for Adapt<&[T; N]> {
32    type Scalar = T;
33    type Cs = Cartesian;
34    const DIM: usize = N;
35
36    #[inline]
37    fn get<const D: usize>(&self) -> T {
38        self.0[D]
39    }
40    // No `set::<D>` — the borrow is read-only by construction.
41    // No `impl PointMut` either, *deliberately*: callers who need
42    // mutation must own their array.
43}
44
45#[cfg(test)]
46#[allow(
47    clippy::float_cmp,
48    reason = "Coordinates are read back unchanged from a literal array."
49)]
50mod tests {
51    //! Mirrors the access round-trip checks in
52    //! `boost/geometry/test/core/access.cpp` (the C-array case) but
53    //! for a borrow.
54
55    use super::*;
56    use geometry_trait::check_point;
57
58    #[test]
59    fn read_a_borrowed_array() {
60        let storage = [3.0_f64, 4.0];
61        let p = Adapt(&storage);
62        assert_eq!(p.get::<0>(), 3.0);
63        assert_eq!(p.get::<1>(), 4.0);
64        assert_eq!(<Adapt<&[f64; 2]> as Point>::DIM, 2);
65    }
66
67    #[test]
68    fn concept_check_passes_for_borrowed_adapter() {
69        check_point::<Adapt<&[f64; 2]>>();
70        check_point::<Adapt<&[f64; 3]>>();
71    }
72
73    /// Doctest-style demonstration: a `Vec` of borrows into a fixed
74    /// backing store. The borrows live as long as the backing slice.
75    #[test]
76    fn vec_of_borrows_iterates() {
77        let backing = [[1.0_f64, 2.0], [3.0, 4.0], [5.0, 6.0]];
78        let points: Vec<Adapt<&[f64; 2]>> = backing.iter().map(Adapt).collect();
79        assert_eq!(points.len(), 3);
80        assert_eq!(points[2].get::<0>(), 5.0);
81    }
82}