1 module served.io.nothrow_fs;
2 
3 public import fs = std.file;
4 
5 import std.experimental.logger;
6 import std.utf;
7 
8 auto tryDirEntries(string path, fs.SpanMode mode, bool followSymlink = true)
9 {
10 	try
11 	{
12 		return nothrowDirIterator(fs.dirEntries(path, mode, followSymlink));
13 	}
14 	catch (fs.FileException)
15 	{
16 		return typeof(return).init;
17 	}
18 }
19 
20 auto tryDirEntries(string path, string pattern, fs.SpanMode mode, bool followSymlink = true)
21 {
22 	try
23 	{
24 		return nothrowDirIterator(fs.dirEntries(path, pattern, mode, followSymlink));
25 	}
26 	catch (fs.FileException)
27 	{
28 		return typeof(return).init;
29 	}
30 }
31 
32 private NothrowDirIterator!T nothrowDirIterator(T)(T range)
33 {
34 	return NothrowDirIterator!T(range);
35 }
36 
37 private struct NothrowDirIterator(T)
38 {
39 @safe:
40 	T base;
41 	bool crashed;
42 
43 public:
44 	@property bool empty()
45 	{
46 		try
47 		{
48 			return crashed || base.empty;
49 		}
50 		catch (fs.FileException)
51 		{
52 			return crashed = true;
53 		}
54 		catch (UTFException e)
55 		{
56 			(() @trusted => error("Got malformed UTF string in dirIterator, something has probably corrupted. ", e))();
57 			return crashed = true;
58 		}
59 	}
60 
61 	@property auto front()
62 	{
63 		try
64 		{
65 			return base.front;
66 		}
67 		catch (fs.FileException)
68 		{
69 			crashed = true;
70 		}
71 		catch (UTFException e)
72 		{
73 			(() @trusted => error("Got malformed UTF string in dirIterator, something has probably corrupted. ", e))();
74 			crashed = true;
75 		}
76 		return fs.DirEntry.init;
77 	}
78 
79 	void popFront()
80 	{
81 		try
82 		{
83 			base.popFront();
84 		}
85 		catch (fs.FileException)
86 		{
87 			crashed = true;
88 		}
89 		catch (UTFException e)
90 		{
91 			(() @trusted => error("Got malformed UTF string in dirIterator, something has probably corrupted. ", e))();
92 			crashed = true;
93 		}
94 	}
95 }