| // Copyright 2019 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. |
| |
| #ifndef SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_ |
| #define SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_ |
| |
| #include "src/lib/fidl_codec/visitor.h" |
| #include "src/lib/fidl_codec/wire_object.h" |
| #include "src/lib/fidl_codec/wire_types.h" |
| |
| namespace fidl_codec { |
| |
| class JsonVisitor : public Visitor { |
| public: |
| JsonVisitor(rapidjson::Value* result, rapidjson::Document::AllocatorType* allocator) |
| : result_(result), allocator_(allocator) {} |
| |
| private: |
| void VisitValue(const Value* node, const Type* for_type) override { |
| std::stringstream ss; |
| PrettyPrinter printer(ss, WithoutColors, false, "", 0, /*header_on_every_line=*/false); |
| node->PrettyPrint(for_type, printer); |
| result_->SetString(ss.str(), *allocator_); |
| } |
| |
| void VisitInvalidValue(const InvalidValue* node, const Type* for_type) override { |
| result_->SetString("(invalid)", *allocator_); |
| } |
| |
| void VisitNullValue(const NullValue* node, const Type* for_type) override { result_->SetNull(); } |
| |
| void VisitStringValue(const StringValue* node, const Type* for_type) override { |
| result_->SetString(node->string().data(), |
| static_cast<rapidjson::SizeType>(node->string().size()), *allocator_); |
| } |
| |
| void VisitUnionValue(const UnionValue* node, const Type* for_type) override { |
| result_->SetObject(); |
| rapidjson::Value key; |
| key.SetString(node->member().name().c_str(), *allocator_); |
| result_->AddMember(key, rapidjson::Value(), *allocator_); |
| JsonVisitor visitor(&(*result_)[node->member().name().c_str()], allocator_); |
| node->value()->Visit(&visitor, node->member().type()); |
| } |
| |
| void VisitStructValue(const StructValue* node, const Type* for_type) override { |
| result_->SetObject(); |
| for (const auto& member : node->struct_definition().members()) { |
| auto it = node->fields().find(member.get()); |
| if (it == node->fields().end()) |
| continue; |
| rapidjson::Value key; |
| key.SetString(member->name().c_str(), *allocator_); |
| result_->AddMember(key, rapidjson::Value(), *allocator_); |
| JsonVisitor visitor(&(*result_)[member->name().c_str()], allocator_); |
| it->second->Visit(&visitor, member->type()); |
| } |
| } |
| |
| void VisitVectorValue(const VectorValue* node, const Type* for_type) override { |
| FX_DCHECK(for_type != nullptr); |
| const Type* component_type = for_type->GetComponentType(); |
| FX_DCHECK(component_type != nullptr); |
| result_->SetArray(); |
| for (const auto& value : node->values()) { |
| rapidjson::Value element; |
| JsonVisitor visitor(&element, allocator_); |
| value->Visit(&visitor, component_type); |
| result_->PushBack(element, *allocator_); |
| } |
| } |
| |
| void VisitTableValue(const TableValue* node, const Type* for_type) override { |
| result_->SetObject(); |
| for (const auto& member : node->table_definition().members()) { |
| if ((member != nullptr) && !member->reserved()) { |
| auto it = node->members().find(member.get()); |
| if ((it == node->members().end()) || (it->second == nullptr) || it->second->IsNull()) |
| continue; |
| rapidjson::Value key; |
| key.SetString(member->name().c_str(), *allocator_); |
| result_->AddMember(key, rapidjson::Value(), *allocator_); |
| JsonVisitor visitor(&(*result_)[member->name().c_str()], allocator_); |
| it->second->Visit(&visitor, member->type()); |
| } |
| } |
| } |
| |
| private: |
| rapidjson::Value* result_; |
| rapidjson::Document::AllocatorType* allocator_; |
| }; |
| |
| } // namespace fidl_codec |
| |
| #endif // SRC_LIB_FIDL_CODEC_JSON_VISITOR_H_ |