las/
feature.rs

1//! Programmatically determine whether a las version supports a feature.
2//!
3//! Features are structures that implement the [Feature] trait. The most common
4//! way to use features is via [Version::supports] or
5//! [Version::verify_support_for]:
6//!
7//! ```
8//! use las::feature::Waveforms;
9//! use las::{Version, Error};
10//!
11//! let las_1_2 = Version::new(1, 2);
12//! assert!(!las_1_2.supports::<Waveforms>());
13//! assert!(las_1_2.verify_support_for::<Waveforms>().is_err());
14//!
15//! let las_1_4 = Version::new(1, 4);
16//! assert!(las_1_4.supports::<Waveforms>());
17//! assert!(las_1_4.verify_support_for::<Waveforms>().is_ok());
18//! ```
19
20use crate::Version;
21
22const MAJOR: u8 = 1;
23
24/// A trait implemented by each feature.
25pub trait Feature {
26    /// Is this feature supported by this version?
27    ///
28    /// # Examples
29    ///
30    /// ```
31    /// use las::feature::{Waveforms, Feature};
32    /// use las::Version;
33    /// assert!(!Waveforms::is_supported_by(Version::new(1, 2)));
34    /// assert!(Waveforms::is_supported_by(Version::new(1, 4)));
35    /// ```
36    fn is_supported_by(version: Version) -> bool;
37
38    /// Returns the name of this feature.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use las::feature::{Waveforms, Feature};
44    /// assert_eq!("Waveforms", Waveforms::name());
45    /// ```
46    fn name() -> &'static str;
47}
48
49macro_rules! features {
50    (   $(
51            $(#[$meta:meta])*
52            $name:ident ($($versions:expr_2021),+);
53        )+
54    ) => {
55        $(
56            $(#[$meta])*
57            #[derive(Clone, Copy, Debug)]
58            pub struct $name {}
59
60            impl Feature for $name {
61                fn is_supported_by(version: Version) -> bool {
62                    vec![$($versions),+]
63                        .into_iter()
64                        .map(|minor| Version::new(MAJOR, minor))
65                        .any(|v| version == v)
66                }
67
68                fn name() -> &'static str {
69                    stringify!($name)
70                }
71            }
72        )+
73    }
74}
75
76features! {
77    /// Does the header allow a file source id, or is that field reserved?
78    FileSourceId(1, 2, 3, 4);
79    /// Is there a bit flag to set the type of time value in each point?
80    GpsStandardTime(2, 3, 4);
81    /// Does this file support waveforms?
82    Waveforms(3, 4);
83    /// Is there a bit flag to indicate synthetic return numbers?
84    SyntheticReturnNumbers(3, 4);
85    /// Does this file support 64-bit point counts?
86    LargeFiles(4);
87    /// Does this file support extended variable length records?
88    Evlrs(4);
89}