diff --git a/src/raster/tests.rs b/src/raster/tests.rs index e2574f3a2..efddb58f7 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -1,13 +1,17 @@ use crate::dataset::Dataset; use crate::metadata::Metadata; use crate::raster::rasterband::ResampleAlg; -use crate::raster::{ByteBuffer, ColorEntry, ColorInterpretation, ColorTable, GdalTypeDescriptor, RasterCreationOption, StatisticsAll, StatisticsMinMax}; +use crate::raster::{ + ByteBuffer, ColorEntry, ColorInterpretation, ColorTable, GdalTypeDescriptor, + RasterCreationOption, StatisticsAll, StatisticsMinMax, +}; use crate::test_utils::TempFixture; use crate::vsi::unlink_mem_file; use crate::Driver; use gdal_sys::GDALDataType; use std::path::Path; +use gdal_sys::GDALDataType::*; #[cfg(feature = "ndarray")] use ndarray::arr2; @@ -891,6 +895,7 @@ fn test_raster_stats() { } #[test] +#[allow(non_upper_case_globals)] fn test_gdal_data_type() { for t in GdalTypeDescriptor::available_types() { // Test converting from GDALDataType:Type @@ -898,5 +903,26 @@ fn test_gdal_data_type() { assert_eq!(t, &t2, "{}", t); assert!(t.bits() > 0, "{}", t); assert_eq!(t.bits(), t.bytes() * 8, "{}", t); + let name = t.name().unwrap(); + match t.gdal_type() { + GDT_Byte | GDT_UInt16 | GDT_Int16 | GDT_UInt32 | GDT_Int32 | GDT_UInt64 | GDT_Int64 => { + assert!(t.is_integer(), "{}", &name); + assert!(!t.is_floating(), "{}", &name); + } + GDT_Float32 | GDT_Float64 => { + assert!(!t.is_integer(), "{}", &name); + assert!(t.is_floating(), "{}", &name); + } + o => panic!("unknown type ordinal '{}'", o), + } + match t.gdal_type() { + GDT_Byte | GDT_UInt16 | GDT_UInt32 | GDT_UInt64 => { + assert!(!t.is_signed(), "{}", &name); + } + GDT_Int16 | GDT_Int32 | GDT_Int64 | GDT_Float32 | GDT_Float64 => { + assert!(t.is_signed(), "{}", &name); + } + o => panic!("unknown type ordinal '{}'", o), + } } } diff --git a/src/raster/types.rs b/src/raster/types.rs index 993ac1803..5cc51e696 100644 --- a/src/raster/types.rs +++ b/src/raster/types.rs @@ -1,8 +1,11 @@ -use std::fmt::{Display, Formatter}; -pub use gdal_sys::GDALDataType; -use gdal_sys::{GDALGetDataTypeName, GDALGetDataTypeSizeBits, GDALGetDataTypeSizeBytes}; use crate::errors::{GdalError, Result}; use crate::utils::{_last_null_pointer_err, _string}; +pub use gdal_sys::GDALDataType; +use gdal_sys::{ + GDALDataTypeIsFloating, GDALDataTypeIsInteger, GDALDataTypeIsSigned, GDALGetDataTypeName, + GDALGetDataTypeSizeBits, GDALGetDataTypeSizeBytes, +}; +use std::fmt::{Display, Formatter}; /// Type-level constraint for limiting which primitive numeric values can be passed /// to functions needing target data type. @@ -73,12 +76,31 @@ impl GdalTypeDescriptor { /// Get the gdal type size in **bits**. pub fn bits(&self) -> u8 { - unsafe { GDALGetDataTypeSizeBits(self.gdal_type()) }.try_into().unwrap() + unsafe { GDALGetDataTypeSizeBits(self.gdal_type()) } + .try_into() + .unwrap() } /// Get the gdal type size in **bytes**. pub fn bytes(&self) -> u8 { - unsafe { GDALGetDataTypeSizeBytes(self.gdal_type()) }.try_into().unwrap() + unsafe { GDALGetDataTypeSizeBytes(self.gdal_type()) } + .try_into() + .unwrap() + } + + /// Returns `true` if data type is integral (non-floating point) + pub fn is_integer(&self) -> bool { + (unsafe { GDALDataTypeIsInteger(self.gdal_type()) }) > 0 + } + + /// Returns `true` if data type is floating point (non-integral) + pub fn is_floating(&self) -> bool { + (unsafe { GDALDataTypeIsFloating(self.gdal_type()) }) > 0 + } + + /// Returns `true` if data type supports negative values. + pub fn is_signed(&self) -> bool { + (unsafe { GDALDataTypeIsSigned(self.gdal_type()) }) > 0 } /// Subset of the GDAL data types supported by Rust bindings. @@ -93,7 +115,7 @@ impl GdalTypeDescriptor { GdalTypeDescriptor(GDT_UInt64), GdalTypeDescriptor(GDT_Int64), GdalTypeDescriptor(GDT_Float32), - GdalTypeDescriptor(GDT_Float64) + GdalTypeDescriptor(GDT_Float64), ] } } @@ -110,10 +132,11 @@ impl TryFrom for GdalTypeDescriptor { fn try_from(value: GDALDataType::Type) -> std::result::Result { let wrapped = GdalTypeDescriptor(value); if !GdalTypeDescriptor::available_types().contains(&wrapped) { - Err(GdalError::BadArgument(format!("unknown GDALDataType {value}"))) + Err(GdalError::BadArgument(format!( + "unknown GDALDataType {value}" + ))) } else { Ok(wrapped) } } } -