Commit 1dcb66b1 authored by Kenton Varda's avatar Kenton Varda

Continuing schema rewrite WIP.

parent 863afbe2
......@@ -903,6 +903,26 @@ Compiler::Impl::Impl(AnnotationFlag annotationFlag)
: annotationFlag(annotationFlag), finalLoader(*this), workspace(*this) {
// Reflectively interpret the members of Declaration.body. Any member prefixed by "builtin"
// defines a builtin declaration visible in the global scope.
#warning "temporary hack for schema transition"
builtinDecls["Void"] = nodeArena.allocateOwn<Node>("Void", Declaration::Body::BUILTIN_VOID);
builtinDecls["Bool"] = nodeArena.allocateOwn<Node>("Bool", Declaration::Body::BUILTIN_BOOL);
builtinDecls["Int8"] = nodeArena.allocateOwn<Node>("Int8", Declaration::Body::BUILTIN_INT8);
builtinDecls["Int16"] = nodeArena.allocateOwn<Node>("Int16", Declaration::Body::BUILTIN_INT16);
builtinDecls["Int32"] = nodeArena.allocateOwn<Node>("Int32", Declaration::Body::BUILTIN_INT32);
builtinDecls["Int64"] = nodeArena.allocateOwn<Node>("Int64", Declaration::Body::BUILTIN_INT64);
builtinDecls["UInt8"] = nodeArena.allocateOwn<Node>("UInt8", Declaration::Body::BUILTIN_U_INT8);
builtinDecls["UInt16"] = nodeArena.allocateOwn<Node>("UInt16", Declaration::Body::BUILTIN_U_INT16);
builtinDecls["UInt32"] = nodeArena.allocateOwn<Node>("UInt32", Declaration::Body::BUILTIN_U_INT32);
builtinDecls["UInt64"] = nodeArena.allocateOwn<Node>("UInt64", Declaration::Body::BUILTIN_U_INT64);
builtinDecls["Float32"] = nodeArena.allocateOwn<Node>("Float32", Declaration::Body::BUILTIN_FLOAT32);
builtinDecls["Float64"] = nodeArena.allocateOwn<Node>("Float64", Declaration::Body::BUILTIN_FLOAT64);
builtinDecls["Text"] = nodeArena.allocateOwn<Node>("Text", Declaration::Body::BUILTIN_TEXT);
builtinDecls["Data"] = nodeArena.allocateOwn<Node>("Data", Declaration::Body::BUILTIN_DATA);
builtinDecls["List"] = nodeArena.allocateOwn<Node>("List", Declaration::Body::BUILTIN_LIST);
builtinDecls["Object"] = nodeArena.allocateOwn<Node>("Object", Declaration::Body::BUILTIN_OBJECT);
#if 0
StructSchema::Union declBodySchema =
Schema::from<Declaration>().getMemberByName("body").asUnion();
for (auto member: declBodySchema.getMembers()) {
......@@ -913,6 +933,7 @@ Compiler::Impl::Impl(AnnotationFlag annotationFlag)
symbolName, static_cast<Declaration::Body::Which>(member.getIndex()));
}
}
#endif
}
Compiler::Impl::~Impl() noexcept(false) {}
......
......@@ -22,7 +22,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "node-translator.h"
#include "parser.h" // only for generateChildId()
#include "parser.h" // only for generateGroupId()
#include <kj/debug.h>
#include <kj/arena.h>
#include <set>
......@@ -906,6 +906,7 @@ public:
case Declaration::Body::GROUP_DECL:
member->setDiscriminantOffsetInSchema(); // in case it contains an unnamed union
member->node.setId(generateGroupId(member->parent->node.getId(), member->index));
targetsFlagName = "targetsGroup";
break;
......@@ -964,6 +965,9 @@ private:
uint codeOrder;
// Code order within the parent.
uint index = 0;
// Index within the parent.
uint childCount = 0;
// Number of children this member has.
......@@ -1017,6 +1021,7 @@ private:
KJ_IF_MAYBE(result, schema) {
return *result;
} else {
index = parent->childInitializedCount;
auto builder = parent->addMemberSchema();
if (isInUnion) {
builder.setDiscriminantValue(parent->unionDiscriminantCount++);
......@@ -1189,7 +1194,7 @@ private:
.newOrphan<schema2::Node>();
auto node = orphan.get();
node.setId(generateChildId(parent.getId(), name));
// We'll set the ID later.
node.setDisplayName(kj::str(parent.getDisplayName(), '.', name));
node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size());
node.setScopeId(parent.getId());
......
......@@ -70,6 +70,31 @@ uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) {
return result | (1ull << 63);
}
uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex) {
// Compute ID by MD5 hashing the concatenation of the parent ID and the group index, and
// then taking the first 8 bytes.
kj::byte bytes[sizeof(uint64_t) + sizeof(uint16_t)];
for (uint i = 0; i < sizeof(uint64_t); i++) {
bytes[i] = (parentId >> (i * 8)) & 0xff;
}
for (uint i = 0; i < sizeof(uint16_t); i++) {
bytes[sizeof(uint64_t) + i] = (groupIndex >> (i * 8)) & 0xff;
}
Md5 md5;
md5.update(bytes);
kj::ArrayPtr<const kj::byte> resultBytes = md5.finish();
uint64_t result = 0;
for (uint i = 0; i < sizeof(uint64_t); i++) {
result = (result << 8) | resultBytes[i];
}
return result | (1ull << 63);
}
void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
const ErrorReporter& errorReporter) {
CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);
......@@ -858,6 +883,8 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
DynamicStruct::Builder dynamicBuilder = builder;
for (auto& maybeTarget: targets.value) {
KJ_IF_MAYBE(target, maybeTarget) {
#warning "temporary hack for schema transition"
#if 0
if (target->value == "*") {
// Set all.
if (targets.value.size() > 1) {
......@@ -892,6 +919,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
}
}
}
#endif
}
}
return DeclParserResult(kj::mv(decl));
......
......@@ -45,8 +45,11 @@ uint64_t generateRandomId();
uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName);
// Generate the ID for a child node given its parent ID and name.
uint64_t generateGroupId(uint64_t parentId, uint16_t groupIndex);
// Generate the ID for a group within a struct.
//
// TODO(cleanup): Move generateRandomId() and generateChildId() somewhere more sensible.
// TODO(cleanup): Move generate*Id() somewhere more sensible.
class CapnpParser {
// Advanced parser interface. This interface exposes the inner parsers so that you can embed
......
......@@ -858,7 +858,7 @@ DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name, uint size
return init(schema.getFieldByName(name), size);
}
void DynamicStruct::Builder::clear(kj::StringPtr name) {
return clear(schema.getFieldByName(name));
clear(schema.getFieldByName(name));
}
DynamicStruct::Builder DynamicStruct::Builder::getObject(
kj::StringPtr name, StructSchema type) {
......@@ -1332,16 +1332,22 @@ Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) {
template <>
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Can't use group type as the root of a message.");
return DynamicStruct::Reader(schema, getRootInternal());
}
template <>
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Can't use group type as the root of a message.");
return DynamicStruct::Builder(schema, initRoot(structSizeFromSchema(schema)));
}
template <>
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Can't use group type as the root of a message.");
return DynamicStruct::Builder(schema, getRoot(structSizeFromSchema(schema)));
}
......@@ -1349,19 +1355,27 @@ namespace _ { // private
DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructReader reader, WirePointerCount index, StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
return DynamicStruct::Reader(schema, reader.getStructField(index, nullptr));
}
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructBuilder builder, WirePointerCount index, StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
return DynamicStruct::Builder(schema, builder.getStructField(
index, structSizeFromSchema(schema), nullptr));
}
void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set(
StructBuilder builder, WirePointerCount index, const DynamicStruct::Reader& value) {
KJ_REQUIRE(!value.schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
builder.setStructField(index, value.reader);
}
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::init(
StructBuilder builder, WirePointerCount index, StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
return DynamicStruct::Builder(schema,
builder.initStructField(index, structSizeFromSchema(schema)));
}
......
......@@ -167,6 +167,7 @@ struct RawSchema {
uint16_t value;
inline operator uint16_t() const { return value; }
MemberInfo() = default;
constexpr MemberInfo(uint16_t value): value(value) {}
constexpr MemberInfo(uint16_t value, uint16_t dummy): value(value) {}
};
......
......@@ -234,7 +234,7 @@ template <typename Reader>
void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer);
// Copy the content of the given reader into the given buffer, such that it can safely be passed to
// readMessageUnchecked(). The buffer's size must be exactly reader.totalSizeInWords() + 1,
// otherwise an exception will be thrown.
// otherwise an exception will be thrown. The buffer must be zero'd before calling.
template <typename Type>
static typename Type::Reader defaultValue();
......@@ -332,7 +332,7 @@ private:
class FlatMessageBuilder: public MessageBuilder {
// A message builder implementation which allocates from a single flat array, throwing an
// exception if it runs out of space.
// exception if it runs out of space. The array must be zero'd before use.
public:
explicit FlatMessageBuilder(kj::ArrayPtr<word> array);
......
This diff is collapsed.
......@@ -31,6 +31,16 @@
namespace capnp {
class SchemaLoader {
// Class which can be used to construct Schema objects from schema::Nodes as defined in
// schema.capnp.
//
// It is a bad idea to use this class on untrusted input with exceptions disabled -- you may
// be exposing yourself to denial-of-service attacks, as attackers can easily construct schemas
// that are subtly inconsistent in a way that causes exceptions to be thrown either by
// SchemaLoader or by the dynamic API when the schemas are subsequently used. If you enable and
// properly catch exceptions, you should be OK -- assuming no bugs in the Cap'n Proto
// implementation, of course.
public:
class LazyLoadCallback {
public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment