• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moonbitlang / x / 867

18 Jun 2026 06:38AM UTC coverage: 88.523% (+1.7%) from 86.827%
867

push

github

myfreess
path: document Node-compatible dispatch

2553 of 2884 relevant lines covered (88.52%)

338.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.93
/path/win32/win_path.mbt
1
// Copyright 2025 International Digital Economy Academy
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
///|
16
/// [Microsoft Naming a Volume](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-volume)
17
/// [Microsoft Naming Files, Paths, and Namespaces](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file)
18
/// [Microsoft Maximum Path Length Limitation](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation)
19
priv struct WinPath {
20
  prefix : WinPrefix
21
  trailing_separator : Bool
22
  components : Array[StringView]
23
} derive(ToJson, Hash, Eq)
24

25
///|
26
/// 
27
/// #### Verbatim Prefix
28
/// 
29
/// refer to [Microsoft Win32 File Namespaces](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-file-namespaces)
30
/// > For file I/O,
31
/// > the "\\?\" prefix to a path string tells the Windows APIs to disable all string parsing and to send the string that follows it straight to the file system.
32
/// 
33
/// #### Windows Encoding 
34
/// 
35
/// refer to [Microsoft Path Unicode Normalization](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation)
36
/// 
37
/// > There is no need to perform any Unicode normalization on path and file name strings for use by the Windows file I/O API functions 
38
/// > because the file system treats path and file names as an opaque sequence of WCHARs.
39
/// > Any normalization that your application requires should be performed with this in mind, 
40
/// > external of any calls to related Windows file I/O API functions.
41
/// 
42
/// #### Relative Paths Cannot use Verbatim Prefix
43
/// 
44
/// refer to [Microsoft Verbatim restriction](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation)
45
/// 
46
/// > Because you cannot use the "\\?\" prefix with a relative path, 
47
/// > relative paths are always limited to a total of MAX_PATH characters.
48
/// 
49
priv enum WinPrefix {
50
  /// Syntax: `\`
51
  ///
52
  /// Example: `\Users\username\Documents\`
53
  Root
54
  /// Syntax: `\\?\<SYMLINK>\` 
55
  ///
56
  /// Example: `\\?\GLOBALROOT\`
57
  VerbatimSymlink(symlink~ : String)
58
  /// Syntax: `\\?\UNC\<SERVER>\<SHARE>\`
59
  ///
60
  /// Example: `\\?\UNC\server\share\`
61
  VerbatimUNC(hostname~ : String, shared_folder~ : String)
62
  /// Syntax: `\\?\<L>:\`
63
  ///
64
  /// Example: `\\?\C:\`
65
  VerbatimVolumeLetterRoot(Char)
66
  /// Syntax: `\\?\Volume{<GUID>}`
67
  ///
68
  /// Example: `\\?\Volume{26a21bda-a627-11d7-9931-806e6f6e6963}`
69
  ///
70
  /// Warning: this letter is case-insensitive.
71
  ///
72
  /// [Microsoft Enumerating Volume GUID Paths](https://learn.microsoft.com/en-us/windows/win32/fileio/enumerating-unique-volume-names)
73
  VerbatimVolumeGUID(String)
74
  /// Syntax: `\\.\<DEVICE>\`
75
  ///
76
  /// Example: `\\.\COM56\`
77
  ///
78
  /// [Microsoft Win32 Device Namespaces](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#win32-device-namespaces)
79
  DeviceNS(device~ : String)
80
  /// Syntax: `\\<SERVER>\<SHARE>\`
81
  ///
82
  /// Example: `\\server\share\`
83
  UNC(hostname~ : String, shared_folder~ : String)
84
  /// Syntax: `<L>:\`
85
  ///
86
  /// Example: `C:\`
87
  ///
88
  /// Warning: this letter is case-insensitive.
89
  VolumeLetterRoot(Char)
90
  /// Syntax: `<L>:<rest_of_path>`
91
  ///
92
  /// Example: `C:main.mbt`
93
  ///
94
  /// 
95
  /// Warning: this letter is case-insensitive.
96
  VolumeLetter(Char)
97
  None
98
} derive(ToJson, Hash, Eq)
99

100
/// In order to make code more clean,
101
/// so we have to define many string constants to avoid escape sequences.
102

103
///|
104
const VerbatimPrefix : String =
105
  #|\\?\
106

107
///|
108
const VerbatimUncPrefix : String =
109
  #|\\?\UNC\
110

111
///|
112
const ColonBackslash : String =
113
  #|:\
