Skip to main content

maliput/api/objects/
mod.rs

1// BSD 3-Clause License
2//
3// Copyright (c) 2026, Woven by Toyota.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice, this
10//   list of conditions and the following disclaimer.
11//
12// * Redistributions in binary form must reproduce the above copyright notice,
13//   this list of conditions and the following disclaimer in the documentation
14//   and/or other materials provided with the distribution.
15//
16// * Neither the name of the copyright holder nor the names of its
17//   contributors may be used to endorse or promote products derived from
18//   this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31use std::collections::HashMap;
32use strum_macros::{Display, EnumString};
33
34#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, Display)]
35/// Defines the possible road object types.
36pub enum RoadObjectType {
37    None,
38    Unknown,
39    Barrier,
40    GuardWall,
41    GuardRail,
42    Building,
43    Gantry,
44    Obstacle,
45    Pole,
46    TrafficIsland,
47    Tree,
48    Vegetation,
49    Pylon,
50    Delineator,
51    BikeStatic,
52    BusStatic,
53    CarStatic,
54    MotorbikeStatic,
55    Patch,
56    PedestrianStatic,
57    Railing,
58    RoadSurface,
59    SoundBarrier,
60    StreetLamp,
61    TrailerStatic,
62    TrainStatic,
63    TramStatic,
64    VanStatic,
65    Wind,
66}
67
68fn road_object_type_from_cpp(obj_type: maliput_sys::api::objects::ffi::RoadObjectType) -> RoadObjectType {
69    match obj_type {
70        maliput_sys::api::objects::ffi::RoadObjectType::kUnknown => RoadObjectType::Unknown,
71        maliput_sys::api::objects::ffi::RoadObjectType::kBarrier => RoadObjectType::Barrier,
72        maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall => RoadObjectType::GuardWall,
73        maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail => RoadObjectType::GuardRail,
74        maliput_sys::api::objects::ffi::RoadObjectType::kBuilding => RoadObjectType::Building,
75        maliput_sys::api::objects::ffi::RoadObjectType::kGantry => RoadObjectType::Gantry,
76        maliput_sys::api::objects::ffi::RoadObjectType::kObstacle => RoadObjectType::Obstacle,
77        maliput_sys::api::objects::ffi::RoadObjectType::kPole => RoadObjectType::Pole,
78        maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland => RoadObjectType::TrafficIsland,
79        maliput_sys::api::objects::ffi::RoadObjectType::kTree => RoadObjectType::Tree,
80        maliput_sys::api::objects::ffi::RoadObjectType::kVegetation => RoadObjectType::Vegetation,
81        maliput_sys::api::objects::ffi::RoadObjectType::kPylon => RoadObjectType::Pylon,
82        maliput_sys::api::objects::ffi::RoadObjectType::kDelineator => RoadObjectType::Delineator,
83        maliput_sys::api::objects::ffi::RoadObjectType::kBikeStatic => RoadObjectType::BikeStatic,
84        maliput_sys::api::objects::ffi::RoadObjectType::kBusStatic => RoadObjectType::BusStatic,
85        maliput_sys::api::objects::ffi::RoadObjectType::kCarStatic => RoadObjectType::CarStatic,
86        maliput_sys::api::objects::ffi::RoadObjectType::kMotorbikeStatic => RoadObjectType::MotorbikeStatic,
87        maliput_sys::api::objects::ffi::RoadObjectType::kPatch => RoadObjectType::Patch,
88        maliput_sys::api::objects::ffi::RoadObjectType::kPedestrianStatic => RoadObjectType::PedestrianStatic,
89        maliput_sys::api::objects::ffi::RoadObjectType::kRailing => RoadObjectType::Railing,
90        maliput_sys::api::objects::ffi::RoadObjectType::kRoadSurface => RoadObjectType::RoadSurface,
91        maliput_sys::api::objects::ffi::RoadObjectType::kSoundBarrier => RoadObjectType::SoundBarrier,
92        maliput_sys::api::objects::ffi::RoadObjectType::kStreetLamp => RoadObjectType::StreetLamp,
93        maliput_sys::api::objects::ffi::RoadObjectType::kTrailerStatic => RoadObjectType::TrailerStatic,
94        maliput_sys::api::objects::ffi::RoadObjectType::kTrainStatic => RoadObjectType::TrainStatic,
95        maliput_sys::api::objects::ffi::RoadObjectType::kTramStatic => RoadObjectType::TramStatic,
96        maliput_sys::api::objects::ffi::RoadObjectType::kVanStatic => RoadObjectType::VanStatic,
97        maliput_sys::api::objects::ffi::RoadObjectType::kWind => RoadObjectType::Wind,
98        _ => RoadObjectType::None,
99    }
100}
101
102fn road_object_type_to_cpp(obj_type: &RoadObjectType) -> maliput_sys::api::objects::ffi::RoadObjectType {
103    match obj_type {
104        RoadObjectType::None => maliput_sys::api::objects::ffi::RoadObjectType::kUnknown,
105        RoadObjectType::Unknown => maliput_sys::api::objects::ffi::RoadObjectType::kUnknown,
106        RoadObjectType::Barrier => maliput_sys::api::objects::ffi::RoadObjectType::kBarrier,
107        RoadObjectType::GuardWall => maliput_sys::api::objects::ffi::RoadObjectType::kGuardWall,
108        RoadObjectType::GuardRail => maliput_sys::api::objects::ffi::RoadObjectType::kGuardRail,
109        RoadObjectType::Building => maliput_sys::api::objects::ffi::RoadObjectType::kBuilding,
110        RoadObjectType::Gantry => maliput_sys::api::objects::ffi::RoadObjectType::kGantry,
111        RoadObjectType::Obstacle => maliput_sys::api::objects::ffi::RoadObjectType::kObstacle,
112        RoadObjectType::Pole => maliput_sys::api::objects::ffi::RoadObjectType::kPole,
113        RoadObjectType::TrafficIsland => maliput_sys::api::objects::ffi::RoadObjectType::kTrafficIsland,
114        RoadObjectType::Tree => maliput_sys::api::objects::ffi::RoadObjectType::kTree,
115        RoadObjectType::Vegetation => maliput_sys::api::objects::ffi::RoadObjectType::kVegetation,
116        RoadObjectType::Pylon => maliput_sys::api::objects::ffi::RoadObjectType::kPylon,
117        RoadObjectType::Delineator => maliput_sys::api::objects::ffi::RoadObjectType::kDelineator,
118        RoadObjectType::BikeStatic => maliput_sys::api::objects::ffi::RoadObjectType::kBikeStatic,
119        RoadObjectType::BusStatic => maliput_sys::api::objects::ffi::RoadObjectType::kBusStatic,
120        RoadObjectType::CarStatic => maliput_sys::api::objects::ffi::RoadObjectType::kCarStatic,
121        RoadObjectType::MotorbikeStatic => maliput_sys::api::objects::ffi::RoadObjectType::kMotorbikeStatic,
122        RoadObjectType::Patch => maliput_sys::api::objects::ffi::RoadObjectType::kPatch,
123        RoadObjectType::PedestrianStatic => maliput_sys::api::objects::ffi::RoadObjectType::kPedestrianStatic,
124        RoadObjectType::Railing => maliput_sys::api::objects::ffi::RoadObjectType::kRailing,
125        RoadObjectType::RoadSurface => maliput_sys::api::objects::ffi::RoadObjectType::kRoadSurface,
126        RoadObjectType::SoundBarrier => maliput_sys::api::objects::ffi::RoadObjectType::kSoundBarrier,
127        RoadObjectType::StreetLamp => maliput_sys::api::objects::ffi::RoadObjectType::kStreetLamp,
128        RoadObjectType::TrailerStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTrailerStatic,
129        RoadObjectType::TrainStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTrainStatic,
130        RoadObjectType::TramStatic => maliput_sys::api::objects::ffi::RoadObjectType::kTramStatic,
131        RoadObjectType::VanStatic => maliput_sys::api::objects::ffi::RoadObjectType::kVanStatic,
132        RoadObjectType::Wind => maliput_sys::api::objects::ffi::RoadObjectType::kWind,
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use super::{road_object_type_from_cpp, road_object_type_to_cpp, RoadObjectType};
139
140    #[test]
141    fn unknown_from_cpp_stays_unknown() {
142        let cpp = maliput_sys::api::objects::ffi::RoadObjectType::kUnknown;
143        assert_eq!(road_object_type_from_cpp(cpp), RoadObjectType::Unknown);
144    }
145
146    #[test]
147    fn none_to_cpp_maps_to_unknown() {
148        assert!(
149            road_object_type_to_cpp(&RoadObjectType::None) == maliput_sys::api::objects::ffi::RoadObjectType::kUnknown
150        );
151    }
152}
153
154/// Represents the position of a [RoadObject] in the road network.
155///
156/// Always contains an inertial position. May also contain a lane position
157/// expressed as `(lane_id, s, r, h)`.
158pub struct RoadObjectPosition {
159    pub inertial_position: crate::api::InertialPosition,
160    pub lane_position: Option<(String, f64, f64, f64)>,
161}
162
163/// Represents a single corner point of an [Outline].
164///
165/// `height` is `Some` when the corner has an explicit height attribute, `None` otherwise.
166pub struct OutlineCorner {
167    pub x: f64,
168    pub y: f64,
169    pub z: f64,
170    pub height: Option<f64>,
171}
172
173/// Represents an outline (a polygon) of a [RoadObject].
174pub struct Outline<'a> {
175    pub(crate) outline: &'a maliput_sys::api::objects::ffi::Outline,
176}
177
178impl<'a> Outline<'a> {
179    /// Returns the unique identifier of this outline.
180    pub fn id(&self) -> String {
181        maliput_sys::api::objects::ffi::Outline_id(self.outline)
182    }
183
184    /// Returns whether this outline is closed (first and last corner coincide).
185    pub fn is_closed(&self) -> bool {
186        maliput_sys::api::objects::ffi::Outline_is_closed(self.outline)
187    }
188
189    /// Returns the number of corners in this outline.
190    pub fn num_corners(&self) -> i32 {
191        maliput_sys::api::objects::ffi::Outline_num_corners(self.outline)
192    }
193
194    /// Returns the corners of this outline.
195    pub fn corners(&self) -> Vec<OutlineCorner> {
196        maliput_sys::api::objects::ffi::Outline_corners(self.outline)
197            .into_iter()
198            .map(|c| OutlineCorner {
199                x: c.x,
200                y: c.y,
201                z: c.z,
202                height: if c.has_height { Some(c.height) } else { None },
203            })
204            .collect()
205    }
206}
207
208/// Models a physical road object in the road network.
209///
210/// A `RoadObject` has a type, position, orientation, bounding box, and optional
211/// outlines and properties.
212pub struct RoadObject<'a> {
213    pub(crate) road_object: &'a maliput_sys::api::objects::ffi::RoadObject,
214}
215
216impl<'a> RoadObject<'a> {
217    /// Returns the unique identifier of this road object.
218    pub fn id(&self) -> String {
219        maliput_sys::api::objects::ffi::RoadObject_id(self.road_object)
220    }
221
222    /// Returns the optional human-readable name of this road object.
223    pub fn name(&self) -> Option<String> {
224        let wrapper = maliput_sys::api::objects::ffi::RoadObject_name(self.road_object);
225        if wrapper.is_null() {
226            return None;
227        }
228        Some(wrapper.value.clone())
229    }
230
231    /// Returns the [RoadObjectType] of this road object.
232    pub fn object_type(&self) -> RoadObjectType {
233        let t = maliput_sys::api::objects::ffi::RoadObject_object_type(self.road_object);
234        road_object_type_from_cpp(t)
235    }
236
237    /// Returns the optional subtype string of this road object.
238    pub fn subtype(&self) -> Option<String> {
239        let wrapper = maliput_sys::api::objects::ffi::RoadObject_subtype(self.road_object);
240        if wrapper.is_null() {
241            return None;
242        }
243        Some(wrapper.value.clone())
244    }
245
246    /// Returns the [RoadObjectPosition] of this road object.
247    pub fn position(&self) -> RoadObjectPosition {
248        let inertial_position = maliput_sys::api::objects::ffi::RoadObject_position_inertial(self.road_object);
249        let has_lane = maliput_sys::api::objects::ffi::RoadObject_position_has_lane_position(self.road_object);
250        let lane_position = if has_lane {
251            Some((
252                maliput_sys::api::objects::ffi::RoadObject_position_lane_id(self.road_object),
253                maliput_sys::api::objects::ffi::RoadObject_position_lane_s(self.road_object),
254                maliput_sys::api::objects::ffi::RoadObject_position_lane_r(self.road_object),
255                maliput_sys::api::objects::ffi::RoadObject_position_lane_h(self.road_object),
256            ))
257        } else {
258            None
259        };
260        RoadObjectPosition {
261            inertial_position: crate::api::InertialPosition { ip: inertial_position },
262            lane_position,
263        }
264    }
265
266    /// Returns the orientation of this road object in the inertial frame.
267    pub fn orientation(&self) -> crate::api::Rotation {
268        let rotation = maliput_sys::api::objects::ffi::RoadObject_orientation(self.road_object);
269        crate::api::Rotation { r: rotation }
270    }
271
272    /// Returns the bounding box of this road object.
273    pub fn bounding_box(&self) -> crate::math::BoundingBox {
274        let b = maliput_sys::api::objects::ffi::RoadObject_bounding_box(self.road_object);
275        crate::math::BoundingBox { b }
276    }
277
278    /// Returns whether this road object is dynamic (i.e., may change position or state).
279    pub fn is_dynamic(&self) -> bool {
280        maliput_sys::api::objects::ffi::RoadObject::is_dynamic(self.road_object)
281    }
282
283    /// Returns whether this road object's position can change.
284    pub fn is_movable(&self) -> bool {
285        maliput_sys::api::objects::ffi::RoadObject::is_movable(self.road_object)
286    }
287
288    /// Returns the IDs of lanes related to this road object.
289    pub fn related_lanes(&self) -> Vec<String> {
290        maliput_sys::api::objects::ffi::RoadObject_related_lanes(self.road_object)
291    }
292
293    /// Returns the number of outlines of this road object.
294    pub fn num_outlines(&self) -> i32 {
295        maliput_sys::api::objects::ffi::RoadObject::num_outlines(self.road_object)
296    }
297
298    /// Returns the outlines of this road object.
299    pub fn outlines(&self) -> Vec<Outline<'_>> {
300        maliput_sys::api::objects::ffi::RoadObject_outlines(self.road_object)
301            .into_iter()
302            .map(|ptr| Outline {
303                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
304            })
305            .collect()
306    }
307
308    /// Returns the key-value properties of this road object.
309    pub fn properties(&self) -> HashMap<String, String> {
310        maliput_sys::api::objects::ffi::RoadObject_properties(self.road_object)
311            .into_iter()
312            .map(|p| (p.key, p.value))
313            .collect()
314    }
315}
316
317/// Interface for accessing [RoadObject]s in the road network.
318pub struct RoadObjectBook<'a> {
319    pub(super) road_object_book: &'a maliput_sys::api::objects::ffi::RoadObjectBook,
320}
321
322impl<'a> RoadObjectBook<'a> {
323    /// Returns all [RoadObject]s in the book.
324    pub fn road_objects(&self) -> Vec<RoadObject<'_>> {
325        maliput_sys::api::objects::ffi::RoadObjectBook_RoadObjects(self.road_object_book)
326            .into_iter()
327            .map(|ptr| RoadObject {
328                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
329            })
330            .collect()
331    }
332
333    /// Returns the [RoadObject] with the given `id`, or `None` if not found.
334    pub fn get_road_object(&self, id: &String) -> Option<RoadObject<'_>> {
335        let ptr = maliput_sys::api::objects::ffi::RoadObjectBook_GetRoadObject(self.road_object_book, id);
336        if ptr.is_null() {
337            return None;
338        }
339        Some(RoadObject {
340            road_object: unsafe { ptr.as_ref().expect("Unable to get underlying RoadObject pointer") },
341        })
342    }
343
344    /// Returns all [RoadObject]s of the given [RoadObjectType].
345    pub fn find_by_type(&self, obj_type: &RoadObjectType) -> Vec<RoadObject<'_>> {
346        let obj_type_ffi = road_object_type_to_cpp(obj_type);
347        maliput_sys::api::objects::ffi::RoadObjectBook_FindByType(self.road_object_book, obj_type_ffi)
348            .into_iter()
349            .map(|ptr| RoadObject {
350                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
351            })
352            .collect()
353    }
354
355    /// Returns all [RoadObject]s whose `related_lanes()` includes the given lane ID.
356    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadObject<'_>> {
357        maliput_sys::api::objects::ffi::RoadObjectBook_FindByLane(self.road_object_book, lane_id)
358            .into_iter()
359            .map(|ptr| RoadObject {
360                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
361            })
362            .collect()
363    }
364
365    /// Returns all [RoadObject]s within `radius` meters of position `(x, y, z)`.
366    pub fn find_in_radius(&self, x: f64, y: f64, z: f64, radius: f64) -> Vec<RoadObject<'_>> {
367        maliput_sys::api::objects::ffi::RoadObjectBook_FindInRadius(self.road_object_book, x, y, z, radius)
368            .into_iter()
369            .map(|ptr| RoadObject {
370                road_object: unsafe { ptr.road_object.as_ref().expect("RoadObject pointer is null") },
371            })
372            .collect()
373    }
374}
375
376/// Domain alias for road marking semantic types.
377pub type RoadMarkingType = crate::api::rules::TrafficControlDeviceType;
378
379#[derive(Debug, Copy, Clone, PartialEq, Eq)]
380/// Unit of a [RoadMarkingValue].
381pub enum RoadMarkingValueUnit {
382    MetersPerSecond,
383    KilometersPerHour,
384    MilesPerHour,
385}
386
387fn road_marking_value_unit_from_cpp(u: maliput_sys::api::objects::ffi::RoadMarkingValueUnit) -> RoadMarkingValueUnit {
388    match u {
389        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMetersPerSecond => RoadMarkingValueUnit::MetersPerSecond,
390        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kKilometersPerHour => {
391            RoadMarkingValueUnit::KilometersPerHour
392        }
393        maliput_sys::api::objects::ffi::RoadMarkingValueUnit::kMilesPerHour => RoadMarkingValueUnit::MilesPerHour,
394        _ => RoadMarkingValueUnit::MetersPerSecond,
395    }
396}
397
398/// Numeric value (with unit) associated with a [RoadMarking] (e.g. a speed limit).
399#[derive(Debug, Copy, Clone, PartialEq)]
400pub struct RoadMarkingValue {
401    pub value: f64,
402    pub unit: RoadMarkingValueUnit,
403}
404
405/// Models a physical road marking (e.g. stop line, crosswalk, arrow) in the road network.
406pub struct RoadMarking<'a> {
407    pub(crate) road_marking: &'a maliput_sys::api::objects::ffi::RoadMarking,
408}
409
410impl<'a> RoadMarking<'a> {
411    /// Returns the unique identifier of this road marking.
412    pub fn id(&self) -> String {
413        maliput_sys::api::objects::ffi::RoadMarking_id(self.road_marking)
414    }
415
416    /// Returns the optional human-readable name of this road marking.
417    pub fn name(&self) -> Option<String> {
418        let wrapper = maliput_sys::api::objects::ffi::RoadMarking_name(self.road_marking);
419        if wrapper.is_null() {
420            return None;
421        }
422        Some(wrapper.value.clone())
423    }
424
425    /// Returns the [RoadMarkingType] of this road marking.
426    pub fn marking_type(&self) -> RoadMarkingType {
427        let t = maliput_sys::api::objects::ffi::RoadMarking_marking_type(self.road_marking);
428        crate::api::rules::traffic_control_device_type_from_cpp(&t)
429    }
430
431    /// Returns the [RoadObjectPosition] of this road marking.
432    pub fn position(&self) -> RoadObjectPosition {
433        let inertial_position = maliput_sys::api::objects::ffi::RoadMarking_position_inertial(self.road_marking);
434        let has_lane = maliput_sys::api::objects::ffi::RoadMarking_position_has_lane_position(self.road_marking);
435        let lane_position = if has_lane {
436            Some((
437                maliput_sys::api::objects::ffi::RoadMarking_position_lane_id(self.road_marking),
438                maliput_sys::api::objects::ffi::RoadMarking_position_lane_s(self.road_marking),
439                maliput_sys::api::objects::ffi::RoadMarking_position_lane_r(self.road_marking),
440                maliput_sys::api::objects::ffi::RoadMarking_position_lane_h(self.road_marking),
441            ))
442        } else {
443            None
444        };
445        RoadObjectPosition {
446            inertial_position: crate::api::InertialPosition { ip: inertial_position },
447            lane_position,
448        }
449    }
450
451    /// Returns the orientation of this road marking in the inertial frame.
452    pub fn orientation(&self) -> crate::api::Rotation {
453        let rotation = maliput_sys::api::objects::ffi::RoadMarking_orientation(self.road_marking);
454        crate::api::Rotation { r: rotation }
455    }
456
457    /// Returns the bounding box of this road marking.
458    pub fn bounding_box(&self) -> crate::math::BoundingBox {
459        let b = maliput_sys::api::objects::ffi::RoadMarking_bounding_box(self.road_marking);
460        crate::math::BoundingBox { b }
461    }
462
463    /// Returns the IDs of lanes related to this road marking.
464    pub fn related_lanes(&self) -> Vec<String> {
465        maliput_sys::api::objects::ffi::RoadMarking_related_lanes(self.road_marking)
466    }
467
468    /// Returns the number of outlines of this road marking.
469    pub fn num_outlines(&self) -> i32 {
470        maliput_sys::api::objects::ffi::RoadMarking::num_outlines(self.road_marking)
471    }
472
473    /// Returns the outlines of this road marking.
474    pub fn outlines(&self) -> Vec<Outline<'_>> {
475        maliput_sys::api::objects::ffi::RoadMarking_outlines(self.road_marking)
476            .into_iter()
477            .map(|ptr| Outline {
478                outline: unsafe { ptr.outline.as_ref().expect("Outline pointer is null") },
479            })
480            .collect()
481    }
482
483    /// Returns the numeric value (with unit) associated with this road marking, if any.
484    pub fn value(&self) -> Option<RoadMarkingValue> {
485        let data = maliput_sys::api::objects::ffi::RoadMarking_value(self.road_marking);
486        if !data.has_value {
487            return None;
488        }
489        Some(RoadMarkingValue {
490            value: data.value,
491            unit: road_marking_value_unit_from_cpp(data.unit),
492        })
493    }
494}
495
496/// Interface for accessing [RoadMarking]s in the road network.
497pub struct RoadMarkingBook<'a> {
498    pub(super) road_marking_book: &'a maliput_sys::api::objects::ffi::RoadMarkingBook,
499}
500
501impl<'a> RoadMarkingBook<'a> {
502    /// Returns all [RoadMarking]s in the book.
503    pub fn road_markings(&self) -> Vec<RoadMarking<'_>> {
504        maliput_sys::api::objects::ffi::RoadMarkingBook_RoadMarkings(self.road_marking_book)
505            .into_iter()
506            .map(|ptr| RoadMarking {
507                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
508            })
509            .collect()
510    }
511
512    /// Returns the [RoadMarking] with the given `id`, or `None` if not found.
513    pub fn get_road_marking(&self, id: &String) -> Option<RoadMarking<'_>> {
514        let ptr = maliput_sys::api::objects::ffi::RoadMarkingBook_GetRoadMarking(self.road_marking_book, id);
515        if ptr.is_null() {
516            return None;
517        }
518        Some(RoadMarking {
519            road_marking: unsafe { ptr.as_ref().expect("Unable to get underlying RoadMarking pointer") },
520        })
521    }
522
523    /// Returns all [RoadMarking]s whose `related_lanes()` includes the given lane ID.
524    pub fn find_by_lane(&self, lane_id: &String) -> Vec<RoadMarking<'_>> {
525        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByLane(self.road_marking_book, lane_id)
526            .into_iter()
527            .map(|ptr| RoadMarking {
528                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
529            })
530            .collect()
531    }
532
533    /// Returns all [RoadMarking]s of the given [RoadMarkingType].
534    pub fn find_by_type(&self, marking_type: &RoadMarkingType) -> Vec<RoadMarking<'_>> {
535        let t_ffi = crate::api::rules::traffic_control_device_type_to_cpp(marking_type);
536        maliput_sys::api::objects::ffi::RoadMarkingBook_FindByType(self.road_marking_book, t_ffi)
537            .into_iter()
538            .map(|ptr| RoadMarking {
539                road_marking: unsafe { ptr.road_marking.as_ref().expect("RoadMarking pointer is null") },
540            })
541            .collect()
542    }
543}