22using System . Threading . Tasks ;
33using Flow . Launcher . Infrastructure . Logger ;
44using Flow . Launcher . Infrastructure . UserSettings ;
5+ using Flow . Launcher . Plugin ;
56using Flow . Launcher . Plugin . SharedCommands ;
67using MemoryPack ;
78
9+ #nullable enable
10+
811namespace Flow . Launcher . Infrastructure . Storage
912{
1013 /// <summary>
1114 /// Stroage object using binary data
1215 /// Normally, it has better performance, but not readable
1316 /// </summary>
1417 /// <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"/>
1619 /// </remarks>
17- public class BinaryStorage < T >
20+ public class BinaryStorage < T > : ISavable
1821 {
22+ protected T ? Data ;
23+
1924 public const string FileSuffix = ".cache" ;
2025
26+ protected string FilePath { get ; init ; } = null ! ;
27+
28+ protected string DirectoryPath { get ; init ; } = null ! ;
29+
2130 // Let the derived class to set the file path
22- public BinaryStorage ( string filename , string directoryPath = null )
31+ protected BinaryStorage ( )
2332 {
24- directoryPath ??= DataLocation . CacheDirectory ;
25- FilesFolders . ValidateDirectory ( directoryPath ) ;
26-
27- FilePath = Path . Combine ( directoryPath , $ "{ filename } { FileSuffix } ") ;
2833 }
2934
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+ }
3142
3243 public async ValueTask < T > TryLoadAsync ( T defaultData )
3344 {
45+ if ( Data != null ) return Data ;
46+
3447 if ( File . Exists ( FilePath ) )
3548 {
3649 if ( new FileInfo ( FilePath ) . Length == 0 )
3750 {
3851 Log . Error ( $ "|BinaryStorage.TryLoad|Zero length cache file <{ FilePath } >") ;
39- await SaveAsync ( defaultData ) ;
40- return defaultData ;
52+ Data = defaultData ;
53+ await SaveAsync ( ) ;
4154 }
4255
4356 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 ) ;
4658 }
4759 else
4860 {
4961 Log . Info ( "|BinaryStorage.TryLoad|Cache file not exist, load default data" ) ;
50- await SaveAsync ( defaultData ) ;
51- return defaultData ;
62+ Data = defaultData ;
63+ await SaveAsync ( ) ;
5264 }
65+
66+ return Data ;
5367 }
5468
5569 private static async ValueTask < T > DeserializeAsync ( Stream stream , T defaultData )
5670 {
5771 try
5872 {
5973 var t = await MemoryPackSerializer . DeserializeAsync < T > ( stream ) ;
60- return t ;
74+ return t ?? defaultData ;
6175 }
6276 catch ( System . Exception )
6377 {
@@ -66,6 +80,27 @@ private static async ValueTask<T> DeserializeAsync(Stream stream, T defaultData)
6680 }
6781 }
6882
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
69104 public async ValueTask SaveAsync ( T data )
70105 {
71106 await using var stream = new FileStream ( FilePath , FileMode . Create ) ;
0 commit comments