114

115
///|
116
const VolumePrefix : String =
117
  #|\\?\Volume{
118

119
///|
120
const VolumeSuffix : String =
121
  #|}
122

123
///|
124
const DevicePrefix : String =
125
  #|\\.\
126

127
///|
128
const UncPrefix : String =
129
  #|\\
130

131
///|
132
const BackSlash : Char = '\\'
133

134
///|
135
impl Show for WinPrefix with fn output(self, logger) {
136
  match self {
48✔
137
    Root => logger.write_char(BackSlash)
2✔
138
    VerbatimSymlink(symlink~) => {
×
139
      logger.write_string(VerbatimPrefix)
×
140
      logger.write_string(symlink)
×
141
      logger.write_char(BackSlash)
×
142
    }
143
    VerbatimUNC(hostname~, shared_folder~) => {
×
144
      logger.write_string(VerbatimUncPrefix)
×
145
      logger.write_string(hostname)
×
146
      logger.write_char(BackSlash)
×
147
      logger.write_string(shared_folder)
×
148
      logger.write_char(BackSlash)
×
149
    }
150
    VerbatimVolumeLetterRoot(letter) => {
×
151
      logger.write_string(VerbatimPrefix)
×
152
      logger.write_char(letter)
×
153
      logger.write_string(ColonBackslash)
×
154
    }
155
    VerbatimVolumeGUID(guid) => {
×
156
      logger.write_string(VolumePrefix)
×
157
      logger.write_string(guid)
×
158
      logger.write_string(VolumeSuffix)
×
159
    }
160
    DeviceNS(device~) => {
×
161
      logger.write_string(DevicePrefix)
×
162
      logger.write_string(device)
×
163
      logger.write_char(BackSlash)
×
164
    }
165
    UNC(hostname~, shared_folder~) => {
2✔
166
      logger.write_string(UncPrefix)
2✔
167
      logger.write_string(hostname)
2✔
168
      logger.write_char(BackSlash)
2✔
169
      logger.write_string(shared_folder)
2✔
170
      logger.write_char(BackSlash)
2✔
171
    }
172
    VolumeLetterRoot(letter) => {
44✔
173
      logger.write_char(letter)
44✔
174
      logger.write_string(ColonBackslash)
44✔
175
    }
176
    VolumeLetter(letter) => {
×
177
      logger.write_char(letter)
×
178
      logger.write_string(":")
×
179
    }
180
    None => ()
×
181
  }
182
}
183

184
///|
185
fn WinPath::output(self : WinPath, logger : &Logger) -> Unit {
186
  let { prefix, trailing_separator, components } = self
243✔
187
  let mut prefix_ends_with_sep = false
188
  match prefix {
243✔
189
    Root => {
21✔
190
      logger.write_char(BackSlash)
21✔
191
      prefix_ends_with_sep = true
192
    }
193
    VerbatimSymlink(symlink~) => {
7✔
194
      logger.write_string(VerbatimPrefix)
7✔
195
      logger.write_string(symlink)
7✔
196
    }
197
    VerbatimUNC(hostname~, shared_folder~) => {
6✔
198
      logger.write_string(VerbatimUncPrefix)
6✔
199
      logger.write_string(hostname)
6✔
200
      logger.write_char(BackSlash)
6✔
201
      logger.write_string(shared_folder)
6✔
202
    }
203
    VerbatimVolumeLetterRoot(letter) => {
6✔
204
      logger.write_string(VerbatimPrefix)
6✔
205
      logger.write_char(letter)
6✔
206
      logger.write_string(ColonBackslash)
6✔
207
      prefix_ends_with_sep = true
208
    }
209
    VerbatimVolumeGUID(guid) => {
×
210
      logger.write_string(VolumePrefix)
×
211
      logger.write_string(guid)
×
212
      logger.write_string(VolumeSuffix)
×
213
    }
214
    DeviceNS(device~) => {
4✔
215
      logger.write_string(DevicePrefix)
4✔
216
      logger.write_string(device)
4✔
217
    }
218
    UNC(hostname~, shared_folder~) => {
14✔
219
      logger.write_string(UncPrefix)
14✔
220
      logger.write_string(hostname)
14✔
221
      logger.write_char(BackSlash)
14✔
222
      logger.write_string(shared_folder)
14✔
223
      logger.write_char(BackSlash)
14✔
224
      prefix_ends_with_sep = true
225
    }
226
    VolumeLetterRoot(letter) => {
95✔
227
      logger.write_char(letter)
95✔
228
      logger.write_string(ColonBackslash)
95✔
229
      prefix_ends_with_sep = true
230
    }
231
    VolumeLetter(letter) => {
8✔
232
      logger.write_char(letter)
8✔
233
      logger.write_string(":")
8✔
234
    }
235
    None => ()
82✔
236
  }
237
  match components {
243✔
238
    [] =>
239
      match prefix {
32✔
240
        None | VolumeLetter(_) =>
241
          if trailing_separator {
10✔
242
            logger.write_string(".\\")
4✔
243
          } else {
244
            logger.write_char('.')
6✔
245
          }
246
        VerbatimSymlink(_)
247
        | VerbatimUNC(_)
248
        | VerbatimVolumeGUID(_)
249
        | DeviceNS(_) => if trailing_separator { logger.write_char(BackSlash) }
2✔
250
        _ => ()
16✔
251
      }
252
    [x, .. xs] => {
211✔
253
      if !prefix_ends_with_sep &&
254
        !(prefix is None) &&
255
        !(prefix is VolumeLetter(_)) {
256
        logger.write_char(BackSlash)
11✔
257
      }
258
      logger.write_view(x)
211✔
259
      for component in xs {
260
        logger.write_char(BackSlash)
230✔
261
        logger.write_view(component)
230✔
262
      }
263
      if trailing_separator {
264
        logger.write_char(BackSlash)
28✔
265
      }
266
    }
267
  }
268
}
269

