refact: add quicktype

Signed-off-by: black-desk <me@black-desk.cn>
This commit is contained in:
black-desk 2023-11-16 11:34:26 +08:00 committed by kamiyadm
parent 85c46d0b77
commit e92e7b2b74
19 changed files with 1016 additions and 0 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "tools/quicktype"]
path = tools/quicktype
url = https://github.com/black-desk/quicktype.git

4
api/README.md Normal file
View File

@ -0,0 +1,4 @@
# linglong API
This diresctory contains files that describes the API of linglong,
which is used to generate code in this project.

View File

@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"remoteRepoEndpoint": {
"type": "string"
},
"remoteRepoName": {
"type": "string"
}
},
"required": [
"remoteRepoEndpoint",
"remoteRepoName"
]
}

View File

@ -0,0 +1,156 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"version": {
"type": "string"
},
"variables": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"package": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"kind": {
"type": "string"
},
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"id",
"kind",
"name",
"version",
"description"
]
},
"runtime": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"id"
]
},
"base": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"id"
]
},
"depends": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"version": {
"type": "string"
},
"type": {
"type": "string"
}
},
"required": [
"id"
]
}
},
"source": {
"type": "object",
"properties": {
"kind": {
"type": "string"
},
"url": {
"type": "string"
},
"digest": {
"type": "string"
},
"version": {
"type": "string"
},
"commit": {
"type": "string"
},
"patch": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"kind"
]
},
"build": {
"type": "object",
"properties": {
"kind": {
"type": "string"
},
"manual": {
"type": "object",
"properties": {
"configure": {
"type": "string"
},
"build": {
"type": "string"
},
"install": {
"type": "string"
}
}
}
},
"required": [
"kind"
]
}
},
"required": [
"version",
"package",
"source",
"build"
]
}

View File

