2
2
using System . Threading . Tasks ;
3
3
using Flow . Launcher . Infrastructure . Logger ;
4
4
using Flow . Launcher . Infrastructure . UserSettings ;
5
+ using Flow . Launcher . Plugin ;
5
6
using Flow . Launcher . Plugin . SharedCommands ;
6
7
using MemoryPack ;
7
8
9
+ #nullable enable
10
+
8
11
namespace Flow . Launcher . Infrastructure . Storage
9
12
{
10
13
/// <summary>
11
14
/// Stroage object using binary data
12
15
/// Normally, it has better performance, but not readable
13
16
/// </summary>
14
17
/// <remarks>
15
- /// It utilize MemoryPack, which means the object must be MemoryPackSerializable <see href="https://github.com/Cysharp/MemoryPack"/>
18
+ /// It utilizes MemoryPack, which means the object must be MemoryPackSerializable <see href="https://github.com/Cysharp/MemoryPack"/>
16
19
/// </remarks>
17
- public class BinaryStorage < T >
20
+ public class BinaryStorage < T > : ISavable
18
21
{
22
+ protected T ? Data ;
23
+
19
24
public const string FileSuffix = ".cache" ;
20
25
26
+ protected string FilePath { get ; init ; } = null ! ;
27
+
28
+ protected string DirectoryPath { get ; init ; } = null ! ;
29
+
21
30
// Let the derived class to set the file path
22
- public BinaryStorage ( string filename , string directoryPath = null )
31
+ protected BinaryStorage ( )
23
32
{
24
- directoryPath ??= DataLocation . CacheDirectory ;
25
- FilesFolders . ValidateDirectory ( directoryPath ) ;
26
-
27
- FilePath = Path . Combine ( directoryPath , $ "{ filename } { FileSuffix } ") ;
28
33
}
29
34
30
- public string FilePath { get ; }
35
+ public BinaryStorage ( string filename )
36
+ {
37
+ DirectoryPath = DataLocation . CacheDirectory ;
38
+ FilesFolders . ValidateDirectory ( DirectoryPath ) ;
39
+
40
+ FilePath = Path . Combine ( DirectoryPath , $ "{ filename } { FileSuffix } ") ;
41
+ }
31
42
32
43
public async ValueTask < T > TryLoadAsync ( T defaultData )
33
44
{
45
+ if ( Data != null ) return Data ;
46
+
34
47
if ( File . Exists ( FilePath ) )
35
48
{
36
49
if ( new FileInfo ( FilePath ) . Length == 0 )
37
50
{
38
51
Log . Error ( $ "|BinaryStorage.TryLoad|Zero length cache file <{ FilePath } >") ;
39
- await SaveAsync ( defaultData ) ;
40
- return defaultData ;
52
+ Data = defaultData ;
53
+ await SaveAsync ( ) ;
41
54
}
42
55
43
56
await using var stream = new FileStream ( FilePath , FileMode . Open ) ;
44
- var d = await DeserializeAsync ( stream , defaultData ) ;
45
- return d ;
57
+ Data = await DeserializeAsync ( stream , defaultData ) ;
46
58
}
47
59
else
48
60
{
49
61
Log . Info ( "|BinaryStorage.TryLoad|Cache file not exist, load default data" ) ;
50
- await SaveAsync ( defaultData ) ;
51
- return defaultData ;
62
+ Data = defaultData ;
63
+ await SaveAsync ( ) ;
52
64
}
65
+
66
+ return Data ;
53
67
}
54
68
55
69
private static async ValueTask < T > DeserializeAsync ( Stream stream , T defaultData )
56
70
{
57
71
try
58
72
{
59
73
var t = await MemoryPackSerializer . DeserializeAsync < T > ( stream ) ;
60
- return t ;
74
+ return t ?? defaultData ;
61
75
}
62
76
catch ( System . Exception )
63
77
{
@@ -66,6 +80,27 @@ private static async ValueTask<T> DeserializeAsync(Stream stream, T defaultData)
66
80
}
67
81
}
68
82
83
+ public void Save ( )
84
+ {
85
+ var serialized = MemoryPackSerializer . Serialize ( Data ) ;
86
+
87
+ File . WriteAllBytes ( FilePath , serialized ) ;
88
+ }
89
+
90
+ public async ValueTask SaveAsync ( )
91
+ {
92
+ await SaveAsync ( Data . NonNull ( ) ) ;
93
+ }
94
+
95
+ // ImageCache need to convert data into concurrent dictionary for usage,
96
+ // so we would better to clear the data
97
+ public void ClearData ( )
98
+ {
99
+ Data = default ;
100
+ }
101
+
102
+ // ImageCache storages data in its class,
103
+ // so we need to pass it to SaveAsync
69
104
public async ValueTask SaveAsync ( T data )
70
105
{
71
106
await using var stream = new FileStream ( FilePath , FileMode . Create ) ;
0 commit comments