text: // 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_VISITOR_H_
  #define 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 {
  
  // Superclass for implementing visitors for Values. Note that the whole class is protected. To use a
  // visitor, use the Visit method on the Value object you want to visit.
  class Visitor {
   protected:
    virtual void VisitValue(const Value* node, const Type* for_type) {}
    virtual void VisitInvalidValue(const InvalidValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitNullValue(const NullValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitRawValue(const RawValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitBoolValue(const BoolValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitIntegerValue(const IntegerValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitActualAndRequestedValue(const ActualAndRequestedValue* node,
                                              const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitDoubleValue(const DoubleValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitStringValue(const StringValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitHandleValue(const HandleValue* node, const Type* for_type) {
      VisitValue(node, for_type);
    }
    virtual void VisitUnionValue(const UnionValue* node, const Type* for_type) {
      node->value()->Visit(this, node->member().type());
    }
    virtual void VisitStructValue(const StructValue* node, const Type* for_type) {
      for (const auto& field : node->fields()) {
        field.second->Visit(this, field.first->type());
      }
    }
    virtual void VisitVectorValue(const VectorValue* node, const Type* for_type) {
      FX_DCHECK(for_type != nullptr);
      const Type* component_type = for_type->GetComponentType();
      FX_DCHECK(component_type != nullptr);
      for (const auto& value : node->values()) {
        value->Visit(this, component_type);
      }
    }
    virtual void VisitTableValue(const TableValue* node, const Type* for_type) {
      for (const auto& member : node->members()) {
        member.second->Visit(this, member.first->type());
      }
    }
    virtual void VisitFidlMessageValue(const FidlMessageValue* node, const Type* for_type) {
      if (node->decoded_request() != nullptr) {
        node->decoded_request()->Visit(this, nullptr);
      }
      if (node->decoded_response() != nullptr) {
        node->decoded_response()->Visit(this, nullptr);
      }
    }
  
    friend class Value;
    friend class InvalidValue;
    friend class NullValue;
    friend class RawValue;
    friend class BoolValue;
    friend class IntegerValue;
    friend class ActualAndRequestedValue;
    friend class DoubleValue;
    friend class StringValue;
    friend class HandleValue;
    friend class UnionValue;
    friend class StructValue;
    friend class VectorValue;
    friend class TableValue;
    friend class FidlMessageValue;
  };
  
  }  // namespace fidl_codec
  
  #endif  // SRC_LIB_FIDL_CODEC_VISITOR_H_
  