From c80bb04542b4a56f2c174b526006f6d3e402eecc Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 9 Nov 2017 09:42:09 -0500 Subject: Rust implementation of protocol_list_supports_protocol_or_later() --- src/rust/protover/ffi.rs | 33 ++++++++++++++++++++++++++++++ src/rust/protover/protover.rs | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) (limited to 'src') diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs index cf2e9fd783..cebf9e12fa 100644 --- a/src/rust/protover/ffi.rs +++ b/src/rust/protover/ffi.rs @@ -100,6 +100,39 @@ pub extern "C" fn protocol_list_supports_protocol( return if is_supported { 1 } else { 0 }; } +/// Provide an interface for C to translate arguments and return types for +/// protover::list_supports_protocol_or_later +#[no_mangle] +pub extern "C" fn protocol_list_supports_protocol_or_later( + c_protocol_list: *const c_char, + c_protocol: uint32_t, + version: uint32_t, +) -> c_int { + if c_protocol_list.is_null() { + return 1; + } + + // Require an unsafe block to read the version from a C string. The pointer + // is checked above to ensure it is not null. + let c_str: &CStr = unsafe { CStr::from_ptr(c_protocol_list) }; + + let protocol_list = match c_str.to_str() { + Ok(n) => n, + Err(_) => return 1, + }; + + let protocol = match translate_to_rust(c_protocol) { + Ok(n) => n, + Err(_) => return 0, + }; + + let is_supported = + protover_string_supports_protocol_or_later( + protocol_list, protocol, version); + + return if is_supported { 1 } else { 0 }; +} + /// Provide an interface for C to translate arguments and return types for /// protover::get_supported_protocols #[no_mangle] diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs index f19f7972fd..85cdb3060a 100644 --- a/src/rust/protover/protover.rs +++ b/src/rust/protover/protover.rs @@ -325,6 +325,53 @@ pub fn protover_string_supports_protocol( supported_versions.contains(&vers) } +/// As protover_string_supports_protocol(), but also returns True if +/// any later version of the protocol is supported. +/// +/// # Examples +/// ``` +/// use protover::*; +/// +/// let is_supported = protover_string_supports_protocol_or_later( +/// "Link=3-4 Cons=5", Proto::Cons, 5); +/// +/// assert_eq!(true, is_supported); +/// +/// let is_supported = protover_string_supports_protocol_or_later( +/// "Link=3-4 Cons=5", Proto::Cons, 4); +/// +/// assert_eq!(true, is_supported); +/// +/// let is_supported = protover_string_supports_protocol_or_later( +/// "Link=3-4 Cons=5", Proto::Cons, 6); +/// +/// assert_eq!(false, is_supported); +/// ``` +pub fn protover_string_supports_protocol_or_later( + list: &str, + proto: Proto, + vers: u32, +) -> bool { + let supported: HashMap>; + + match parse_protocols_from_string(list) { + Ok(result) => supported = result, + Err(_) => return false, + } + + let supported_versions = match supported.get(&proto) { + Some(n) => n, + None => return false, + }; + + for v in supported_versions.iter() { + if v >= &vers { + return true; + } + } + return false; +} + /// Fully expand a version range. For example, 1-3 expands to 1,2,3 /// Helper for get_versions /// -- cgit v1.2.3-54-g00ecf