@ -0,0 +1,32 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Config.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <nlohmann/json.hpp>
#include "linglong/builder/config/helper.hpp"
namespace linglong {
namespace builder {
namespace config {
using nlohmann::json;
struct Config {
std::string remoteRepoEndpoint;
std::string remoteRepoName;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,41 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Generators.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <nlohmann/json.hpp>
#include "linglong/builder/config/helper.hpp"
#include "linglong/builder/config/Config.hpp"
namespace linglong {
namespace builder {
namespace config {
void from_json(const json & j, Config & x);
void to_json(json & j, const Config & x);
inline void from_json(const json & j, Config& x) {
x.remoteRepoEndpoint = j.at("remoteRepoEndpoint").get<std::string>();
x.remoteRepoName = j.at("remoteRepoName").get<std::string>();
}
inline void to_json(json & j, const Config & x) {
j = json::object();
j["remoteRepoEndpoint"] = x.remoteRepoEndpoint;
j["remoteRepoName"] = x.remoteRepoName;
}
}
}
}
// clang-format on

View File

@ -0,0 +1,42 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// helper.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <nlohmann/json.hpp>
#include <sstream>
namespace linglong {
namespace builder {
namespace config {
using nlohmann::json;
#ifndef NLOHMANN_UNTYPED_linglong_builder_config_HELPER
#define NLOHMANN_UNTYPED_linglong_builder_config_HELPER
inline json get_untyped(const json & j, const char * property) {
if (j.find(property) != j.end()) {
return j.at(property).get<json>();
}
return json();
}
inline json get_untyped(const json & j, std::string property) {
return get_untyped(j, property.data());
}
#endif
}
}
}
// clang-format on

View File

@ -0,0 +1,33 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Base.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Base {
std::string id;
std::optional<std::string> version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,35 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Build.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
#include "linglong/builder/project/Manual.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Build {
std::string kind;
std::optional<Manual> manual;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,34 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Depend.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Depend {
std::string id;
std::optional<std::string> type;
std::optional<std::string> version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,215 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Generators.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
#include "linglong/builder/project/Project.hpp"
#include "linglong/builder/project/Source.hpp"
#include "linglong/builder/project/Runtime.hpp"
#include "linglong/builder/project/Package.hpp"
#include "linglong/builder/project/Depend.hpp"
#include "linglong/builder/project/Build.hpp"
#include "linglong/builder/project/Manual.hpp"
#include "linglong/builder/project/Base.hpp"
namespace linglong {
namespace builder {
namespace project {
void from_json(const json & j, Base & x);
void to_json(json & j, const Base & x);
void from_json(const json & j, Manual & x);
void to_json(json & j, const Manual & x);
void from_json(const json & j, Build & x);
void to_json(json & j, const Build & x);
void from_json(const json & j, Depend & x);
void to_json(json & j, const Depend & x);
void from_json(const json & j, Package & x);
void to_json(json & j, const Package & x);
void from_json(const json & j, Runtime & x);
void to_json(json & j, const Runtime & x);
void from_json(const json & j, Source & x);
void to_json(json & j, const Source & x);
void from_json(const json & j, Project & x);
void to_json(json & j, const Project & x);
inline void from_json(const json & j, Base& x) {
x.id = j.at("id").get<std::string>();
x.version = get_stack_optional<std::string>(j, "version");
}
inline void to_json(json & j, const Base & x) {
j = json::object();
j["id"] = x.id;
if (x.version) {
j["version"] = x.version;
}
}
inline void from_json(const json & j, Manual& x) {
x.build = get_stack_optional<std::string>(j, "build");
x.configure = get_stack_optional<std::string>(j, "configure");
x.install = get_stack_optional<std::string>(j, "install");
}
inline void to_json(json & j, const Manual & x) {
j = json::object();
if (x.build) {
j["build"] = x.build;
}
if (x.configure) {
j["configure"] = x.configure;
}
if (x.install) {
j["install"] = x.install;
}
}
inline void from_json(const json & j, Build& x) {
x.kind = j.at("kind").get<std::string>();
x.manual = get_stack_optional<Manual>(j, "manual");
}
inline void to_json(json & j, const Build & x) {
j = json::object();
j["kind"] = x.kind;
if (x.manual) {
j["manual"] = x.manual;
}
}
inline void from_json(const json & j, Depend& x) {
x.id = j.at("id").get<std::string>();
x.type = get_stack_optional<std::string>(j, "type");
x.version = get_stack_optional<std::string>(j, "version");
}
inline void to_json(json & j, const Depend & x) {
j = json::object();
j["id"] = x.id;
if (x.type) {
j["type"] = x.type;
}
if (x.version) {
j["version"] = x.version;
}
}
inline void from_json(const json & j, Package& x) {
x.description = j.at("description").get<std::string>();
x.id = j.at("id").get<std::string>();
x.kind = j.at("kind").get<std::string>();
x.name = j.at("name").get<std::string>();
x.version = j.at("version").get<std::string>();
}
inline void to_json(json & j, const Package & x) {
j = json::object();
j["description"] = x.description;
j["id"] = x.id;
j["kind"] = x.kind;
j["name"] = x.name;
j["version"] = x.version;
}
inline void from_json(const json & j, Runtime& x) {
x.id = j.at("id").get<std::string>();
x.version = get_stack_optional<std::string>(j, "version");
}
inline void to_json(json & j, const Runtime & x) {
j = json::object();
j["id"] = x.id;
if (x.version) {
j["version"] = x.version;
}
}
inline void from_json(const json & j, Source& x) {
x.commit = get_stack_optional<std::string>(j, "commit");
x.digest = get_stack_optional<std::string>(j, "digest");
x.kind = j.at("kind").get<std::string>();
x.patch = get_stack_optional<std::vector<std::string>>(j, "patch");
x.url = get_stack_optional<std::string>(j, "url");
x.version = get_stack_optional<std::string>(j, "version");
}
inline void to_json(json & j, const Source & x) {
j = json::object();
if (x.commit) {
j["commit"] = x.commit;
}
if (x.digest) {
j["digest"] = x.digest;
}
j["kind"] = x.kind;
if (x.patch) {
j["patch"] = x.patch;
}
if (x.url) {
j["url"] = x.url;
}
if (x.version) {
j["version"] = x.version;
}
}
inline void from_json(const json & j, Project& x) {
x.base = get_stack_optional<Base>(j, "base");
x.build = j.at("build").get<Build>();
x.depends = get_stack_optional<std::vector<Depend>>(j, "depends");
x.environment = get_stack_optional<std::map<std::string, std::string>>(j, "environment");
x.package = j.at("package").get<Package>();
x.runtime = get_stack_optional<Runtime>(j, "runtime");
x.source = j.at("source").get<Source>();
x.variables = get_stack_optional<std::map<std::string, std::string>>(j, "variables");
x.version = j.at("version").get<std::string>();
}
inline void to_json(json & j, const Project & x) {
j = json::object();
if (x.base) {
j["base"] = x.base;
}
j["build"] = x.build;
if (x.depends) {
j["depends"] = x.depends;
}
if (x.environment) {
j["environment"] = x.environment;
}
j["package"] = x.package;
if (x.runtime) {
j["runtime"] = x.runtime;
}
j["source"] = x.source;
if (x.variables) {
j["variables"] = x.variables;
}
j["version"] = x.version;
}
}
}
}
// clang-format on

View File

@ -0,0 +1,34 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Manual.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Manual {
std::optional<std::string> build;
std::optional<std::string> configure;
std::optional<std::string> install;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,36 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Package.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Package {
std::string description;
std::string id;
std::string kind;
std::string name;
std::string version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,47 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Project.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
#include "linglong/builder/project/Base.hpp"
#include "linglong/builder/project/Build.hpp"
#include "linglong/builder/project/Depend.hpp"
#include "linglong/builder/project/Package.hpp"
#include "linglong/builder/project/Runtime.hpp"
#include "linglong/builder/project/Source.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Project {
std::optional<Base> base;
Build build;
std::optional<std::vector<Depend>> depends;
std::optional<std::map<std::string, std::string>> environment;
Package package;
std::optional<Runtime> runtime;
Source source;
std::optional<std::map<std::string, std::string>> variables;
std::string version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,33 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Runtime.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Runtime {
std::string id;
std::optional<std::string> version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,37 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// Source.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include "linglong/builder/project/helper.hpp"
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
struct Source {
std::optional<std::string> commit;
std::optional<std::string> digest;
std::string kind;
std::optional<std::vector<std::string>> patch;
std::optional<std::string> url;
std::optional<std::string> version;
};
}
}
}
// clang-format on

View File

@ -0,0 +1,99 @@
// Thish file is generated by /tools/run-quicktype.sh
// DO NOT EDIT IT.
// clang-format off
// To parse this JSON data, first install
//
// json.hpp https://github.com/nlohmann/json
//
// Then include this file, and then do
//
// helper.hpp data = nlohmann::json::parse(jsonString);
#pragma once
#include <optional>
#include <nlohmann/json.hpp>
#include <sstream>
namespace linglong {
namespace builder {
namespace project {
using nlohmann::json;
#ifndef NLOHMANN_UNTYPED_linglong_builder_project_HELPER
#define NLOHMANN_UNTYPED_linglong_builder_project_HELPER
inline json get_untyped(const json & j, const char * property) {
if (j.find(property) != j.end()) {
return j.at(property).get<json>();
}
return json();
}
inline json get_untyped(const json & j, std::string property) {
return get_untyped(j, property.data());
}
#endif
#ifndef NLOHMANN_OPTIONAL_linglong_builder_project_HELPER
#define NLOHMANN_OPTIONAL_linglong_builder_project_HELPER
template <typename T>
inline std::shared_ptr<T> get_heap_optional(const json & j, const char * property) {
auto it = j.find(property);
if (it != j.end() && !it->is_null()) {
return j.at(property).get<std::shared_ptr<T>>();
}
return std::shared_ptr<T>();
}
template <typename T>
inline std::shared_ptr<T> get_heap_optional(const json & j, std::string property) {
return get_heap_optional<T>(j, property.data());
}
template <typename T>
inline std::optional<T> get_stack_optional(const json & j, const char * property) {
auto it = j.find(property);
if (it != j.end() && !it->is_null()) {
return j.at(property).get<std::optional<T>>();
}
return std::optional<T>();
}
template <typename T>
inline std::optional<T> get_stack_optional(const json & j, std::string property) {
return get_stack_optional<T>(j, property.data());
}
#endif
}
}
}
#ifndef NLOHMANN_OPT_HELPER
#define NLOHMANN_OPT_HELPER
namespace nlohmann {
template <typename T>
struct adl_serializer<std::shared_ptr<T>> {
static void to_json(json & j, const std::shared_ptr<T> & opt) {
if (!opt) j = nullptr; else j = *opt;
}
static std::shared_ptr<T> from_json(const json & j) {
if (j.is_null()) return std::make_shared<T>(); else return std::make_shared<T>(j.get<T>());
}
};
template <typename T>
struct adl_serializer<std::optional<T>> {
static void to_json(json & j, const std::optional<T> & opt) {
if (!opt) j = nullptr; else j = *opt;
}
static std::optional<T> from_json(const json & j) {
if (j.is_null()) return std::make_optional<T>(); else return std::make_optional<T>(j.get<T>());
}
};
}
#endif
// clang-format on

1
tools/quicktype Submodule

@ -0,0 +1 @@
Subproject commit 69d1574e5068f2f54a2e9a2dd952fab8b8106240

118
tools/run-quicktype.sh Executable file
View File

@ -0,0 +1,118 @@
#!/bin/bash
set -e
set -o pipefail
GIT=${GIT:="git"}
repoRoot="$("$GIT" rev-parse --show-toplevel)"
cd "$repoRoot/tools"
git submodule update --init --depth 1
QUICKTYPE=${QUICKTYPE:=""}
if [ -z "$QUICKTYPE" ]; then
pushd quicktype
npm i
npm run build
popd
fi
quicktype() {
if [ -z "$QUICKTYPE" ]; then
pushd quicktype
npx quicktype "$@"
popd
else
exec $QUICKTYPE "$@"
fi
}
generate() {
schema="$1"
shift
toplevel_type="$1"
shift
namespace="$1"
shift
include="$1"
shift
output_path="$1"
if [[ ! -f "$schema" ]]; then
echo "$schema not found" || exit 255
fi
filename="/dev/null"
while read -r line; do
if [[ $line != //\ stdout &&
$line != //*.hpp &&
$line != \#include\ \"*\" ]]; then
echo "$line" >>"$filename"
continue
fi
if [[ $line == \#include\ \"*\" ]]; then
header=${line#\#include\ \"}
header=${header%\"}
printf "#include \"%s/%s\"\n" \
"$output_path" \
"$header" \
>>"$filename"
continue
fi
echo "// clang-format on" >>"$filename"
filename="${repoRoot}/$include/$output_path/${line#\/\/ }"
if [[ $line == //\ stdout ]]; then
filename="/dev/null"
fi
# echo "generating $filename"
mkdir -p "$(dirname "$filename")"
{
echo "// Thish file is generated by /tools/run-quicktype.sh"
echo "// DO NOT EDIT IT."
echo ""
echo "// clang-format off"
} >"$filename"
done < <(quicktype "$schema" \
--lang c++ \
-s schema \
-t "$toplevel_type" \
--namespace "$namespace" \
--code-format with-struct \
--source-style multi-source \
--include-location global-include \
--type-style pascal-case-upper-acronyms \
--member-style camel-case-upper-acronyms \
--enumerator-style pascal-case-upper-acronyms \
--no-boost \
--hide-null-optional)
{
echo ""
echo "// clang-format on"
} >>"$filename"
}
include="src/"
generate \
"$repoRoot/api/builder/project.schema.json" \
Project \
"linglong::builder::project" \
"$include" \
"linglong/builder/project"
generate \
"$repoRoot/api/builder/config.schema.json" \
Config \
"linglong::builder::config" \
"$include" \
"linglong/builder/config"