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}