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) ...@@ -903,6 +903,26 @@ Compiler::Impl::Impl(AnnotationFlag annotationFlag)
: annotationFlag(annotationFlag), finalLoader(*this), workspace(*this) { : annotationFlag(annotationFlag), finalLoader(*this), workspace(*this) {
// Reflectively interpret the members of Declaration.body. Any member prefixed by "builtin" // Reflectively interpret the members of Declaration.body. Any member prefixed by "builtin"
// defines a builtin declaration visible in the global scope. // 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 = StructSchema::Union declBodySchema =
Schema::from<Declaration>().getMemberByName("body").asUnion(); Schema::from<Declaration>().getMemberByName("body").asUnion();
for (auto member: declBodySchema.getMembers()) { for (auto member: declBodySchema.getMembers()) {
...@@ -913,6 +933,7 @@ Compiler::Impl::Impl(AnnotationFlag annotationFlag) ...@@ -913,6 +933,7 @@ Compiler::Impl::Impl(AnnotationFlag annotationFlag)
symbolName, static_cast<Declaration::Body::Which>(member.getIndex())); symbolName, static_cast<Declaration::Body::Which>(member.getIndex()));
} }
} }
#endif
} }
Compiler::Impl::~Impl() noexcept(false) {} Compiler::Impl::~Impl() noexcept(false) {}
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "node-translator.h" #include "node-translator.h"
#include "parser.h" // only for generateChildId() #include "parser.h" // only for generateGroupId()
#include <kj/debug.h> #include <kj/debug.h>
#include <kj/arena.h> #include <kj/arena.h>
#include <set> #include <set>
...@@ -906,6 +906,7 @@ public: ...@@ -906,6 +906,7 @@ public:
case Declaration::Body::GROUP_DECL: case Declaration::Body::GROUP_DECL:
member->setDiscriminantOffsetInSchema(); // in case it contains an unnamed union member->setDiscriminantOffsetInSchema(); // in case it contains an unnamed union
member->node.setId(generateGroupId(member->parent->node.getId(), member->index));
targetsFlagName = "targetsGroup"; targetsFlagName = "targetsGroup";
break; break;
...@@ -964,6 +965,9 @@ private: ...@@ -964,6 +965,9 @@ private:
uint codeOrder; uint codeOrder;
// Code order within the parent. // Code order within the parent.
uint index = 0;
// Index within the parent.
uint childCount = 0; uint childCount = 0;
// Number of children this member has. // Number of children this member has.
...@@ -1017,6 +1021,7 @@ private: ...@@ -1017,6 +1021,7 @@ private:
KJ_IF_MAYBE(result, schema) { KJ_IF_MAYBE(result, schema) {
return *result; return *result;
} else { } else {
index = parent->childInitializedCount;
auto builder = parent->addMemberSchema(); auto builder = parent->addMemberSchema();
if (isInUnion) { if (isInUnion) {
builder.setDiscriminantValue(parent->unionDiscriminantCount++); builder.setDiscriminantValue(parent->unionDiscriminantCount++);
...@@ -1189,7 +1194,7 @@ private: ...@@ -1189,7 +1194,7 @@ private:
.newOrphan<schema2::Node>(); .newOrphan<schema2::Node>();
auto node = orphan.get(); auto node = orphan.get();
node.setId(generateChildId(parent.getId(), name)); // We'll set the ID later.
node.setDisplayName(kj::str(parent.getDisplayName(), '.', name)); node.setDisplayName(kj::str(parent.getDisplayName(), '.', name));
node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size()); node.setDisplayNamePrefixLength(node.getDisplayName().size() - name.size());
node.setScopeId(parent.getId()); node.setScopeId(parent.getId());
......
...@@ -70,6 +70,31 @@ uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) { ...@@ -70,6 +70,31 @@ uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName) {
return result | (1ull << 63); 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, void parseFile(List<Statement>::Reader statements, ParsedFile::Builder result,
const ErrorReporter& errorReporter) { const ErrorReporter& errorReporter) {
CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter); CapnpParser parser(Orphanage::getForMessageContaining(result), errorReporter);
...@@ -858,6 +883,8 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep ...@@ -858,6 +883,8 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
DynamicStruct::Builder dynamicBuilder = builder; DynamicStruct::Builder dynamicBuilder = builder;
for (auto& maybeTarget: targets.value) { for (auto& maybeTarget: targets.value) {
KJ_IF_MAYBE(target, maybeTarget) { KJ_IF_MAYBE(target, maybeTarget) {
#warning "temporary hack for schema transition"
#if 0
if (target->value == "*") { if (target->value == "*") {
// Set all. // Set all.
if (targets.value.size() > 1) { if (targets.value.size() > 1) {
...@@ -892,6 +919,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep ...@@ -892,6 +919,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
} }
} }
} }
#endif
} }
} }
return DeclParserResult(kj::mv(decl)); return DeclParserResult(kj::mv(decl));
......
...@@ -45,8 +45,11 @@ uint64_t generateRandomId(); ...@@ -45,8 +45,11 @@ uint64_t generateRandomId();
uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName); uint64_t generateChildId(uint64_t parentId, kj::StringPtr childName);
// Generate the ID for a child node given its parent ID and name. // 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 { class CapnpParser {
// Advanced parser interface. This interface exposes the inner parsers so that you can embed // 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 ...@@ -858,7 +858,7 @@ DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name, uint size
return init(schema.getFieldByName(name), size); return init(schema.getFieldByName(name), size);
} }
void DynamicStruct::Builder::clear(kj::StringPtr name) { void DynamicStruct::Builder::clear(kj::StringPtr name) {
return clear(schema.getFieldByName(name)); clear(schema.getFieldByName(name));
} }
DynamicStruct::Builder DynamicStruct::Builder::getObject( DynamicStruct::Builder DynamicStruct::Builder::getObject(
kj::StringPtr name, StructSchema type) { kj::StringPtr name, StructSchema type) {
...@@ -1332,16 +1332,22 @@ Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) { ...@@ -1332,16 +1332,22 @@ Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) {
template <> template <>
DynamicStruct::Reader MessageReader::getRoot<DynamicStruct>(StructSchema schema) { 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()); return DynamicStruct::Reader(schema, getRootInternal());
} }
template <> template <>
DynamicStruct::Builder MessageBuilder::initRoot<DynamicStruct>(StructSchema schema) { 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))); return DynamicStruct::Builder(schema, initRoot(structSizeFromSchema(schema)));
} }
template <> template <>
DynamicStruct::Builder MessageBuilder::getRoot<DynamicStruct>(StructSchema schema) { 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))); return DynamicStruct::Builder(schema, getRoot(structSizeFromSchema(schema)));
} }
...@@ -1349,19 +1355,27 @@ namespace _ { // private ...@@ -1349,19 +1355,27 @@ namespace _ { // private
DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic( DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructReader reader, WirePointerCount index, StructSchema schema) { 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)); return DynamicStruct::Reader(schema, reader.getStructField(index, nullptr));
} }
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic( DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::getDynamic(
StructBuilder builder, WirePointerCount index, StructSchema schema) { StructBuilder builder, WirePointerCount index, StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
return DynamicStruct::Builder(schema, builder.getStructField( return DynamicStruct::Builder(schema, builder.getStructField(
index, structSizeFromSchema(schema), nullptr)); index, structSizeFromSchema(schema), nullptr));
} }
void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set( void PointerHelpers<DynamicStruct, Kind::UNKNOWN>::set(
StructBuilder builder, WirePointerCount index, const DynamicStruct::Reader& value) { 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); builder.setStructField(index, value.reader);
} }
DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::init( DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::UNKNOWN>::init(
StructBuilder builder, WirePointerCount index, StructSchema schema) { StructBuilder builder, WirePointerCount index, StructSchema schema) {
KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(),
"Cannot form pointer to group type.");
return DynamicStruct::Builder(schema, return DynamicStruct::Builder(schema,
builder.initStructField(index, structSizeFromSchema(schema))); builder.initStructField(index, structSizeFromSchema(schema)));
} }
......
...@@ -167,6 +167,7 @@ struct RawSchema { ...@@ -167,6 +167,7 @@ struct RawSchema {
uint16_t value; uint16_t value;
inline operator uint16_t() const { return value; } inline operator uint16_t() const { return value; }
MemberInfo() = default;
constexpr MemberInfo(uint16_t value): value(value) {} constexpr MemberInfo(uint16_t value): value(value) {}
constexpr MemberInfo(uint16_t value, uint16_t dummy): value(value) {} constexpr MemberInfo(uint16_t value, uint16_t dummy): value(value) {}
}; };
......
...@@ -234,7 +234,7 @@ template <typename Reader> ...@@ -234,7 +234,7 @@ template <typename Reader>
void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer); 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 // 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, // 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> template <typename Type>
static typename Type::Reader defaultValue(); static typename Type::Reader defaultValue();
...@@ -332,7 +332,7 @@ private: ...@@ -332,7 +332,7 @@ private:
class FlatMessageBuilder: public MessageBuilder { class FlatMessageBuilder: public MessageBuilder {
// A message builder implementation which allocates from a single flat array, throwing an // 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: public:
explicit FlatMessageBuilder(kj::ArrayPtr<word> array); explicit FlatMessageBuilder(kj::ArrayPtr<word> array);
......
This diff is collapsed.
...@@ -31,6 +31,16 @@ ...@@ -31,6 +31,16 @@
namespace capnp { namespace capnp {
class SchemaLoader { 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: public:
class LazyLoadCallback { class LazyLoadCallback {
public: 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