using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Google.Protobuf;
using Google.Protobuf.Reflection;
using UnityEngine.Assertions;
namespace Ubisoft.Hotel.Cache
{
///
/// Cache driver that works with Protobuf messages. Converts IMessage types to json and viceversa
///
/// The data type managed by the cache driver. It must implement Google.Protobuf.IMessage.
public class GenericProtobufCacheDriver : AbstractCacheDriver where T : IMessage, new()
{
public string Filepath { get; private set; }
private MessageParser Parser { get; set; }
//private MessageParser Parser { get; set; }
private JsonFormatter Formatter { get; set; }
// TODO Consumers may need to add more message descriptors
public static async UniTask> CreateAsync(string rootFolder, string filePath, CacheSettings settings)//, MessageParser parser)
{
Assert.IsFalse(string.IsNullOrEmpty(rootFolder));
GenericProtobufCacheDriver driver = new GenericProtobufCacheDriver();
driver.RootFolder = rootFolder;
driver.Filepath = filePath;
// Instantiate T so that we can access its static members
var t = new T();
// Get a reference to MessageParser for Protobuf message deserialization
//driver.Parser = parser;
driver.Parser = (MessageParser)t.Descriptor.Parser;
//driver.Parser = new T().Descriptor.Parser;
// Initialize json formatter for Protobuf message serialization
//List descriptors = new List() { ContentServiceReflection.Descriptor };
//TypeRegistry typeRegistry = TypeRegistry.FromFiles(descriptors);
TypeRegistry typeRegistry = TypeRegistry.FromMessages(t.Descriptor);
driver.Formatter = new JsonFormatter(new JsonFormatter.Settings(true, typeRegistry));
// Initialize the driver
await driver.InitAsync(settings);
return driver;
}
private GenericProtobufCacheDriver()
{
// We can't enforce T to be a nullable type using a generic constraint (such constraint doesn't exist). So instead we do the following JIT compile-time check
if (default(T) != null)
{
throw new InvalidOperationException("GenericProtobufCacheDriver requires T to be a nullable type");
}
}
public async UniTask GetDataAsync(string filter = "")
{
string json = await CacheManager.GetDataAsync(GetRelativeCacheFilepath(Filepath), filter);
if (!string.IsNullOrEmpty(json))
{
return Parser.ParseJson(json);
}
return default(T); // This should always be null, since T is a nullable type
}
public async UniTask GetCrcAsync(string filter = "")
{
CacheFileMetadata metadata = await CacheManager.GetFileMetadataAsync(GetRelativeCacheFilepath(Filepath), filter);
if (metadata != null)
{
return metadata.Crc;
}
return null;
}
public async UniTask SaveDataAsync(T data, string filter = "")
{
string json = Formatter.Format(data);
await CacheManager.UpdateDataAsync(Filepath, json, filter);
}
public void InvalidateData(string filter = "")
{
CacheManager.InvalidateFile(GetRelativeCacheFilepath(Filepath), filter);
}
}
}