diff options
Diffstat (limited to 'src/Package.cpp')
-rw-r--r-- | src/Package.cpp | 168 |
1 files changed, 116 insertions, 52 deletions
diff --git a/src/Package.cpp b/src/Package.cpp index c1c00be..a2aaf52 100644 --- a/src/Package.cpp +++ b/src/Package.cpp @@ -9,6 +9,83 @@ static Document *packageList = nullptr; namespace sibs { + // TODO: Use containsPlatform in Conf.hpp instead? dont need a vector of string when we can use vector of enum + bool containsPlatform(const vector<string> &supportedPlatforms, const char *platform) + { + for(const string &supportedPlatform : supportedPlatforms) + { + if(strcmp(supportedPlatform.c_str(), platform) == 0 || strcmp(supportedPlatform.c_str(), "any") == 0) + return true; + } + + return false; + } + + Result<PackageMetadata> getPackageMetadata(Value::ConstObject jsonObj) + { + const auto &description = jsonObj["description"]; + if(!description.IsString()) return Result<PackageMetadata>::Err("Expected description to be a string"); + const auto &version = jsonObj["version"]; + if(!version.IsString()) return Result<PackageMetadata>::Err("Expected version to be a string"); + const auto &platforms = jsonObj["platforms"]; + if(!platforms.IsArray() || platforms.GetArray().Empty()) return Result<PackageMetadata>::Err("Expected platforms to be an array of strings"); + const auto &urls = jsonObj["urls"]; + if(!urls.IsArray() || urls.GetArray().Empty()) return Result<PackageMetadata>::Err("Expected urls to be an array of string"); + + PackageMetadata packageMetadata; + packageMetadata.description.assign(description.GetString(), description.GetStringLength()); + packageMetadata.version.assign(version.GetString(), version.GetStringLength()); + + const auto &platformsArray = platforms.GetArray(); + packageMetadata.platforms.reserve(platformsArray.Size()); + for(int i = 0; i < platformsArray.Size(); ++i) + { + const auto &platformElement = platformsArray[i]; + if(!platformElement.IsString()) + return Result<PackageMetadata>::Err("Expected platforms to only contain strings"); + packageMetadata.platforms.push_back(platformElement.GetString()); + } + + const auto &urlsArray = urls.GetArray(); + packageMetadata.urls.reserve(urlsArray.Size()); + for(int i = 0; i < urlsArray.Size(); ++i) + { + const auto &urlElement = urlsArray[i]; + if(!urlElement.IsString()) + return Result<PackageMetadata>::Err("Expected urls to only contain strings"); + packageMetadata.urls.push_back(urlElement.GetString()); + } + + return Result<PackageMetadata>::Ok(packageMetadata); + } + + Result<string> getPackageUrl(const PackageMetadata &packageMetadata, const char *packageName, const char *packageVersion, const char *platform) + { + if(strcmp(packageMetadata.version.c_str(), packageVersion) != 0) + { + string errMsg = "Package \""; + errMsg += packageName; + errMsg += "\" does not exist for version \""; + errMsg += packageVersion; + errMsg += "\""; + return Result<string>::Err(errMsg); + } + + if(!containsPlatform(packageMetadata.platforms, platform)) + { + string errMsg = "Package \""; + errMsg += packageName; + errMsg += "\" with version \""; + errMsg += packageVersion; + errMsg += "\" does not support platform \""; + errMsg += platform; + errMsg += "\""; + return Result<string>::Err(errMsg); + } + + return Result<string>::Ok(packageMetadata.urls[0]); + } + // TODO: Always downloading is fine right now because the package list is small. This should later be modified to use local cache. // The package file should be stored locally (at ~/.sibs/packages.json) and the version file should also be stored. // First we check if the version is incorrect and if it, we download the new packages.json file. @@ -40,75 +117,62 @@ namespace sibs return Result<Document*>::Ok(packageList); } - Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion) + Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion, const char *platform) { Result<Document*> packageList = Package::getPackageList("https://raw.githubusercontent.com/DEC05EBA/sibs_packages/master/packages.json"); if(!packageList) return Result<string>::Err(packageList); const Document &packageDoc = *packageList.unwrap(); - const Value &packageMetaData = packageDoc[packageName]; - if(!packageMetaData.IsObject()) - { - string errMsg = "No package with the name \""; - errMsg += packageName; - errMsg += "\" was found"; - return Result<string>::Err(errMsg); - } - - const Value &packageVersions = packageMetaData["versions"]; - if(!packageVersions.IsObject()) - { - string errMsg = "Package file is corrupt. "; - errMsg += packageName; - errMsg += ".versions is not a json object"; - return Result<string>::Err("errMsg"); - } - - const Value &package = packageVersions[packageVersion]; - if(!package.IsObject()) - { - string errMsg = "Package file is corrupt. "; - errMsg += packageName; - errMsg += ".versions."; - errMsg += packageVersion; - errMsg += " is not a json object"; - return Result<string>::Err(errMsg); - } - const Value &packageUrlsValue = package["urls"]; - if(!packageUrlsValue.IsArray()) + const Value &packageMetaDataJson = packageDoc[packageName]; + if(packageMetaDataJson.IsObject()) { - string errMsg = "Package file is corrupt. "; - errMsg += packageName; - errMsg += ".versions."; - errMsg += packageVersion; - errMsg += ".urls is not a json array"; - return Result<string>::Err(errMsg); + Result<PackageMetadata> packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(!packageMetadataResult) return Result<string>::Err(packageMetadataResult); + return ::sibs::getPackageUrl(packageMetadataResult.unwrap(), packageName, packageVersion, platform); } - - auto packageUrls = packageUrlsValue.GetArray(); - if(packageUrls.Empty()) + else if(packageMetaDataJson.IsArray()) { - string errMsg = "Package file is corrupt. "; + int i = 0; + for(const auto &packageData : packageMetaDataJson.GetArray()) + { + if(!packageData.IsObject()) + { + string errMsg = "Package file is corrupt. "; + errMsg += packageName; + errMsg += "["; + errMsg += to_string(i); + errMsg += "] is not an object"; + return Result<string>::Err(errMsg); + } + + Result<PackageMetadata> packageMetadataResult = getPackageMetadata(packageMetaDataJson.GetObject()); + if(packageMetadataResult) + { + Result<string> packageUrlResult = ::sibs::getPackageUrl(packageMetadataResult.unwrap(), packageName, packageVersion, platform); + if(packageUrlResult) + return packageUrlResult; + } + + ++i; + } + + string errMsg = "Package \""; errMsg += packageName; - errMsg += ".versions."; + errMsg += "\" with version \""; errMsg += packageVersion; - errMsg += ".urls is an empty json array"; + errMsg += "\" does not exist or does not exist for platform \""; + errMsg += platform; + errMsg += "\""; return Result<string>::Err(errMsg); } - - const Value &packageUrlValue = packageUrls[0]; - if(!packageUrlValue.IsString()) + else { - string errMsg = "Package file is corrupt. "; + string errMsg = "No package with the name \""; errMsg += packageName; - errMsg += ".versions."; - errMsg += packageVersion; - errMsg += ".urls[0] is not a string"; + errMsg += "\" was found"; return Result<string>::Err(errMsg); } - - return Result<std::string>::Ok(string(packageUrlValue.GetString(), packageUrlValue.GetStringLength())); } } |