@@ -46,9 +46,26 @@ pub struct EnvKey {
46
46
utf16 : Vec < u16 > ,
47
47
}
48
48
49
- // Windows environment variables preserve their case but comparisons use
50
- // simplified case folding. So we call `CompareStringOrdinal` to get the OS to
51
- // perform the comparison.
49
+ // Comparing Windows environment variable keys[1] are behaviourally the
50
+ // composition of two operations[2]:
51
+ //
52
+ // 1. Case-fold both strings. This is done using a language-independent
53
+ // uppercase mapping that's unique to Windows (albeit based on data from an
54
+ // older Unicode spec). It only operates on individual UTF-16 code units so
55
+ // surrogates are left unchanged. This uppercase mapping can potentially change
56
+ // between Windows versions.
57
+ //
58
+ // 2. Perform an ordinal comparison of the strings. A comparison using ordinal
59
+ // is just a comparison based on the numerical value of each UTF-16 code unit[3].
60
+ //
61
+ // Because the case-folding mapping is unique to Windows and not guaranteed to
62
+ // be stable, we ask the OS to compare the strings for us. This is done by
63
+ // calling `CompareStringOrdinal`[4] with `bIgnoreCase` set to `TRUE`.
64
+ //
65
+ // [1] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#choosing-a-stringcomparison-member-for-your-method-call
66
+ // [2] https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices-strings#stringtoupper-and-stringtolower
67
+ // [3] https://docs.microsoft.com/en-us/dotnet/api/system.stringcomparison?view=net-5.0#System_StringComparison_Ordinal
68
+ // [4] https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal
52
69
impl Ord for EnvKey {
53
70
fn cmp ( & self , other : & Self ) -> cmp:: Ordering {
54
71
unsafe {
@@ -84,6 +101,8 @@ impl PartialEq for EnvKey {
84
101
}
85
102
}
86
103
104
+ // Environment variable keys should preserve their original case even though
105
+ // they are compared using a caseless string mapping.
87
106
impl From < OsString > for EnvKey {
88
107
fn from ( k : OsString ) -> Self {
89
108
EnvKey { utf16 : k. encode_wide ( ) . collect ( ) , os_string : k }
0 commit comments