270
///|
271
impl Show for WinPath with fn output(self, logger) {
272
  WinPath::output(self, logger)
243✔
273
}
274

275
///|
276
fn is_win_sep_at_view(path : StringView, index : Int) -> Bool {
277
  match path.get_char(index) {
6,381✔
278
    Some(ch) => is_win_sep(ch)
6,381✔
279
    _ => false
×
280
  }
281
}
282

283
///|
284
fn has_win_drive_view(path : StringView, start : Int) -> Bool {
285
  if start + 1 >= path.length() || path.get_char(start + 1) != Some(':') {
301✔
286
    false
98✔
287
  } else {
288
    match path.get_char(start) {
212✔
289
      Some(ch) => is_ascii_alpha(ch)
212✔
290
      _ => false
×
291
    }
292
  }
293
}
294

295
///|
296
fn skip_win_separators_view(path : StringView, start : Int) -> Int {
297
  let mut index = start
819✔
298
  while index < path.length() && is_win_sep_at_view(path, index) {
1,616✔
299
    index += 1
858✔
300
  }
301
  index
302
}
303

304
///|
305
fn find_next_win_sep_view(path : StringView, start : Int) -> Int? {
306
  for i = start; i < path.length(); i = i + 1 {
81✔
307
    if is_win_sep_at_view(path, i) {
494✔
308
      return Some(i)
75✔
309
    }
310
  }
311
  None
312
}
313

314
///|
315
fn find_win_char_view(path : StringView, start : Int, target : Char) -> Int? {
316
  for i = start; i < path.length(); i = i + 1 {
×
317
    if path.get_char(i) == Some(target) {
×
318
      return Some(i)
×
319
    }
320
  }
321
  None
322
}
323

324
///|
325
fn push_windows_component(
326
  components : Array[StringView],
327
  component : StringView,
328
  allow_above_root~ : Bool,
329
) -> Unit {
330
  match component {
789✔
331
    "." => ()
37✔
332
    ".." =>
333
      match components.pop() {
61✔
334
        Some("..") => {
×
335
          components.push("..")
×
336
          if allow_above_root {
337
            components.push("..")
×
338
          }
339
        }
340
        None => if allow_above_root { components.push("..") }
8✔
341
        Some(_) => ()
47✔
342
      }
343
    _ => components.push(component)
691✔
344
  }
345
}
346

347
///|
348
fn parse_windows_components(
349
  path : StringView,
350
  start : Int,
351
  allow_above_root~ : Bool,
352
) -> Array[StringView] {
353
  let components : Array[StringView] = []
341✔
354
  let mut component_start = start
355
  let mut index = start
356
  while index <= path.length() {
3,488✔
357
    if index == path.length() || is_win_sep_at_view(path, index) {
3,147✔
358
      if component_start < index {
850✔
359
        push_windows_component(
789✔
360
          components,
361
          path[component_start:index],
362
          allow_above_root~,
363
        )
364
      }
365
      if index == path.length() {
850✔
366
        break
341✔
367
      }
368
      index = skip_win_separators_view(path, index)
509✔
369
      component_start = index
370
    } else {
371
      index += 1
2,638✔
372
    }
373
  }
374
  components
375
}
376

377
///|
378
fn parse_verbatim_prefixed_path(
379
  path : StringView,
380
  trailing_separator : Bool,
381
) -> WinPath? {
382
  guard path.length() >= 4 && path.get_char(2) == Some('?') else { return None }
30✔
383
  let marker_end = 4
25✔
384
  guard is_win_sep_at_view(path, 3) else { return None }
25✔
385
  if path.length() >= marker_end + 4 &&
25✔
386
    path[marker_end:marker_end + 3].equal_ignore_ascii_case("UNC") &&
22✔
387
    is_win_sep_at_view(path, marker_end + 3) {
12✔
388
    let hostname_start = skip_win_separators_view(path, marker_end + 3)
12✔
389
    match find_next_win_sep_view(path, hostname_start) {
12✔
390
      Some(hostname_end) => {
12✔
391
        let share_start = skip_win_separators_view(path, hostname_end)
12✔
392
        guard share_start < path.length() else {
12✔
393
          return Some({
4✔
394
            prefix: VerbatimSymlink(symlink="UNC"),
395
            trailing_separator,
396
            components: [path[hostname_start:hostname_end]],
397
          })
398
        }
399
        let share_end = match find_next_win_sep_view(path, share_start) {
8✔
400
          Some(index) => index
7✔
401
          _ => path.length()
1✔
402
        }
403
        let component_start = if share_end < path.length() {
8✔
404
          skip_win_separators_view(path, share_end)
7✔
405
        } else {
406
          path.length()
1✔
407
        }
408
        let components = parse_windows_components(
8✔
409
          path,
410
          component_start,
411
          allow_above_root=false,
412
        )
413
        return Some({
414
          prefix: VerbatimUNC(
415
            hostname=path[hostname_start:hostname_end].to_owned(),
8✔
416
            shared_folder=path[share_start:share_end].to_owned(),
8✔
417
          ),
418
          trailing_separator,
419
          components,
420
        })
421
      }
422
      _ => ()
×
423
    }
424
  }
425
  let part_start = marker_end
426
  guard part_start < path.length() else {
13✔
427
    return Some({
×
428
      prefix: VerbatimSymlink(symlink=""),
429
      trailing_separator,
430
      components: [],
431
    })
432
  }
433
  if path.length() > part_start + 7 &&
13✔
434
    path[part_start:part_start + 7] == "Volume{" {
435
    match find_win_char_view(path, part_start + 7, '}') {
×
436
      Some(guid_end) => {
×
437
        let component_start = if guid_end + 1 < path.length() {
×
438
          skip_win_separators_view(path, guid_end + 1)
×
439
        } else {
440
          path.length()
×
441
        }
442
        let components = parse_windows_components(
×
443
          path,
444
          component_start,
445
          allow_above_root=false,
446
        )
447
        return Some({
448
          prefix: VerbatimVolumeGUID(path[part_start + 7:guid_end].to_owned()),
×
449
          trailing_separator,
450
          components,
451
        })
452
      }
453
      _ => ()
×
454
    }
455
  }
456
  let part_end = match find_next_win_sep_view(path, part_start) {
13✔
457
    Some(index) => index
11✔
458
    _ => path.length()
2✔
459
  }
460
  if has_win_drive_view(path, part_start) &&
13✔
461
    part_start + 2 == part_end &&
462
    part_end < path.length() {
10✔
463
    let components = parse_windows_components(
9✔
464
      path,
465
      skip_win_separators_view(path, part_end),
9✔
466
      allow_above_root=false,
467
    )
468
    return Some({
469
      prefix: VerbatimVolumeLetterRoot(
470
        path[part_start:part_start + 1].get_char(0).unwrap(),
9✔
471
      ),
472
      trailing_separator,
473
      components,
474
    })
475
  }
476
  let components = if part_end < path.length() {
4✔
477
    parse_windows_components(
2✔
478
      path,
479
      skip_win_separators_view(path, part_end),
2✔
480
      allow_above_root=false,
481
    )
482
  } else {
483
    []
2✔
484
  }
485
  Some({
486
    prefix: VerbatimSymlink(symlink=path[part_start:part_end].to_owned()),
4✔
487
    trailing_separator,
488
    components,
489
  })
490
}
491

