1#[derive(Default, Debug, Clone)]
7pub struct AgentNameAndVersionSet(HashSet<(AgentName, Version)>);
8
9impl Deref for AgentNameAndVersionSet
10{
11 type Target = HashSet<(AgentName, Version)>;
12
13 #[inline(always)]
15 fn deref(&self) -> &Self::Target
16 {
17 &self.0
18 }
19}
20
21impl AgentNameAndVersionSet
22{
23 #[inline(always)]
25 pub fn support_for_a_feature<'a, F: FnMut(&Agent, &Version, &Support)>(&self, can_i_use: &'a CanIUse, feature_name: &'a FeatureName, mut support_user: F)
26 {
27 self.feature(can_i_use, feature_name, |agent, version, support|
28 {
29 if let Some(Some(ref support)) = support
30 {
31 support_user(agent, version, support)
32 }
33 })
34 }
35
36 #[inline(always)]
38 pub fn feature<'a, F: FnMut(&Agent, &Version, Option<Option<Support>>)>(&self, can_i_use: &'a CanIUse, feature_name: &'a FeatureName, mut feature_implementation_user: F)
39 {
40 if let Some(feature) = feature_name.feature(can_i_use)
41 {
42 for &(ref agent_name, ref version) in self.0.iter()
43 {
44 if let Some(agent) = agent_name.agent(can_i_use)
45 {
46 feature_implementation_user(&agent, version, feature.implementation(agent_name, version));
47 }
48 }
49 }
50 }
51
52 #[inline(always)]
54 pub fn new(values: HashSet<(AgentName, Version)>) -> Self
55 {
56 AgentNameAndVersionSet(values)
57 }
58
59 #[inline(always)]
61 pub fn a_sensible_set_of_choices_for_an_international_website_in_multiple_languages(can_i_use: &CanIUse, maximum_release_age_from_can_i_use_database_last_updated: Duration, minimum_usage_threshold: UsagePercentage, regional_usages: &[&RegionalUsage]) -> Self
62 {
63 let obsolete_browsers_still_in_use = Self::obsolete_browsers_still_in_use();
64 let browsers_which_underwent_a_major_change_of_rendering_engine = Self::browsers_which_underwent_a_major_change_of_rendering_engine();
65 let automatically_updated_browsers = Self::automatically_updated_browsers();
66 let long_term_releases_of_automatically_updated_browsers = Self::long_term_releases_of_automatically_updated_browsers();
67 let regionally_significant_occasionally_automatically_updated_browsers = Self::regionally_significant_occasionally_automatically_updated_browsers();
68
69 Self::sensible_choices(can_i_use, maximum_release_age_from_can_i_use_database_last_updated, minimum_usage_threshold, regional_usages, obsolete_browsers_still_in_use, browsers_which_underwent_a_major_change_of_rendering_engine, automatically_updated_browsers, long_term_releases_of_automatically_updated_browsers, regionally_significant_occasionally_automatically_updated_browsers)
70 }
71
72 pub fn sensible_choices(can_i_use: &CanIUse, maximum_release_age_from_can_i_use_database_last_updated: Duration, minimum_usage_threshold: UsagePercentage, regional_usages: &[&RegionalUsage], obsolete_browsers_still_in_use: Self, browsers_which_underwent_a_major_change_of_rendering_engine: Self, automatically_updated_browsers: HashSet<AgentName>, long_term_releases_of_automatically_updated_browsers: HashSet<AgentName>, regionally_significant_occasionally_automatically_updated_browsers: HashSet<AgentName>) -> Self
78 {
79 let mut result = Self::default();
80
81 for regional_usage in regional_usages.iter()
82 {
83 result.add_just_these_versions_by_usage_percentage(&obsolete_browsers_still_in_use, regional_usage, minimum_usage_threshold);
84 result.add_just_these_versions_by_usage_percentage(&browsers_which_underwent_a_major_change_of_rendering_engine, regional_usage, minimum_usage_threshold);
85 result.add_any_current_or_older_version_by_usage_percentage(®ionally_significant_occasionally_automatically_updated_browsers, regional_usage, minimum_usage_threshold, can_i_use);
86 }
87
88 let oldest_release_date = match can_i_use.last_updated().checked_sub_signed(maximum_release_age_from_can_i_use_database_last_updated)
89 {
90 Some(oldest_release_date) => oldest_release_date,
91 None => Utc.timestamp(0, 0),
92 };
93
94 result.add_any_current_or_older_version_by_age(&automatically_updated_browsers, oldest_release_date, can_i_use);
95 result.add_any_current_or_older_version_by_age(&long_term_releases_of_automatically_updated_browsers, oldest_release_date, can_i_use);
96
97 result
98 }
99
100 pub fn add_just_these_versions_by_usage_percentage(&mut self, obsolete_or_changed_rendering_engine: &Self, regional_usage: &RegionalUsage, minimum_usage_threshold: UsagePercentage)
102 {
103 for &(ref agent_name, ref version) in obsolete_or_changed_rendering_engine.0.iter()
104 {
105 if let Some(Some(&Some(actual_usage))) = regional_usage.usage_of_version(agent_name, version)
106 {
107 if actual_usage >= minimum_usage_threshold
108 {
109 self.0.insert((agent_name.clone(), version.clone()));
110 }
111 }
112 }
113 }
114
115 pub fn add_any_current_or_older_version_by_usage_percentage(&mut self, agent_names: &HashSet<AgentName>, regional_usage: &RegionalUsage, minimum_usage_threshold: UsagePercentage, can_i_use: &CanIUse)
117 {
118 for agent_name in agent_names.iter()
119 {
120 if let Some(agent) = agent_name.agent(can_i_use)
121 {
122 agent.version_details_for_current_and_older_versions().for_each(|(version, _version_detail)|
123 {
124 if let Some(Some(&Some(actual_usage))) = regional_usage.usage_of_version(agent_name, version)
125 {
126 if actual_usage >= minimum_usage_threshold
127 {
128 self.0.insert((agent_name.clone(), version.clone()));
129 }
130 }
131 })
132 }
133 }
134 }
135
136 pub fn add_any_current_or_older_version_by_age(&mut self, agent_names: &HashSet<AgentName>, oldest_release_date: DateTime<Utc>, can_i_use: &CanIUse)
138 {
139 for agent_name in agent_names.iter()
140 {
141 if let Some(agent) = agent_name.agent(can_i_use)
142 {
143 agent.version_details_for_current_and_older_versions().for_each(|(version, version_detail)|
144 {
145 if let Some(release_date) = version_detail.release_date()
146 {
147 if release_date >= oldest_release_date
148 {
149 self.0.insert((agent_name.clone(), version.clone()));
150 }
151 }
152 })
153 }
154 }
155 }
156
157 #[inline(always)]
162 pub fn obsolete_browsers_still_in_use() -> Self
163 {
164 use self::AgentName::*;
165
166 AgentNameAndVersionSet
167 (
168 hashset!
169 (
170 (MicrosoftInternetExplorer, Version::major(11)),
171 (Blackberry, Version::major(10)),
172 (MicrosoftInternetExplorerMobile, Version::major(11)),
173 )
174 )
175 }
176
177 #[inline(always)]
182 pub fn browsers_which_underwent_a_major_change_of_rendering_engine() -> Self
183 {
184 use self::AgentName::*;
185
186 AgentNameAndVersionSet
187 (
188 hashset!
189 (
190 (Opera, Version::major_minor(12, 1)),
191 (GoogleAndroidBrowserAndWebComponent, Version::major_minor_revision(4, 4, 4)),
192 (OperaMobile, Version::major_minor(12, 1)),
193 )
194 )
195 }
196
197 #[inline(always)]
202 pub fn automatically_updated_browsers() -> HashSet<AgentName>
203 {
204 use self::AgentName::*;
205
206 hashset!
207 (
208 MicrosoftEdge,
209 MozillaFirefox,
210 GoogleChrome,
211 AppleSafari,
212 Opera,
213 AppleSafariIOs,
214 GoogleAndroidBrowserAndWebComponent,
215 OperaMobile,
216 GoogleChromeAndroid,
217 MozillaFirefoxAndroid,
218 )
219 }
220
221 #[inline(always)]
230 pub fn long_term_releases_of_automatically_updated_browsers() -> HashSet<AgentName>
231 {
232 use self::AgentName::*;
233
234 hashset!
235 (
236 MozillaFirefox,
237 )
238 }
239
240 #[inline(always)]
247 pub fn regionally_significant_occasionally_automatically_updated_browsers() -> HashSet<AgentName>
248 {
249 use self::AgentName::*;
250
251 hashset!
252 (
253 UcBrowserAndroid,
254 SamsungBrowserAndroid,
255 QqBrowserAndroid,
256 BaiduBrowserAndroid,
257 )
258 }
259}