| // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:io'; | |
| /// Result of polling a path. | |
| /// | |
| /// If it's a file, the result is combined from the file's "last modification" | |
| /// time and size, so that a change to either can be noticed as a change. | |
| /// | |
| /// If the path is not a file, [fileExists] return `false`. | |
| extension type PollResult._(int _value) { | |
| /// A [PollResult] with [fileExists] `false`. | |
| factory PollResult.notAFile() => PollResult._(0); | |
| static Future<PollResult> poll(String path) async { | |
| final stat = await FileStat.stat(path); | |
| if (stat.type != FileSystemEntityType.file) return PollResult.notAFile(); | |
| // Construct the poll result from the "last modified" time and size. | |
| // It should be very likely to change if either changes. Both are 64 bit | |
| // ints with the interesting bits in the low bits. Swap the 32 bit sections | |
| // of `microseconds` so the interesting bits don't clash, then XOR them. | |
| var microseconds = stat.modified.microsecondsSinceEpoch; | |
| microseconds = microseconds << 32 | microseconds >>> 32; | |
| return PollResult._(microseconds ^ stat.size); | |
| } | |
| /// Whether the path exists and is a file. | |
| bool get fileExists => _value != 0; | |
| } |