Created
March 2, 2024 01:42
-
-
Save JohnScience/b409739f3c84d856e259f9ac56f6c38a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct VSRegKey(registry::RegKey); | |
impl VSRegKey { | |
pub fn open() -> Result<Self, registry::key::Error> { | |
let regkey = registry::Hive::LocalMachine.open( | |
r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio", | |
registry::Security::Read, | |
)?; | |
Ok(Self(regkey)) | |
} | |
pub fn into_inner(self) -> registry::RegKey { | |
self.0 | |
} | |
} | |
/// A version of Visual Studio, e.g. "14.0", "14.29", "15.0", "16.0". | |
#[derive(Debug)] | |
pub struct VSVersion(String); | |
pub struct VCRedistRegKeyForVSVersion(registry::RegKey); | |
impl VCRedistRegKeyForVSVersion { | |
pub fn open(version: &VSVersion) -> Result<Self, registry::key::Error> { | |
let regkey = registry::Hive::LocalMachine.open( | |
&format!( | |
r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\{}\VC\Runtimes\x86", | |
version.0 | |
), | |
registry::Security::Read, | |
)?; | |
Ok(Self(regkey)) | |
} | |
pub fn into_inner(self) -> registry::RegKey { | |
self.0 | |
} | |
} | |
/// A generator that yields available versions of Visual Studio and can be used with | |
/// [`genawaiter::stack::let_gen_using`] macro to create a coroutine-based iterator. | |
/// | |
/// ## Examples | |
/// | |
/// ```rust | |
/// use genawaiter::stack::let_gen_using; | |
/// use vcredist::{VSRegKey, available_vs_versions_gen}; | |
/// | |
/// fn main() -> Result<(), registry::Error> { | |
/// let regkey = VSRegKey::open()?; | |
/// let_gen_using!(gen, |co| async move { available_vs_versions_gen(®key, co).await }); | |
/// for version in gen { | |
/// println!("Found Visual Studio version: {:?}", version); | |
/// } | |
/// Ok(()) | |
/// } | |
/// ``` | |
/// | |
/// Note that in the example above `regkey` gets captured by the closure. In order to mutably borrow or take ownership of `regkey` after the iteration, | |
/// you have write the code slightly differently. | |
/// | |
/// The generator must be dropped before the non-shared use of `regkey` and it must capture only the shared reference to the `regkey` instead of the owned value. | |
/// | |
/// The reason why the generator must be dropped prior to that is that even if it **borrows** the `regkey`, the captured shared reference is dropped in the drop implementation of the generator, | |
/// which extends the borrow of `regkey` to the end of the scope where the generator is defined. | |
/// | |
/// ```rust | |
/// use genawaiter::stack::let_gen_using; | |
/// use vcredist::{VSRegKey, available_vs_versions_gen}; | |
/// | |
/// fn main() -> Result<(), registry::Error> { | |
/// let regkey = VSRegKey::open()?; | |
/// { | |
/// let regkey_ref = ®key; | |
/// let_gen_using!(gen, |co| async move { available_vs_versions_gen(regkey_ref, co).await }); | |
/// for version in gen { | |
/// println!("Found Visual Studio version: {:?}", version); | |
/// } | |
/// } | |
/// let _inner = regkey.into_inner(); | |
/// Ok(()) | |
/// } | |
/// ``` | |
/// | |
// TODO: find a way to generalize this function over the couroutine type if genawaiter::core becomes stable/public | |
pub async fn available_vs_versions_gen( | |
regkey: &VSRegKey, | |
co: genawaiter::stack::Co<'_, Result<VSVersion, registry::iter::keys::Error>>, | |
) { | |
for subkey in regkey.0.keys() { | |
let version: Result<String, _> = subkey.map(|k| k.to_string()); | |
let version: String = match version { | |
Err(e) => { | |
co.yield_(Err(e)).await; | |
continue; | |
} | |
Ok(v) => v, | |
}; | |
if version.contains(|c: char| c != '.' && !c.is_numeric()) { | |
continue; | |
}; | |
co.yield_(Ok(VSVersion(version))).await; | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
#[test] | |
fn it_works() { | |
use super::{available_vs_versions_gen, VSRegKey}; | |
use genawaiter::stack::let_gen_using; | |
fn main() -> Result<(), registry::Error> { | |
let regkey = VSRegKey::open()?; | |
{ | |
let regkey_ref = ®key; | |
let_gen_using!(gen, |co| async move { | |
available_vs_versions_gen(regkey_ref, co).await | |
}); | |
for version in gen { | |
println!("Found Visual Studio version: {:?}", version); | |
} | |
} | |
let _inner = regkey.into_inner(); | |
Ok(()) | |
} | |
main().unwrap(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment