Skip to content

Commit

Permalink
Merge #305
Browse files Browse the repository at this point in the history
305: Added a more ergonomic means of accessing GDAL version properties. r=lnicola a=metasim

- [X] I agree to follow the project's [code of conduct](https://github.com/georust/gdal/blob/master/CODE_OF_CONDUCT.md).
- [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---

This PR is of minor impact, but does provide some quality-of-life benefits when building systems which need to dynamically check and verify the version of GDAL available at runtime. 

GDAL's native query mechanism uses magical tokens that requires either brute memory, or repeated digging through API docs to fetch the particular version property needed. This PR aims to provide a slightly more principled approach to querying this information via a new `enum` called `VersionInfo`. It does not change the existing mechanism, only provides an alternative.

Co-authored-by: Simeon H.K. Fitch <fitch@astraea.io>
  • Loading branch information
bors[bot] and metasim committed Sep 21, 2022
2 parents 7536f19 + 476689b commit b495279
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Expand Up @@ -10,6 +10,10 @@

- <https://github.com/georust/gdal/pull/303>

- Added a more ergonomic means of accessing GDAL version properties

- <https://github.com/georust/gdal/pull/305>

- Provided access to `gdal-sys` discriminant values in `ResampleAlg` enum.

- <https://github.com/georust/gdal/pull/309>
Expand Down
132 changes: 130 additions & 2 deletions src/version.rs
@@ -1,18 +1,131 @@
//! GDAL Version Information Functions
//! GDAL Version Inspection Utilities
//!
//! See [`GDALVersionInfo`](https://gdal.org/api/raster_c_api.html#_CPPv415GDALVersionInfoPKc) for details.
//! ## Example
//!
//! Get the same string provided by using `--version` with the various GDAL CLI tools,
//! use [`VersionInfo::version_summary`]:
//!
//! ```rust, no_run
//! use gdal::version::VersionInfo;
//! let gdal_ver = VersionInfo::version_summary();
//! println!("{gdal_ver}")
//! ```
//! ```text,
//! GDAL 3.5.1, released 2022/06/30
//! ```

use crate::utils::_string;
use std::collections::HashMap;
use std::ffi::CString;
use std::fmt::Write;

/// Calls `GDALVersionInfo`, expecting `key` as one of the following values:
///
/// “VERSION_NUM”, “RELEASE_DATE”, “RELEASE_NAME”, "-–version”, “LICENSE”, “BUILD_INFO”.
///
/// See [`VersionInfo`] for a more ergonomic means of accessing these components.
///
/// Details: [`const char *GDALVersionInfo(const char*)`](https://gdal.org/api/raster_c_api.html#_CPPv415GDALVersionInfoPKc)
pub fn version_info(key: &str) -> String {
let c_key = CString::new(key.as_bytes()).unwrap();
_string(unsafe { gdal_sys::GDALVersionInfo(c_key.as_ptr()) })
}

/// Convenience functions for the various pre-defined queryable properties of GDAL version information.
///
/// ## Example
///
/// For the string returned from passing `--version` to GDAL CLI tools,
/// use [`VersionInfo::version_summary`]:
///
/// ```rust, no_run
/// # use gdal::version::VersionInfo;
/// println!("{}", VersionInfo::version_summary());
/// ```
/// ```text,
/// GDAL 3.5.1, released 2022/06/30
/// ```
/// For all the available version properties (except [`VersionInfo::license`],
/// use [VersionInfo::version_report]:
///
/// ```rust, no_run
/// # use gdal::version::VersionInfo;
/// let report = VersionInfo::version_report();
/// println!("{report}");
/// ```
/// ```text
/// GDALVersionInfo {
/// RELEASE_NAME: "3.5.1"
/// RELEASE_DATE: "20220630"
/// VERSION_NUM: "3050100"
/// BUILD_INFO {
/// PAM_ENABLED: "YES"
/// PROJ_BUILD_VERSION: "9.0.1"
/// OGR_ENABLED: "YES"
/// PROJ_RUNTIME_VERSION: "9.0.1"
/// GEOS_ENABLED: "YES"
/// GEOS_VERSION: "3.11.0-CAPI-1.17.0"
/// }
/// }
/// ```
pub struct VersionInfo;
impl VersionInfo {
/// Returns one line version message suitable for use in response to version requests. i.e. “GDAL 1.1.7, released 2002/04/16”
pub fn version_summary() -> String {
version_info("--version")
}
/// Returns GDAL_VERSION_NUM formatted as a string. i.e. “1170”
pub fn version_num() -> String {
version_info("VERSION_NUM")
}
/// Returns GDAL_RELEASE_DATE formatted as a string. i.e. “20020416"
pub fn release_date() -> String {
version_info("RELEASE_DATE")
}
/// Returns the GDAL_RELEASE_NAME. ie. “1.1.7”
pub fn release_name() -> String {
version_info("RELEASE_NAME")
}
/// Returns the content of the LICENSE.TXT file from the GDAL_DATA directory.
pub fn license() -> String {
version_info("LICENSE")
}
/// Get a dictionary of GDAL build configuration options, such as `GEOS_VERSION` and
/// `OGR_ENABLED`.
pub fn build_info() -> HashMap<String, String> {
let text = version_info("BUILD_INFO");
text.lines()
.filter_map(|l| l.split_once('='))
.map(|p| (p.0.to_string(), p.1.to_string()))
.collect()
}
/// Render all available version and build details in a multiline, debug string
pub fn version_report() -> String {
let mut buff: String = "GDALVersionInfo {\n".into();

fn kv(buff: &mut String, l: usize, k: &str, v: &str) {
writeln!(buff, "{:indent$}{k}: \"{v}\"", " ", indent = l * 4).unwrap();
}

kv(&mut buff, 1, "RELEASE_NAME", &Self::release_name());
kv(&mut buff, 1, "RELEASE_DATE", &Self::release_date());
kv(&mut buff, 1, "VERSION_NUM", &Self::version_num());
buff.push_str(" BUILD_INFO {\n");

Self::build_info()
.iter()
.for_each(|(k, v)| kv(&mut buff, 2, k, v));

buff.push_str(" }\n");
buff.push('}');
buff
}
}

#[cfg(test)]
mod tests {
use super::version_info;
use crate::version::VersionInfo;

#[test]
fn test_version_info() {
Expand All @@ -32,4 +145,19 @@ mod tests {

assert_eq!(version_text, expected_text);
}

#[test]
fn test_version_info_functions() {
let rel_name = VersionInfo::release_name();
assert!(!rel_name.is_empty());

let build = VersionInfo::build_info();
assert!(!build.is_empty());

let rpt = VersionInfo::version_report();
assert!(rpt.contains(&rel_name));

let license = VersionInfo::license();
assert!(!license.is_empty());
}
}

0 comments on commit b495279

Please sign in to comment.