<commit_before>﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisualRust.Shared
{
    public class Environment
    {
        private const string MozillaPath = @"Software\Mozilla Foundation";
        private const string install = "InstallLocation";

        // I'm really torn between "default", "local", "native", "unspecified" and "any"
        public const string DefaultTarget = "default";

        /* 
         * If the target is "default" just return first location
         * Otherwise check for bin\rustlib\<target>
         */
        public static string FindInstallPath(string target)
        {
            return GetAllInstallPaths().Select(p => Path.Combine(p, "bin")).FirstOrDefault(p => CanActuallyBuildTarget(p, target));
        }

        public static IEnumerable<string> FindInstalledTargets()
        {
            return GetAllInstallPaths().SelectMany(SniffTargets);
        }

        private static IEnumerable<string> GetAllInstallPaths()
        {
            IEnumerable<string> installPaths = GetInstallRoots(RegistryHive.CurrentUser, RegistryView.Registry32)
                .Union(GetInstallRoots(RegistryHive.LocalMachine, RegistryView.Registry32));
            if(System.Environment.Is64BitOperatingSystem)
            {
                installPaths = installPaths
                    .Union(GetInstallRoots(RegistryHive.CurrentUser, RegistryView.Registry64))
                    .Union(GetInstallRoots(RegistryHive.LocalMachine, RegistryView.Registry64));
            }
            return installPaths;
        }

        private static IEnumerable<string> GetInstallRoots(RegistryHive hive, RegistryView view)
        {
            RegistryKey mozillaKey = RegistryKey.OpenBaseKey(hive, view).OpenSubKey(MozillaPath);
            if (mozillaKey == null)
                return new string[0];
            return mozillaKey
                .GetSubKeyNames()
                .Where(n => n.StartsWith("Rust", StringComparison.OrdinalIgnoreCase))
                .SelectMany(n => AllSubKeys(mozillaKey.OpenSubKey(n)))
                .Select(k => k.GetValue("InstallDir") as string)
                .Where(x => x != null);
        }

        private static IEnumerable<RegistryKey> AllSubKeys(RegistryKey key)
        {
            return key.GetSubKeyNames().Select(n => key.OpenSubKey(n));
        }

        private static bool CanActuallyBuildTarget(string binPath, string target)
        {
            if(String.Equals(DefaultTarget, target, StringComparison.OrdinalIgnoreCase))
                return true;<commit_msg>When searching for rust install paths prefer 64-bit paths on 64-bit OSes<commit_after>﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VisualRust.Shared
{
    public class Environment
    {
        private const string MozillaPath = @"Software\Mozilla Foundation";
        private const string install = "InstallLocation";

        // I'm really torn between "default", "local", "native", "unspecified" and "any"
        public const string DefaultTarget = "default";

        /* 
         * If the target is "default" just return first location
         * Otherwise check for bin\rustlib\<target>
         */
        public static string FindInstallPath(string target)
        {
            return GetAllInstallPaths().Select(p => Path.Combine(p, "bin")).FirstOrDefault(p => CanActuallyBuildTarget(p, target));
        }

        public static IEnumerable<string> FindInstalledTargets()
        {
            return GetAllInstallPaths().SelectMany(SniffTargets);
        }

        private static IEnumerable<string> GetAllInstallPaths()
        {
            IEnumerable<string> installPaths;
            if(System.Environment.Is64BitOperatingSystem)
            {
                installPaths = GetInstallRoots(RegistryHive.CurrentUser, RegistryView.Registry64)
                    .Union(GetInstallRoots(RegistryHive.LocalMachine, RegistryView.Registry64));
            }
            else
            {
                installPaths = new string[0];
            }
            return installPaths.Union(GetInstallRoots(RegistryHive.CurrentUser, RegistryView.Registry32))
                .Union(GetInstallRoots(RegistryHive.LocalMachine, RegistryView.Registry32));
        }

        private static IEnumerable<string> GetInstallRoots(RegistryHive hive, RegistryView view)
        {
            RegistryKey mozillaKey = RegistryKey.OpenBaseKey(hive, view).OpenSubKey(MozillaPath);
            if (mozillaKey == null)
                return new string[0];
            return mozillaKey
                .GetSubKeyNames()
                .Where(n => n.StartsWith("Rust", StringComparison.OrdinalIgnoreCase))
                .SelectMany(n => AllSubKeys(mozillaKey.OpenSubKey(n)))
                .Select(k => k.GetValue("InstallDir") as string)
                .Where(x => x != null);
        }

        private static IEnumerable<RegistryKey> AllSubKeys(RegistryKey key)
        {
            return key.GetSubKeyNames().Select(n => key.OpenSubKey(n));
        }

        private static bool CanActuallyBuildTarget(string binPath, string target)
        {
            if(String.Equals(DefaultTarget, target, StringComparison.OrdinalIgnoreCase))
                return true;
{'fraction_non_alphanumeric': 0.09165751920965971, 'fraction_numerical': 0.005671423344310282, 'mean_word_length': 2.408354114713217, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '645859', 'n_tokens_mistral': 1455, 'n_tokens_neox': 1367, 'n_words': 304}