blob: 8ac5ad212d82e60ae36e9113ce3da04bf5591252 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia_pkg_url.h"
// #include <re2/re2.h>
#include <regex>
#include <string>
#include <string_view>
namespace component {
// Subsitutue functions copied from fxl.
static std::string SubstituteWithArray(std::string_view format,
std::string_view* args,
size_t nargs);
std::string Substitute(std::string_view format, std::string_view arg0) {
std::array<std::string_view, 1> arr = {arg0};
return SubstituteWithArray(format, arr.data(), arr.size());
}
std::string Substitute(std::string_view format,
std::string_view arg0,
std::string_view arg1) {
std::array<std::string_view, 2> arr = {arg0, arg1};
return SubstituteWithArray(format, arr.data(), arr.size());
}
std::string Substitute(std::string_view format,
std::string_view arg0,
std::string_view arg1,
std::string_view arg2) {
std::array<std::string_view, 3> arr = {arg0, arg1, arg2};
return SubstituteWithArray(format, arr.data(), arr.size());
}
static const std::string kFuchsiaPkgPrefix = "fuchsia-pkg://";
// kFuchsiaPkgRexp has the following group matches:
// 1: user/domain/port/etc (everything after scheme, before path)
// 2: package name
// 3: package variant
// 4: package merkle-root hash
// 5: resource path
static const std::regex* kFuchsiaPkgRexp = std::regex(
"^fuchsia-pkg://([^/]+)/([^/#?]+)(?:/([^/"
"#?]+))?(?:\\?hash=([^&#]+))?(?:#(.+))?$");
// static
bool FuchsiaPkgUrl::IsFuchsiaPkgScheme(const std::string& url) {
return url.compare(0, kFuchsiaPkgPrefix.length(), kFuchsiaPkgPrefix) == 0;
}
std::string FuchsiaPkgUrl::GetDefaultComponentCmxPath() const {
return fxl::Substitute("meta/$0.cmx", package_name());
}
bool FuchsiaPkgUrl::Parse(const std::string& url) {
package_name_.clear();
resource_path_.clear();
// if (!re2::RE2::FullMatch(url, *kFuchsiaPkgRexp, &host_name_,
// &package_name_,
// &variant_, &hash_, &resource_path_)) {
// return false;
// }
char* cstr = new char[url.size()];
std::copy(url.begin(), url.end(), cstr);
std::cmatch cm;
bool full_match = std::regex_match(cstr, cm, kFuchsiaPkgRexp);
if (!full_match) {
return false;
}
host_name_ = cm[1];
package_name_ = cm[2];
variant_ = cm[3];
hash_ = cm[4];
resource_path_ = cm[5];
url_ = url;
if (variant_.empty()) {
// TODO(fxbug.dev/4002): Currently this defaults to "0" if not present, but
// variant will eventually be required in fuchsia-pkg URLs.
variant_ = "0";
}
return true;
}
bool FuchsiaPkgUrl::operator==(const FuchsiaPkgUrl& rhs) const {
return (this->host_name() == rhs.host_name() &&
this->package_name() == rhs.package_name() &&
this->variant() == rhs.variant() &&
this->resource_path() == rhs.resource_path() &&
this->hash() == rhs.hash());
}
std::string FuchsiaPkgUrl::pkgfs_dir_path() const {
return fxl::Substitute("/pkgfs/packages/$0/$1", package_name_, variant_);
}
std::string FuchsiaPkgUrl::package_path() const {
std::string query = "";
if (!hash_.empty()) {
query = fxl::Substitute("?hash=$0", hash_);
}
return fxl::Substitute("fuchsia-pkg://$0/$1/$2$3", host_name_, package_name_,
variant_, query);
}
const std::string& FuchsiaPkgUrl::ToString() const {
return url_;
}
} // namespace component