492
///|
493
fn parse_device_prefixed_path(
494
  path : StringView,
495
  trailing_separator : Bool,
496
) -> WinPath? {
497
  guard path.length() >= 4 && path.get_char(2) == Some('.') else { return None }
25✔
498
  guard is_win_sep_at_view(path, 3) else { return None }
5✔
499
  let part_start = 4
5✔
500
  guard part_start < path.length() else {
5✔
501
    return Some({
×
502
      prefix: DeviceNS(device=""),
503
      trailing_separator,
504
      components: [],
505
    })
506
  }
507
  let part_end = match find_next_win_sep_view(path, part_start) {
5✔
508
    Some(index) => index
4✔
509
    _ => path.length()
1✔
510
  }
511
  let components = if part_end < path.length() {
5✔
512
    parse_windows_components(
4✔
513
      path,
514
      skip_win_separators_view(path, part_end),
4✔
515
      allow_above_root=false,
516
    )
517
  } else {
518
    []
1✔
519
  }
520
  Some({
521
    prefix: DeviceNS(device=path[part_start:part_end].to_owned()),
5✔
522
    trailing_separator,
523
    components,
524
  })
525
}
526

527
///|
528
fn parse_unc_path(path : StringView, trailing_separator : Bool) -> WinPath? {
529
  guard path.length() <= 2 || !is_win_sep_at_view(path, 2) else { return None }
3✔
530
  let hostname_start = 2
22✔
531
  guard hostname_start < path.length() else { return None }
22✔
532
  match find_next_win_sep_view(path, hostname_start) {
22✔
533
    Some(hostname_end) => {
21✔
534
      let share_start = skip_win_separators_view(path, hostname_end)
21✔
535
      guard share_start < path.length() else { return None }
21✔
536
      let share_end = match find_next_win_sep_view(path, share_start) {
21✔
537
        Some(index) => index
20✔
538
        _ => path.length()
1✔
539
      }
540
      let component_start = if share_end < path.length() {
21✔
541
        skip_win_separators_view(path, share_end)
20✔
542
      } else {
543
        path.length()
1✔
544
      }
545
      let components = parse_windows_components(
21✔
546
        path,
547
        component_start,
548
        allow_above_root=false,
549
      )
550
      Some({
551
        prefix: UNC(
552
          hostname=path[hostname_start:hostname_end].to_owned(),
21✔
553
          shared_folder=path[share_start:share_end].to_owned(),
21✔
554
        ),
555
        trailing_separator,
556
        components,
557
      })
558
    }
559
    _ => None
1✔
560
  }
561
}
562

563
///|
564
fn WinPath::parse(path : StringView) -> WinPath {
565
  let trailing_separator = path.length() > 0 &&
348✔
566
    is_win_sep_at_view(path, path.length() - 1)
346✔
567
  if path.length() >= 2 &&
348✔
568
    is_win_sep_at_view(path, 0) &&
339✔
569
    is_win_sep_at_view(path, 1) {
77✔
570
    match parse_verbatim_prefixed_path(path, trailing_separator) {
55✔
571
      Some(parsed) => return parsed
25✔
572
      _ => ()
30✔
573
    }
574
    match parse_device_prefixed_path(path, trailing_separator) {
30✔
575
      Some(parsed) => return parsed
5✔
576
      _ => ()
25✔
577
    }
578
    match parse_unc_path(path, trailing_separator) {
25✔
579
      Some(parsed) => return parsed
21✔
580
      _ => ()
4✔
581
    }
582
  }
583
  if has_win_drive_view(path, 0) {
297✔
584
    let letter = path[0:1].get_char(0).unwrap()
202✔
585
    if path.length() > 2 && is_win_sep_at_view(path, 2) {
202✔
586
      let components = parse_windows_components(
194✔
587
        path,
588
        skip_win_separators_view(path, 2),
194✔
589
        allow_above_root=false,
590
      )
591
      return {
592
        prefix: VolumeLetterRoot(letter),
593
        trailing_separator,
594
        components,
595
      }
596
    }
597
    let components = parse_windows_components(path, 2, allow_above_root=true)
8✔
598
    return { prefix: VolumeLetter(letter), trailing_separator, components }
599
  }
600
  if path.length() > 0 && is_win_sep_at_view(path, 0) {
93✔
601
    let components = parse_windows_components(
29✔
602
      path,
603
      skip_win_separators_view(path, 0),
29✔
604
      allow_above_root=false,
605
    )
606
    return { prefix: Root, trailing_separator, components }
607
  }
608
  let components = parse_windows_components(path, 0, allow_above_root=true)
66✔
609
  { prefix: None, trailing_separator, components }
610
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc