Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a more ergonomic means of accessing GDAL version properties. #305

Merged
merged 7 commits into from Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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());
}
}