@@ -11,7 +11,7 @@ use relay_protocol::{Annotated, Empty, Value};
11
11
12
12
/// Environment.OSVersion (GetVersionEx) or RuntimeInformation.OSDescription on Windows
13
13
static OS_WINDOWS_REGEX1 : Lazy < Regex > = Lazy :: new ( || {
14
- Regex :: new ( r"^(Microsoft )?Windows (NT )?(?P<version>\d+\.\d+\.(?P<build_number>\d+)).*$" )
14
+ Regex :: new ( r"^(Microsoft\s+ )?Windows\s+ (NT\s+ )?(?P<version>\d+\.\d+\.(?P<build_number>\d+)).*$" )
15
15
. unwrap ( )
16
16
} ) ;
17
17
static OS_WINDOWS_REGEX2 : Lazy < Regex > = Lazy :: new ( || {
@@ -179,6 +179,28 @@ fn get_windows_version(description: &str) -> Option<(&str, &str)> {
179
179
Some ( ( version_name, build_number_str) )
180
180
}
181
181
182
+ /// Simple marketing names in the form `<OS> <version>`.
183
+ fn get_marketing_name ( description : & str ) -> Option < ( & str , & str ) > {
184
+ let ( name, version) = description. split_once ( ' ' ) ?;
185
+ let name = name. trim ( ) ;
186
+ let version = version. trim ( ) ;
187
+
188
+ // Validate if it looks like a reasonable name.
189
+ if name. bytes ( ) . any ( |c| !c. is_ascii_alphabetic ( ) ) {
190
+ return None ;
191
+ }
192
+
193
+ // Validate if it looks like a reasonable version.
194
+ if version
195
+ . bytes ( )
196
+ . any ( |c| !matches ! ( c, b'0' ..=b'9' | b'.' | b'-' ) )
197
+ {
198
+ return None ;
199
+ }
200
+
201
+ Some ( ( name, version) )
202
+ }
203
+
182
204
#[ allow( dead_code) ]
183
205
/// Returns the API version of an Android description.
184
206
///
@@ -221,20 +243,12 @@ fn normalize_os_context(os: &mut OsContext) {
221
243
. name ( "version" )
222
244
. map ( |m| m. as_str ( ) . to_owned ( ) )
223
245
. into ( ) ;
224
- os. build = captures
225
- . name ( "build" )
226
- . map ( |m| m. as_str ( ) . to_owned ( ) . into ( ) )
227
- . into ( ) ;
228
246
} else if let Some ( captures) = OS_IPADOS_REGEX . captures ( raw_description) {
229
247
os. name = "iPadOS" . to_owned ( ) . into ( ) ;
230
248
os. version = captures
231
249
. name ( "version" )
232
250
. map ( |m| m. as_str ( ) . to_owned ( ) )
233
251
. into ( ) ;
234
- os. build = captures
235
- . name ( "build" )
236
- . map ( |m| m. as_str ( ) . to_owned ( ) . into ( ) )
237
- . into ( ) ;
238
252
} else if let Some ( captures) = OS_LINUX_DISTRO_UNAME_REGEX . captures ( raw_description) {
239
253
os. name = captures. name ( "name" ) . map ( |m| m. as_str ( ) . to_owned ( ) ) . into ( ) ;
240
254
os. version = captures
@@ -259,6 +273,9 @@ fn normalize_os_context(os: &mut OsContext) {
259
273
. into ( ) ;
260
274
} else if raw_description == "Nintendo Switch" {
261
275
os. name = "Nintendo OS" . to_owned ( ) . into ( ) ;
276
+ } else if let Some ( ( name, version) ) = get_marketing_name ( raw_description) {
277
+ os. name = name. to_owned ( ) . into ( ) ;
278
+ os. version = version. to_owned ( ) . into ( ) ;
262
279
}
263
280
}
264
281
@@ -732,6 +749,17 @@ mod tests {
732
749
assert_eq ! ( Some ( "30" ) , get_android_api_version( description) ) ;
733
750
}
734
751
752
+ #[ test]
753
+ fn test_unreal_windows_os ( ) {
754
+ let mut os = OsContext {
755
+ raw_description : "Windows 10" . to_owned ( ) . into ( ) ,
756
+ ..OsContext :: default ( )
757
+ } ;
758
+ normalize_os_context ( & mut os) ;
759
+ assert_eq ! ( Some ( "Windows" ) , os. name. as_str( ) ) ;
760
+ assert_eq ! ( Some ( "10" ) , os. version. as_str( ) ) ;
761
+ }
762
+
735
763
#[ test]
736
764
fn test_linux_5_11 ( ) {
737
765
let mut os = OsContext {
0 commit comments